From db5bc1c7d00571feb8d4858d505326c845ded7da Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 15 Dec 2023 15:19:52 +0100 Subject: [PATCH 001/106] Added declarations and r-type definition with assert helper --- src/coreclr/jit/emitriscv64.cpp | 29 +++++++++++++++++++++++++++++ src/coreclr/jit/emitriscv64.h | 7 +++++++ 2 files changed, 36 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 038abec3f654fb..8cfb5dab0d4165 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2127,6 +2127,35 @@ void emitter::emitJumpDistBind() return sizeof(code_t); } +static void assertCodeLength(unsigned code, uint8_t size) +{ +#ifdef DEBUG + assert(code < (1u << size)); +#endif // DEBUG +} + +/***************************************************************************** + * + * Emit a 32-bit RISCV64 R-Type instruction + * + * Note: Instruction types as per RISC-V Spec, Chapter 24 RV32/64G Instruction Set Listings + * R-Type layout: + * 31-------25-24---20-19--15-14------12-11-----------7-6------------0 + * | funct7 | rs2 | rs1 | funct3 | rd | opcode | + * ------------------------------------------------------------------- + */ + +/*static*/ code_t emitter::insEncodeRTypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned rs2, unsigned funct7) const +{ + assertCodeLength(opcode, 7); + assertCodeLength(rd, 5); + assertCodeLength(funct3, 3); + assertCodeLength(rs1, 5); + assertCodeLength(rs2, 5); + assertCodeLength(funct7, 7); + return opcode | (rd << 7) | (funct3 << 12) | (rs1 << 15) | (rs2 << 20) | (funct7 << 25); +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 986dbb95251489..55814c64455587 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -79,6 +79,13 @@ bool IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regNumber src bool IsRedundantLdStr( instruction ins, regNumber reg1, regNumber reg2, ssize_t imm, emitAttr size, insFormat fmt); // New functions end. +static code_t insEncodeRTypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned rs2, unsigned funct7) const; +static code_t insEncodeITypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned imm12) const; +static code_t insEncodeSTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12) const; +static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, unsigned imm20) const; +static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12) const; +static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, unsigned imm20) const; + /************************************************************************/ /* Public inline informational methods */ /************************************************************************/ From f09636f3859a8bb07f88199c158e0aff1b0e42cd Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 15 Dec 2023 15:33:16 +0100 Subject: [PATCH 002/106] Added insEncodeITypeInstr --- src/coreclr/jit/emitriscv64.cpp | 24 +++++++++++++++++++++++- src/coreclr/jit/emitriscv64.h | 13 +++++++------ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 8cfb5dab0d4165..b20715ec610356 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2145,7 +2145,8 @@ static void assertCodeLength(unsigned code, uint8_t size) * ------------------------------------------------------------------- */ -/*static*/ code_t emitter::insEncodeRTypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned rs2, unsigned funct7) const +/*static*/ emitter::code_t emitter::insEncodeRTypeInstr( + unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned rs2, unsigned funct7) { assertCodeLength(opcode, 7); assertCodeLength(rd, 5); @@ -2156,6 +2157,27 @@ static void assertCodeLength(unsigned code, uint8_t size) return opcode | (rd << 7) | (funct3 << 12) | (rs1 << 15) | (rs2 << 20) | (funct7 << 25); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 I-Type instruction + * + * Note: Instruction types as per RISC-V Spec, Chapter 24 RV32/64G Instruction Set Listings + * I-Type layout: + * 31----------------------15-14------12-11-----------7-6------------0 + * | imm[11:0] | funct3 | rd | opcode | + * ------------------------------------------------------------------- + */ + +/*static*/ emitter::code_t emitter::insEncodeITypeInstr( + unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned imm12) +{ + assertCodeLength(opcode, 7); + assertCodeLength(rd, 5); + assertCodeLength(funct3, 3); + assertCodeLength(imm12, 12); + return opcode | (rd << 7) | (funct3 << 12) | (imm12 << 15); +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 55814c64455587..061a7ffa282747 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -79,12 +79,13 @@ bool IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regNumber src bool IsRedundantLdStr( instruction ins, regNumber reg1, regNumber reg2, ssize_t imm, emitAttr size, insFormat fmt); // New functions end. -static code_t insEncodeRTypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned rs2, unsigned funct7) const; -static code_t insEncodeITypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned imm12) const; -static code_t insEncodeSTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12) const; -static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, unsigned imm20) const; -static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12) const; -static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, unsigned imm20) const; +static code_t insEncodeRTypeInstr( + unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned rs2, unsigned funct7); +static code_t insEncodeITypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned imm12); +static code_t insEncodeSTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12); +static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, unsigned imm20); +static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12); +static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, unsigned imm20); /************************************************************************/ /* Public inline informational methods */ From ffeb2adf647934f70c828e05c00143063c90a236 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 15 Dec 2023 16:01:35 +0100 Subject: [PATCH 003/106] Added definition of S type instr --- src/coreclr/jit/emitriscv64.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index b20715ec610356..c706a3ab9b919d 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2178,6 +2178,33 @@ static void assertCodeLength(unsigned code, uint8_t size) return opcode | (rd << 7) | (funct3 << 12) | (imm12 << 15); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 S-Type instruction + * + * Note: Instruction types as per RISC-V Spec, Chapter 24 RV32/64G Instruction Set Listings + * S-Type layout: + * 31-------25-24---20-19--15-14------12-11-----------7-6------------0 + * |imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode | + * ------------------------------------------------------------------- + */ + +/*static*/ emitter::code_t emitter::insEncodeSTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12) +{ + static constexpr unsigned kLoMask = 0x1f; // 0b00011111 + static constexpr unsigned kHiMask = 0x7f; // 0b01111111 + + assertCodeLength(opcode, 7); + assertCodeLength(funct3, 3); + assertCodeLength(rs1, 5); + assertCodeLength(rs2, 5); + assertCodeLength(imm12, 12); + unsigned imm12Lo = imm12 & kLoMask; + unsigned imm12Hi = (imm12 >> 5) & kHiMask; + + return opcode | (imm12Lo << 7) | (funct3 << 12) | (rs1 << 15) | (rs2 << 20) | (imm12Hi << 25); +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor From 4fba3b70962554da1d904bb58421458e53842f1d Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 15 Dec 2023 16:05:44 +0100 Subject: [PATCH 004/106] Added definition of U type instr --- src/coreclr/jit/emitriscv64.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index c706a3ab9b919d..ff10fd8a529efe 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2154,6 +2154,7 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(rs1, 5); assertCodeLength(rs2, 5); assertCodeLength(funct7, 7); + return opcode | (rd << 7) | (funct3 << 12) | (rs1 << 15) | (rs2 << 20) | (funct7 << 25); } @@ -2175,6 +2176,7 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(rd, 5); assertCodeLength(funct3, 3); assertCodeLength(imm12, 12); + return opcode | (rd << 7) | (funct3 << 12) | (imm12 << 15); } @@ -2205,6 +2207,26 @@ static void assertCodeLength(unsigned code, uint8_t size) return opcode | (imm12Lo << 7) | (funct3 << 12) | (rs1 << 15) | (rs2 << 20) | (imm12Hi << 25); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 U-Type instruction + * + * Note: Instruction types as per RISC-V Spec, Chapter 24 RV32/64G Instruction Set Listings + * U-Type layout: + * 31---------------------------------12-11-----------7-6------------0 + * | imm[31:12] | rd | opcode | + * ------------------------------------------------------------------- + */ + +/*static*/ emitter::code_t emitter::insEncodeUTypeInstr(unsigned opcode, unsigned rd, unsigned imm20) +{ + assertCodeLength(opcode, 7); + assertCodeLength(rd, 5); + assertCodeLength(imm20, 20); + + return opcode | (rd << 7) | (imm20 << (12 + 12)); +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor From e2589bf1c85cb97b5dd268b61e42549f54aa6510 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 15 Dec 2023 16:26:00 +0100 Subject: [PATCH 005/106] Added definition of B type instr --- src/coreclr/jit/emitriscv64.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index ff10fd8a529efe..90ee9968d15e69 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2130,7 +2130,7 @@ void emitter::emitJumpDistBind() static void assertCodeLength(unsigned code, uint8_t size) { #ifdef DEBUG - assert(code < (1u << size)); + assert((code >> size) == 0); #endif // DEBUG } @@ -2227,6 +2227,35 @@ static void assertCodeLength(unsigned code, uint8_t size) return opcode | (rd << 7) | (imm20 << (12 + 12)); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 B-Type instruction + * + * Note: Instruction types as per RISC-V Spec, Chapter 24 RV32/64G Instruction Set Listings + * B-Type layout: + * 31-------30-----25-24-20-19-15-14--12-11-------8----7----6--------0 + * |imm[12]|imm[10:5]| rs2 | rs1 |funct3| imm[4:1]|imm[11]| opcode | + * ------------------------------------------------------------------- + */ + +/*static*/ emitter::code_t emitter::insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm13) +{ + static constexpr unsigned kLoMask = 0x0f; // 0b00001111 + static constexpr unsigned kHiMask = 0x3f; // 0b00111111 + static constexpr unsigned kBitMask = 0x01; + + assertCodeLength(opcode, 7); + assertCodeLength(funct3, 3); + assertCodeLength(rs1, 5); + assertCodeLength(rs2, 5); + assertCodeLength(imm13, 13); + imm13 >>= 1; + unsigned imm13Lo = ((imm13 & kLoMask) << 1) | ((imm13 >> 10) & kBitMask); + unsigned imm13Hi = ((imm13 >> 4) & kHiMask) | (((imm13 >> 11) & kBitMask) << 6); + + return opcode | (imm13Lo << 7) | (funct3 << 12) | (rs1 << 15) | (rs2 << 20) | (imm13Hi << 25); +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor From b5a17d39bf7362ee97abc33f73464fa7b5cdd392 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 15 Dec 2023 16:45:38 +0100 Subject: [PATCH 006/106] Added definition of J type instr --- src/coreclr/jit/emitriscv64.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 90ee9968d15e69..16d3cfa0ce0e73 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2256,6 +2256,34 @@ static void assertCodeLength(unsigned code, uint8_t size) return opcode | (imm13Lo << 7) | (funct3 << 12) | (rs1 << 15) | (rs2 << 20) | (imm13Hi << 25); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 J-Type instruction + * + * Note: Instruction types as per RISC-V Spec, Chapter 24 RV32/64G Instruction Set Listings + * J-Type layout: + * 31-------30--------21----20---19----------12-11----7-6------------0 + * |imm[20]| imm[10:1] |imm[11]| imm[19:12] | rd | opcode | + * ------------------------------------------------------------------- + */ + +/*static*/ emitter::code_t emitter::insEncodeJTypeInstr(unsigned opcode, unsigned rd, unsigned imm21) +{ + static constexpr unsigned kSectionMask = 0x3ff; // 0b1111111111 + static constexpr unsigned kBitMask = 0x01; + + assertCodeLength(opcode, 7); + assertCodeLength(rd, 5); + assertCodeLength(imm21, 21); + unsigned imm20 = imm21 >> 1; + unsigned imm20HiSection = imm20 & kSectionMask; + unsigned imm20HiBit = (imm20 >> 19) & kBitMask; + unsigned imm20LoSection = (imm20 >> 11) & kSection; + unsigned imm20LoBit = (imm20 >> 10) & kBitMask; + + return opcode | (rd << 7) | (imm20LoSection << 12) | (imm20LoBit << 20) | (imm20HiSection << 21) | (imm20HiBit << 31); +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor From ca39ca4fb523eccdc818b04d06eec3bdb516b8d7 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 15 Dec 2023 16:50:03 +0100 Subject: [PATCH 007/106] Restructurized bit operations --- src/coreclr/jit/emitriscv64.cpp | 36 +++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 16d3cfa0ce0e73..36dfbd57e7e1ac 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2191,7 +2191,8 @@ static void assertCodeLength(unsigned code, uint8_t size) * ------------------------------------------------------------------- */ -/*static*/ emitter::code_t emitter::insEncodeSTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12) +/*static*/ emitter::code_t emitter::insEncodeSTypeInstr( + unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12) { static constexpr unsigned kLoMask = 0x1f; // 0b00011111 static constexpr unsigned kHiMask = 0x7f; // 0b01111111 @@ -2238,22 +2239,26 @@ static void assertCodeLength(unsigned code, uint8_t size) * ------------------------------------------------------------------- */ -/*static*/ emitter::code_t emitter::insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm13) +/*static*/ emitter::code_t emitter::insEncodeBTypeInstr( + unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm13) { - static constexpr unsigned kLoMask = 0x0f; // 0b00001111 - static constexpr unsigned kHiMask = 0x3f; // 0b00111111 - static constexpr unsigned kBitMask = 0x01; + static constexpr unsigned kLoSectionMask = 0x0f; // 0b00001111 + static constexpr unsigned kHiSectionMask = 0x3f; // 0b00111111 + static constexpr unsigned kBitMask = 0x01; assertCodeLength(opcode, 7); assertCodeLength(funct3, 3); assertCodeLength(rs1, 5); assertCodeLength(rs2, 5); assertCodeLength(imm13, 13); - imm13 >>= 1; - unsigned imm13Lo = ((imm13 & kLoMask) << 1) | ((imm13 >> 10) & kBitMask); - unsigned imm13Hi = ((imm13 >> 4) & kHiMask) | (((imm13 >> 11) & kBitMask) << 6); - - return opcode | (imm13Lo << 7) | (funct3 << 12) | (rs1 << 15) | (rs2 << 20) | (imm13Hi << 25); + unsigned imm12 = imm13 >> 1; + unsigned imm12LoSection = imm12 & kLoSectionMask; + unsigned imm12LoBit = (imm12 >> 10) & kBitMask; + unsigned imm12HiSection = (imm12 >> 4) & kHiSectionMask; + unsigned imm12HiBit = (imm12 >> 11) & kBitMask; + + return opcode | (imm12LoBit << 7) | (imm12LoSection << 8) | (funct3 << 12) | (rs1 << 15) | (rs2 << 20) | + (imm12HiSection << 25) | (imm12HiBit << 31); } /***************************************************************************** @@ -2270,18 +2275,19 @@ static void assertCodeLength(unsigned code, uint8_t size) /*static*/ emitter::code_t emitter::insEncodeJTypeInstr(unsigned opcode, unsigned rd, unsigned imm21) { static constexpr unsigned kSectionMask = 0x3ff; // 0b1111111111 - static constexpr unsigned kBitMask = 0x01; + static constexpr unsigned kBitMask = 0x01; assertCodeLength(opcode, 7); assertCodeLength(rd, 5); assertCodeLength(imm21, 21); - unsigned imm20 = imm21 >> 1; + unsigned imm20 = imm21 >> 1; unsigned imm20HiSection = imm20 & kSectionMask; - unsigned imm20HiBit = (imm20 >> 19) & kBitMask; + unsigned imm20HiBit = (imm20 >> 19) & kBitMask; unsigned imm20LoSection = (imm20 >> 11) & kSection; - unsigned imm20LoBit = (imm20 >> 10) & kBitMask; + unsigned imm20LoBit = (imm20 >> 10) & kBitMask; - return opcode | (rd << 7) | (imm20LoSection << 12) | (imm20LoBit << 20) | (imm20HiSection << 21) | (imm20HiBit << 31); + return opcode | (rd << 7) | (imm20LoSection << 12) | (imm20LoBit << 20) | (imm20HiSection << 21) | + (imm20HiBit << 31); } /***************************************************************************** From b28007242b9448fb871732df9997a2dfb9119b2b Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 15 Dec 2023 16:57:53 +0100 Subject: [PATCH 008/106] Improved checks in insEncode functions --- src/coreclr/jit/emitriscv64.cpp | 23 +++++++++++++---------- src/coreclr/jit/emitriscv64.h | 10 +++++----- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 36dfbd57e7e1ac..e5dfb95b87a6b2 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2170,12 +2170,12 @@ static void assertCodeLength(unsigned code, uint8_t size) */ /*static*/ emitter::code_t emitter::insEncodeITypeInstr( - unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned imm12) + unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, int imm12) { assertCodeLength(opcode, 7); assertCodeLength(rd, 5); assertCodeLength(funct3, 3); - assertCodeLength(imm12, 12); + isValidSimm12(imm12); return opcode | (rd << 7) | (funct3 << 12) | (imm12 << 15); } @@ -2192,7 +2192,7 @@ static void assertCodeLength(unsigned code, uint8_t size) */ /*static*/ emitter::code_t emitter::insEncodeSTypeInstr( - unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12) + unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm12) { static constexpr unsigned kLoMask = 0x1f; // 0b00011111 static constexpr unsigned kHiMask = 0x7f; // 0b01111111 @@ -2201,7 +2201,8 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(funct3, 3); assertCodeLength(rs1, 5); assertCodeLength(rs2, 5); - assertCodeLength(imm12, 12); + isValidSimm12(imm12); + unsigned imm12Lo = imm12 & kLoMask; unsigned imm12Hi = (imm12 >> 5) & kHiMask; @@ -2219,11 +2220,11 @@ static void assertCodeLength(unsigned code, uint8_t size) * ------------------------------------------------------------------- */ -/*static*/ emitter::code_t emitter::insEncodeUTypeInstr(unsigned opcode, unsigned rd, unsigned imm20) +/*static*/ emitter::code_t emitter::insEncodeUTypeInstr(unsigned opcode, unsigned rd, int imm20) { assertCodeLength(opcode, 7); assertCodeLength(rd, 5); - assertCodeLength(imm20, 20); + isValidSimm20(imm20); return opcode | (rd << 7) | (imm20 << (12 + 12)); } @@ -2240,7 +2241,7 @@ static void assertCodeLength(unsigned code, uint8_t size) */ /*static*/ emitter::code_t emitter::insEncodeBTypeInstr( - unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm13) + unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm13) { static constexpr unsigned kLoSectionMask = 0x0f; // 0b00001111 static constexpr unsigned kHiSectionMask = 0x3f; // 0b00111111 @@ -2250,7 +2251,8 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(funct3, 3); assertCodeLength(rs1, 5); assertCodeLength(rs2, 5); - assertCodeLength(imm13, 13); + isValidSimm13(imm13); + unsigned imm12 = imm13 >> 1; unsigned imm12LoSection = imm12 & kLoSectionMask; unsigned imm12LoBit = (imm12 >> 10) & kBitMask; @@ -2272,14 +2274,15 @@ static void assertCodeLength(unsigned code, uint8_t size) * ------------------------------------------------------------------- */ -/*static*/ emitter::code_t emitter::insEncodeJTypeInstr(unsigned opcode, unsigned rd, unsigned imm21) +/*static*/ emitter::code_t emitter::insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21) { static constexpr unsigned kSectionMask = 0x3ff; // 0b1111111111 static constexpr unsigned kBitMask = 0x01; assertCodeLength(opcode, 7); assertCodeLength(rd, 5); - assertCodeLength(imm21, 21); + isValidSimm21(imm21); + unsigned imm20 = imm21 >> 1; unsigned imm20HiSection = imm20 & kSectionMask; unsigned imm20HiBit = (imm20 >> 19) & kBitMask; diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 061a7ffa282747..45d7a675f7a3ca 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -81,11 +81,11 @@ bool IsRedundantLdStr( static code_t insEncodeRTypeInstr( unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned rs2, unsigned funct7); -static code_t insEncodeITypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned imm12); -static code_t insEncodeSTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12); -static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, unsigned imm20); -static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12); -static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, unsigned imm20); +static code_t insEncodeITypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, int imm12); +static code_t insEncodeSTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm12); +static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, int imm20); +static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm13); +static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); /************************************************************************/ /* Public inline informational methods */ From 5df65bc5c0cd77e7dae2c9862dd66d453af33ee2 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 18 Dec 2023 12:00:57 +0100 Subject: [PATCH 009/106] Fixed some of the encoding methods --- src/coreclr/jit/emitriscv64.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index c8198da43ca4bd..b7de674a8795b7 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2156,8 +2156,8 @@ static void assertCodeLength(unsigned code, uint8_t size) * * Note: Instruction types as per RISC-V Spec, Chapter 24 RV32/64G Instruction Set Listings * I-Type layout: - * 31----------------------15-14------12-11-----------7-6------------0 - * | imm[11:0] | funct3 | rd | opcode | + * 31------------20-19-----15-14------12-11-----------7-6------------0 + * | imm[11:0] | rs1 | funct3 | rd | opcode | * ------------------------------------------------------------------- */ @@ -2167,9 +2167,10 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(opcode, 7); assertCodeLength(rd, 5); assertCodeLength(funct3, 3); + assertCodeLength(rs1, 5); isValidSimm12(imm12); - return opcode | (rd << 7) | (funct3 << 12) | (imm12 << 15); + return opcode | (rd << 7) | (funct3 << 12) | (rs1 << 15) | (imm12 << 20); } /***************************************************************************** @@ -2218,7 +2219,7 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(rd, 5); isValidSimm20(imm20); - return opcode | (rd << 7) | (imm20 << (12 + 12)); + return opcode | (rd << 7) | ((imm20 >> 12) << 12); } /***************************************************************************** @@ -2278,7 +2279,7 @@ static void assertCodeLength(unsigned code, uint8_t size) unsigned imm20 = imm21 >> 1; unsigned imm20HiSection = imm20 & kSectionMask; unsigned imm20HiBit = (imm20 >> 19) & kBitMask; - unsigned imm20LoSection = (imm20 >> 11) & kSection; + unsigned imm20LoSection = (imm20 >> 11) & kSectionMask; unsigned imm20LoBit = (imm20 >> 10) & kBitMask; return opcode | (rd << 7) | (imm20LoSection << 12) | (imm20LoBit << 20) | (imm20HiSection << 21) | From 593009b8cdc16f694485bbc90e3604fca8105e3a Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 18 Dec 2023 15:46:16 +0100 Subject: [PATCH 010/106] Bugfix --- src/coreclr/jit/emit.h | 4 +-- src/coreclr/jit/emitriscv64.cpp | 51 ++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 87c57113a6513a..c6134353ed3f61 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -993,15 +993,15 @@ class emitter #elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) struct { - unsigned int iiaEncodedInstr; // instruction's binary encoding. regNumber _idReg3 : REGNUM_BITS; regNumber _idReg4 : REGNUM_BITS; + unsigned int iiaEncodedInstr; // instruction's binary encoding. }; struct { - int iiaJmpOffset; // temporary saving the offset of jmp or data. emitLclVarAddr iiaLclVar; + int iiaJmpOffset; // temporary saving the offset of jmp or data. }; void iiaSetInstrEncode(unsigned int encode) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 5945cc61d73eb0..7ac03670f30e09 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -659,7 +659,9 @@ void emitter::emitIns_R_R( void emitter::emitIns_R_R_I( instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */) { - code_t code = emitInsCode(ins); + code_t code = emitInsCode(ins); + instrDesc* id = emitNewInstr(attr); + if ((INS_addi <= ins && INS_srai >= ins) || (INS_addiw <= ins && INS_sraiw >= ins) || (INS_lb <= ins && INS_lhu >= ins) || INS_ld == ins || INS_lw == ins || INS_jalr == ins || INS_fld == ins || INS_flw == ins) @@ -688,6 +690,8 @@ void emitter::emitIns_R_R_I( code |= ((imm >> 1) & 0xf) << 8; code |= ((imm >> 5) & 0x3f) << 25; code |= ((imm >> 12) & 0x1) << 31; + // TODO-RISCV64: Move jump logic to emitIns_J + id->idAddr()->iiaSetInstrCount(imm / sizeof(code_t)); } else if (ins == INS_csrrs || ins == INS_csrrw || ins == INS_csrrc) { @@ -702,7 +706,6 @@ void emitter::emitIns_R_R_I( { NYI_RISCV64("illegal ins within emitIns_R_R_I!"); } - instrDesc* id = emitNewInstr(attr); id->idIns(ins); id->idReg1(reg1); @@ -2124,22 +2127,22 @@ void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, UNATIVE_OFFSET& dstOffs, const BYTE*& dstAddr) const { - // TODO-RISCV64-BUG: iiaEncodedInstrCount is not set by the riscv impl making distinguishing the jumps to label and - // an instruction-count based jumps impossible - if (jmp->idAddr()->iiaHasInstrCount()) - { - assert(ig != nullptr); - int instrCount = jmp->idAddr()->iiaGetInstrCount(); - unsigned insNum = emitFindInsNum(ig, jmp); - if (instrCount < 0) - { - // Backward branches using instruction count must be within the same instruction group. - assert(insNum + 1 >= static_cast(-instrCount)); - } - dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount)); - dstAddr = emitOffsetToPtr(dstOffs); - return; - } + // TODO-RISCV64: Currently the iiaEncodedInstrCount is not set by any of the emitIns_* methods + assert(!jmp->idAddr()->iiaHasInstrCount()); + // if (jmp->idAddr()->iiaHasInstrCount()) + // { + // assert(ig != nullptr); + // int instrCount = jmp->idAddr()->iiaGetInstrCount(); + // unsigned insNum = emitFindInsNum(ig, jmp); + // if (instrCount < 0) + // { + // // Backward branches using instruction count must be within the same instruction group. + // assert(insNum + 1 >= static_cast(-instrCount)); + // } + // dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount); + // dstAddr = emitOffsetToPtr(dstOffs); + // return; + // } dstOffs = jmp->idAddr()->iiaIGlabel->igOffs; dstAddr = emitOffsetToPtr(dstOffs); } @@ -2997,10 +3000,18 @@ void emitter::emitDispBranchOffset(const instrDesc* id, const insGroup* ig) cons printf("pc%s%d instructions", signFn(instrCount), instrCount); return; } - unsigned insNum = emitFindInsNum(ig, id); + unsigned insNum = emitFindInsNum(ig, id); + + if (ig->igInsCnt >= insNum + 1 + instrCount) + { + // TODO-RISCV64-BUG: This should be a labeled offset but does not contain a label + printf("pc%s%d instructions", signFn(instrCount), instrCount); + return; + } + UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1); UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount); - ssize_t relOffs = static_cast(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(dstOffs)); + ssize_t relOffs = static_cast(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs)); printf("pc%s%d (%d instructions)", signFn(relOffs), static_cast(relOffs), instrCount); } From c238b82cf939c19ed55ce9e027fcaf4def6ba064 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 18 Dec 2023 15:53:20 +0100 Subject: [PATCH 011/106] Fixed comparation sign --- src/coreclr/jit/emitarm64.cpp | 148 +++++++++++++++++----------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 709ab8659be71f..a091ce7e1a3174 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -2674,7 +2674,7 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes2[] = { - #define INST1(id, nm, info, fmt, e1 ) + #define INST1(id, nm, info, fmt, e1 ) #define INST2(id, nm, info, fmt, e1, e2 ) e2, #define INST3(id, nm, info, fmt, e1, e2, e3 ) e2, #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) e2, @@ -2690,8 +2690,8 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes3[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) #define INST3(id, nm, info, fmt, e1, e2, e3 ) e3, #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) e3, #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e3, @@ -2706,9 +2706,9 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes4[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) e4, #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e4, #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e4, @@ -2722,10 +2722,10 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes5[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e5, #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e5, #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) e5, @@ -2738,11 +2738,11 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes6[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e6, #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) e6, #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e6, @@ -2754,12 +2754,12 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes7[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) e7, #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e7, #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) e7, @@ -2770,13 +2770,13 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes8[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e8, #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) e8, #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) e8, @@ -2786,14 +2786,14 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes9[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) - #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) e9, #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) e9, #define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ) e9, @@ -2802,15 +2802,15 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes10[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) - #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) - #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) e10, #define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ) e10, #include "instrsarm64sve.h" @@ -2818,15 +2818,15 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes11[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) - #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) - #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) e11, #define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ) e11, #include "instrsarm64sve.h" @@ -2834,32 +2834,32 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes12[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) - #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) - #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) - #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) + #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) #define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ) e12, #include "instrsarm64sve.h" }; const static code_t insCodes13[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) - #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) - #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) - #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) + #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) #define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ) e13, #include "instrsarm64sve.h" }; From c5f212a1c8c53a6f2e4a21e9a928069d71f0aa9f Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 18 Dec 2023 15:54:53 +0100 Subject: [PATCH 012/106] Revert "Fixed comparation sign" This reverts commit c238b82cf939c19ed55ce9e027fcaf4def6ba064. --- src/coreclr/jit/emitarm64.cpp | 148 +++++++++++++++++----------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index a091ce7e1a3174..709ab8659be71f 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -2674,7 +2674,7 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes2[] = { - #define INST1(id, nm, info, fmt, e1 ) + #define INST1(id, nm, info, fmt, e1 ) #define INST2(id, nm, info, fmt, e1, e2 ) e2, #define INST3(id, nm, info, fmt, e1, e2, e3 ) e2, #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) e2, @@ -2690,8 +2690,8 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes3[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) #define INST3(id, nm, info, fmt, e1, e2, e3 ) e3, #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) e3, #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e3, @@ -2706,9 +2706,9 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes4[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) e4, #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e4, #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e4, @@ -2722,10 +2722,10 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes5[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e5, #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e5, #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) e5, @@ -2738,11 +2738,11 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes6[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e6, #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) e6, #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e6, @@ -2754,12 +2754,12 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes7[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) e7, #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e7, #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) e7, @@ -2770,13 +2770,13 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes8[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e8, #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) e8, #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) e8, @@ -2786,14 +2786,14 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes9[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) - #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) e9, #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) e9, #define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ) e9, @@ -2802,15 +2802,15 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes10[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) - #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) - #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) e10, #define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ) e10, #include "instrsarm64sve.h" @@ -2818,15 +2818,15 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes11[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) - #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) - #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) e11, #define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ) e11, #include "instrsarm64sve.h" @@ -2834,32 +2834,32 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static code_t insCodes12[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) - #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) - #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) - #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) + #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) #define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ) e12, #include "instrsarm64sve.h" }; const static code_t insCodes13[] = { - #define INST1(id, nm, info, fmt, e1 ) - #define INST2(id, nm, info, fmt, e1, e2 ) - #define INST3(id, nm, info, fmt, e1, e2, e3 ) - #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) - #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) - #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) - #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST7(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7 ) + #define INST8(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) + #define INST11(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 ) #define INST13(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ) e13, #include "instrsarm64sve.h" }; From f9adbefbe7829e0e6b0e505c69b29ddba2b14708 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 18 Dec 2023 15:55:08 +0100 Subject: [PATCH 013/106] Fixed comparation sign --- 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 7ac03670f30e09..9c30ff31fc591b 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -3002,7 +3002,7 @@ void emitter::emitDispBranchOffset(const instrDesc* id, const insGroup* ig) cons } unsigned insNum = emitFindInsNum(ig, id); - if (ig->igInsCnt >= insNum + 1 + instrCount) + if (ig->igInsCnt < insNum + 1 + instrCount) { // TODO-RISCV64-BUG: This should be a labeled offset but does not contain a label printf("pc%s%d instructions", signFn(instrCount), instrCount); From 661aebac763242d8ad3441eae5a168812caf9eed Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 18 Dec 2023 15:58:31 +0100 Subject: [PATCH 014/106] Reverted changes in emitOutputInstrJumpDistanceHelper --- src/coreclr/jit/emitriscv64.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 9c30ff31fc591b..b3045974ec0dd8 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2127,22 +2127,22 @@ void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, UNATIVE_OFFSET& dstOffs, const BYTE*& dstAddr) const { - // TODO-RISCV64: Currently the iiaEncodedInstrCount is not set by any of the emitIns_* methods - assert(!jmp->idAddr()->iiaHasInstrCount()); - // if (jmp->idAddr()->iiaHasInstrCount()) - // { - // assert(ig != nullptr); - // int instrCount = jmp->idAddr()->iiaGetInstrCount(); - // unsigned insNum = emitFindInsNum(ig, jmp); - // if (instrCount < 0) - // { - // // Backward branches using instruction count must be within the same instruction group. - // assert(insNum + 1 >= static_cast(-instrCount)); - // } - // dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount); - // dstAddr = emitOffsetToPtr(dstOffs); - // return; - // } + // TODO-RISCV64-BUG: Currently the iiaEncodedInstrCount is not set by the riscv impl making distinguishing the jump + // to label and an instruction-count based jumps impossible + if (jmp->idAddr()->iiaHasInstrCount()) + { + assert(ig != nullptr); + int instrCount = jmp->idAddr()->iiaGetInstrCount(); + unsigned insNum = emitFindInsNum(ig, jmp); + if (instrCount < 0) + { + // Backward branches using instruction count must be within the same instruction group. + assert(insNum + 1 >= static_cast(-instrCount)); + } + dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount); + dstAddr = emitOffsetToPtr(dstOffs); + return; + } dstOffs = jmp->idAddr()->iiaIGlabel->igOffs; dstAddr = emitOffsetToPtr(dstOffs); } From 6a8dffaf72577383261200634327ae383436bb97 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 18 Dec 2023 16:10:04 +0100 Subject: [PATCH 015/106] Fixed misspell --- 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 b3045974ec0dd8..6ab61f8d3c1e35 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -3004,7 +3004,7 @@ void emitter::emitDispBranchOffset(const instrDesc* id, const insGroup* ig) cons if (ig->igInsCnt < insNum + 1 + instrCount) { - // TODO-RISCV64-BUG: This should be a labeled offset but does not contain a label + // TODO-RISCV64-BUG: This should be a labeled offset but does not contain a iiaIGlabel printf("pc%s%d instructions", signFn(instrCount), instrCount); return; } From 9e095a592828af44d69a48f15b6e86966f07afbf Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 18 Dec 2023 16:43:54 +0100 Subject: [PATCH 016/106] Fixes after review --- src/coreclr/jit/emitriscv64.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 6ab61f8d3c1e35..fac65fda898975 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2992,27 +2992,25 @@ bool emitter::emitDispBranchInstrType(unsigned opcode2) const void emitter::emitDispBranchOffset(const instrDesc* id, const insGroup* ig) const { - static const auto signFn = [](int offset) { return offset >= 0 ? "+" : ""; }; - int instrCount = id->idAddr()->iiaGetInstrCount(); if (ig == nullptr) { - printf("pc%s%d instructions", signFn(instrCount), instrCount); + printf("pc%+d instructions", instrCount); return; } unsigned insNum = emitFindInsNum(ig, id); if (ig->igInsCnt < insNum + 1 + instrCount) { - // TODO-RISCV64-BUG: This should be a labeled offset but does not contain a iiaIGlabel - printf("pc%s%d instructions", signFn(instrCount), instrCount); + // TODO-RISCV64-BUG: This should be a labeled offset but does not contain an iiaIGlabel + printf("pc%+d instructions", instrCount); return; } UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1); UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount); ssize_t relOffs = static_cast(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs)); - printf("pc%s%d (%d instructions)", signFn(relOffs), static_cast(relOffs), instrCount); + printf("pc%+d (%d instructions)", static_cast(relOffs), instrCount); } void emitter::emitDispBranchLabel(const instrDesc* id) const From ce8f5946c091c88082d9e66028fb9d447a537686 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 12:03:30 +0100 Subject: [PATCH 017/106] Fixes in insEncodeJTypeInstr --- src/coreclr/jit/emitriscv64.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index b7de674a8795b7..98344ead6601dc 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2269,7 +2269,8 @@ static void assertCodeLength(unsigned code, uint8_t size) /*static*/ emitter::code_t emitter::insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21) { - static constexpr unsigned kSectionMask = 0x3ff; // 0b1111111111 + static constexpr unsigned kHiSectionMask = 0x3ff; // 0b1111111111 + static constexpr unsigned kLoSectionMask = 0xff; // 0b11111111 static constexpr unsigned kBitMask = 0x01; assertCodeLength(opcode, 7); @@ -2277,9 +2278,9 @@ static void assertCodeLength(unsigned code, uint8_t size) isValidSimm21(imm21); unsigned imm20 = imm21 >> 1; - unsigned imm20HiSection = imm20 & kSectionMask; + unsigned imm20HiSection = imm20 & kHiSectionMask; unsigned imm20HiBit = (imm20 >> 19) & kBitMask; - unsigned imm20LoSection = (imm20 >> 11) & kSectionMask; + unsigned imm20LoSection = (imm20 >> 11) & kLoSectionMask; unsigned imm20LoBit = (imm20 >> 10) & kBitMask; return opcode | (rd << 7) | (imm20LoSection << 12) | (imm20LoBit << 20) | (imm20HiSection << 21) | From e8f7149f259684c3b83fba0ae323d2deb8ffaa47 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 14:05:32 +0100 Subject: [PATCH 018/106] Added emitOutput_RTypeInstr --- src/coreclr/jit/emitriscv64.cpp | 21 ++++++++++++++++++--- src/coreclr/jit/emitriscv64.h | 4 +++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 98344ead6601dc..a27daf257de35d 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2112,7 +2112,7 @@ void emitter::emitJumpDistBind() * Emit a 32-bit RISCV64 instruction */ -unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code) +unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code) const { assert(sizeof(code_t) == 4); memcpy(dst + writeableOffset, &code, sizeof(code_t)); @@ -2270,8 +2270,8 @@ static void assertCodeLength(unsigned code, uint8_t size) /*static*/ emitter::code_t emitter::insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21) { static constexpr unsigned kHiSectionMask = 0x3ff; // 0b1111111111 - static constexpr unsigned kLoSectionMask = 0xff; // 0b11111111 - static constexpr unsigned kBitMask = 0x01; + static constexpr unsigned kLoSectionMask = 0xff; // 0b11111111 + static constexpr unsigned kBitMask = 0x01; assertCodeLength(opcode, 7); assertCodeLength(rd, 5); @@ -2287,6 +2287,21 @@ static void assertCodeLength(unsigned code, uint8_t size) (imm20HiBit << 31); } +unsigned code_t +emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const +{ +#ifdef DEBUG + static constexpr unsigned kInstructionMask = 0xfe00707f; + + assert((ins & kInstructionMask) == 0); +#endif // DEBUG + + unsigned opcode = ins & 0x7f; + unsigned funct3 = (ins >> 12) & 0x07; + unsigned funct7 = (ins >> 25) & 0x7f; + return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7), sizeof(code_t)); +} + void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, instrDescJmp* jmp, UNATIVE_OFFSET& dstOffs, diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 1916fd02bf03ba..574fa8feca7c71 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -79,7 +79,7 @@ emitter::code_t emitInsCode(instruction ins /*, insFormat fmt*/); void emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir); // Emit the 32-bit RISCV64 instruction 'code' into the 'dst' buffer -unsigned emitOutput_Instr(BYTE* dst, code_t code); +unsigned emitOutput_Instr(BYTE* dst, code_t code) const; ssize_t emitOutputInstrJumpDistance(const BYTE* dst, const BYTE* src, const insGroup* ig, instrDescJmp* jmp); void emitOutputInstrJumpDistanceHelper(const insGroup* ig, @@ -102,6 +102,8 @@ static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, int imm20); static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm13); static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); +unsigned code_t emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const; + /************************************************************************/ /* Public inline informational methods */ /************************************************************************/ From 37cfcb42ecc1cd77cb4c8535063860203c79e2ee Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 14:14:12 +0100 Subject: [PATCH 019/106] Added emitOutput_ITypeInstr --- src/coreclr/jit/emitriscv64.cpp | 26 ++++++++++++++++++++++---- src/coreclr/jit/emitriscv64.h | 1 + 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index a27daf257de35d..07131f6c7ada02 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2287,21 +2287,39 @@ static void assertCodeLength(unsigned code, uint8_t size) (imm20HiBit << 31); } +static constexpr unsigned kInstructionOpcodeMask = 0x7f; +static constexpr unsigned kInstructionFunct3Mask = 0x7000; +static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; + unsigned code_t emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const { #ifdef DEBUG - static constexpr unsigned kInstructionMask = 0xfe00707f; + static constexpr unsigned kInstructionMask = kInstructionOpcodeMask + | kInstructionFunct3Mask | kInstructionFunct7Mask; assert((ins & kInstructionMask) == 0); #endif // DEBUG - unsigned opcode = ins & 0x7f; - unsigned funct3 = (ins >> 12) & 0x07; - unsigned funct7 = (ins >> 25) & 0x7f; + unsigned opcode = ins & kInstructionOpcodeMask; + unsigned funct3 = (ins & kInstructionFunct3Mask) >> 12; + unsigned funct7 = (ins & kInstructionFunct7Mask) >> 25; return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7), sizeof(code_t)); } +unsigned code_t emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const +{ +#ifdef DEBUG + static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; + + assert((ins & kInstructionMask) == 0); +#endif // DEBUG + + unsigned opcode = ins & kInstructionOpcodeMask; + unsigned funct3 = (ins & kInstructionFunct3Mask) >> 12; + return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, imm12), sizeof(code_t)); +} + void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, instrDescJmp* jmp, UNATIVE_OFFSET& dstOffs, diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 574fa8feca7c71..0f74c9ad6c39be 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -103,6 +103,7 @@ static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1 static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); unsigned code_t emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const; +unsigned code_t emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const; /************************************************************************/ /* Public inline informational methods */ From 41600c6f0ad287e14c355215341b10076bfbaa97 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 14:16:44 +0100 Subject: [PATCH 020/106] Added emitOutput_STypeInstr --- src/coreclr/jit/emitriscv64.cpp | 15 ++++++++++++++- src/coreclr/jit/emitriscv64.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 07131f6c7ada02..100c03d489244a 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2307,7 +2307,7 @@ emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7), sizeof(code_t)); } -unsigned code_t emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const +unsigned code_t emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const { #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; @@ -2320,6 +2320,19 @@ unsigned code_t emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, u return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, imm12), sizeof(code_t)); } +unsigned code_t emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const +{ +#ifdef DEBUG + static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; + + assert((ins & kInstructionMask) == 0); +#endif // DEBUG + + unsigned opcode = ins & kInstructionOpcodeMask; + unsigned funct3 = (ins & kInstructionFunct3Mask) >> 12; + return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2, imm12), sizeof(code_t)); +} + void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, instrDescJmp* jmp, UNATIVE_OFFSET& dstOffs, diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 0f74c9ad6c39be..9d8fc8e5848135 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -104,6 +104,7 @@ static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); unsigned code_t emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const; unsigned code_t emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const; +unsigned code_t emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const; /************************************************************************/ /* Public inline informational methods */ From 2098df0db0e6aed095bec0b9c50082370ca5c3f6 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 14:19:23 +0100 Subject: [PATCH 021/106] Added emitOutput_UTypeInstr --- src/coreclr/jit/emitriscv64.cpp | 5 +++++ src/coreclr/jit/emitriscv64.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 100c03d489244a..711f641609733e 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2333,6 +2333,11 @@ unsigned code_t emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsig return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2, imm12), sizeof(code_t)); } +unsigned code_t emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const +{ + return emitOutput_Instr(dst, insEncodeUTypeInstr(ins, rd, imm20), sizeof(code_t)); +} + void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, instrDescJmp* jmp, UNATIVE_OFFSET& dstOffs, diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 9d8fc8e5848135..eca3902872f9ee 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -105,6 +105,7 @@ static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); unsigned code_t emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const; unsigned code_t emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const; unsigned code_t emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const; +unsigned code_t emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20); /************************************************************************/ /* Public inline informational methods */ From c137d466976ea85bb96a1ae5ff5a74cd969f33aa Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 14:21:57 +0100 Subject: [PATCH 022/106] Added emitOutput_BTypeInstr --- src/coreclr/jit/emitriscv64.cpp | 13 +++++++++++++ src/coreclr/jit/emitriscv64.h | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 711f641609733e..b071d52dd34627 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2338,6 +2338,19 @@ unsigned code_t emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsig return emitOutput_Instr(dst, insEncodeUTypeInstr(ins, rd, imm20), sizeof(code_t)); } +unsigned code_t emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const +{ +#ifdef DEBUG + static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; + + assert((ins & kInstructionMask) == 0); +#endif // DEBUG + + unsigned opcode = ins & kInstructionOpcodeMask; + unsigned funct3 = (ins & kInstructionFunct3Mask) >> 12; + return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13), sizeof(code_t)); +} + void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, instrDescJmp* jmp, UNATIVE_OFFSET& dstOffs, diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index eca3902872f9ee..15600fea996bff 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -105,7 +105,8 @@ static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); unsigned code_t emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const; unsigned code_t emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const; unsigned code_t emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const; -unsigned code_t emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20); +unsigned code_t emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const; +unsigned code_t emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const; /************************************************************************/ /* Public inline informational methods */ From 71485b5cba91a10f35de47ae0bcbbf12d21186dd Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 14:24:11 +0100 Subject: [PATCH 023/106] Added emitOutput_JTypeInstr --- src/coreclr/jit/emitriscv64.cpp | 15 ++++++++++----- src/coreclr/jit/emitriscv64.h | 11 ++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index b071d52dd34627..611da0adf919b2 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2291,7 +2291,7 @@ static constexpr unsigned kInstructionOpcodeMask = 0x7f; static constexpr unsigned kInstructionFunct3Mask = 0x7000; static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; -unsigned code_t +unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const { #ifdef DEBUG @@ -2307,7 +2307,7 @@ emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7), sizeof(code_t)); } -unsigned code_t emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const +unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const { #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; @@ -2320,7 +2320,7 @@ unsigned code_t emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsig return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, imm12), sizeof(code_t)); } -unsigned code_t emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const +unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const { #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; @@ -2333,12 +2333,12 @@ unsigned code_t emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsig return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2, imm12), sizeof(code_t)); } -unsigned code_t emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const +unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const { return emitOutput_Instr(dst, insEncodeUTypeInstr(ins, rd, imm20), sizeof(code_t)); } -unsigned code_t emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const +unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const { #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; @@ -2351,6 +2351,11 @@ unsigned code_t emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsig return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13), sizeof(code_t)); } +unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm21) const +{ + return emitOutput_Instr(dst, insEncodeJTypeInstr(ins, rd, imm21), sizeof(code_t)); +} + void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, instrDescJmp* jmp, UNATIVE_OFFSET& dstOffs, diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 15600fea996bff..269d8c35583641 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -102,11 +102,12 @@ static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, int imm20); static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm13); static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); -unsigned code_t emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const; -unsigned code_t emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const; -unsigned code_t emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const; -unsigned code_t emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const; -unsigned code_t emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const; +unsigned emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const; +unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const; +unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const; +unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const; +unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const; +unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm21) const; /************************************************************************/ /* Public inline informational methods */ From 6b6eaa32b88b56c57b150a6a529b3fd624d6b74d Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 14:31:01 +0100 Subject: [PATCH 024/106] Fixes in emitOutput_ methods --- src/coreclr/jit/emitriscv64.cpp | 39 +++++++++++++++++++-------------- src/coreclr/jit/emitriscv64.h | 2 +- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 611da0adf919b2..97e72cbf4e701a 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -188,7 +188,7 @@ bool emitter::emitInsIsLoadOrStore(instruction ins) * Returns the specific encoding of the given CPU instruction. */ -inline emitter::code_t emitter::emitInsCode(instruction ins /*, insFormat fmt*/) +inline emitter::code_t emitter::emitInsCode(instruction ins /*, insFormat fmt*/) const { code_t code = BAD_CODE; @@ -2291,19 +2291,19 @@ static constexpr unsigned kInstructionOpcodeMask = 0x7f; static constexpr unsigned kInstructionFunct3Mask = 0x7000; static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; -unsigned -emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const +unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const { #ifdef DEBUG - static constexpr unsigned kInstructionMask = kInstructionOpcodeMask - | kInstructionFunct3Mask | kInstructionFunct7Mask; + static constexpr unsigned kInstructionMask = + kInstructionOpcodeMask | kInstructionFunct3Mask | kInstructionFunct7Mask; assert((ins & kInstructionMask) == 0); #endif // DEBUG - unsigned opcode = ins & kInstructionOpcodeMask; - unsigned funct3 = (ins & kInstructionFunct3Mask) >> 12; - unsigned funct7 = (ins & kInstructionFunct7Mask) >> 25; + unsigned insCode = emitInsCode(ins); + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 25; return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7), sizeof(code_t)); } @@ -2315,8 +2315,9 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, assert((ins & kInstructionMask) == 0); #endif // DEBUG - unsigned opcode = ins & kInstructionOpcodeMask; - unsigned funct3 = (ins & kInstructionFunct3Mask) >> 12; + unsigned insCode = emitInsCode(ins); + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, imm12), sizeof(code_t)); } @@ -2328,14 +2329,16 @@ unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1 assert((ins & kInstructionMask) == 0); #endif // DEBUG - unsigned opcode = ins & kInstructionOpcodeMask; - unsigned funct3 = (ins & kInstructionFunct3Mask) >> 12; + unsigned insCode = emitInsCode(ins); + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2, imm12), sizeof(code_t)); } unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const { - return emitOutput_Instr(dst, insEncodeUTypeInstr(ins, rd, imm20), sizeof(code_t)); + unsigned insCode = emitInsCode(ins); + return emitOutput_Instr(dst, insEncodeUTypeInstr(insCode, rd, imm20), sizeof(code_t)); } unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const @@ -2346,14 +2349,16 @@ unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1 assert((ins & kInstructionMask) == 0); #endif // DEBUG - unsigned opcode = ins & kInstructionOpcodeMask; - unsigned funct3 = (ins & kInstructionFunct3Mask) >> 12; + unsigned insCode = emitInsCode(ins); + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13), sizeof(code_t)); } unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm21) const { - return emitOutput_Instr(dst, insEncodeJTypeInstr(ins, rd, imm21), sizeof(code_t)); + unsigned insCode = emitInsCode(ins); + return emitOutput_Instr(dst, insEncodeJTypeInstr(insCode, rd, imm21), sizeof(code_t)); } void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, @@ -2427,7 +2432,7 @@ ssize_t emitter::emitOutputInstrJumpDistance(const BYTE* dst, const BYTE* src, c size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { - BYTE* const dst = *dp; + BYTE* dst = *dp; BYTE* dstRW = *dp + writeableOffset; BYTE* dstRW2 = dstRW + 4; // addr for updating gc info if needed. const BYTE* const odstRW = dstRW; diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 269d8c35583641..95655b8e2c91b8 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -73,7 +73,7 @@ void emitDispBranchLabel(const instrDesc* id) const; bool emitDispBranchInstrType(unsigned opcode2) const; void emitDispIllegalInstruction(code_t instructionCode); -emitter::code_t emitInsCode(instruction ins /*, insFormat fmt*/); +emitter::code_t emitInsCode(instruction ins /*, insFormat fmt*/) const; // Generate code for a load or store operation and handle the case of contained GT_LEA op1 with [base + offset] void emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir); From 4d2d7c150dfe1c692ff4ce54a12a9f229eb8fbfe Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 14:40:02 +0100 Subject: [PATCH 025/106] Replaced reloc with new code --- src/coreclr/jit/emitriscv64.cpp | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 97e72cbf4e701a..43f563a5740745 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2449,36 +2449,22 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { case INS_OPTS_RELOC: { - regNumber reg1 = id->idReg1(); - - *(code_t*)dstRW = 0x00000017 | (code_t)(reg1 << 7); + const regNumber reg1 = id->idReg1(); - dstRW += 4; - -#ifdef DEBUG - code = emitInsCode(INS_auipc); - assert(code == 0x00000017); - code = emitInsCode(INS_addi); - assert(code == 0x00000013); - code = emitInsCode(INS_ld); - assert(code == 0x00003003); -#endif + dst += emitOutput_UTypeInstr(dst, INS_auipc, reg1, 0); if (id->idIsCnsReloc()) { - ins = INS_addi; - *(code_t*)dstRW = 0x00000013 | (code_t)(reg1 << 7) | (code_t)(reg1 << 15); + ins = INS_addi; } else { assert(id->idIsDspReloc()); - ins = INS_ld; - *(code_t*)dstRW = 0x00003003 | (code_t)(reg1 << 7) | (code_t)(reg1 << 15); + ins = INS_ld; } + dst += emitOutput_ITypeInstr(dst, ins, reg1, reg1, 0); - dstRW += 4; - - emitRecordRelocation(dstRW - 8 - writeableOffset, id->idAddr()->iiaAddr, IMAGE_REL_RISCV64_PC); + emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_RISCV64_PC); sz = sizeof(instrDesc); } From 12eabdec1db887bbcfec6bb8edd426b90e50a8ef Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 14:44:32 +0100 Subject: [PATCH 026/106] Removed invalid code --- src/coreclr/jit/emitriscv64.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 43f563a5740745..c6385342725de7 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2304,7 +2304,7 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 25; - return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7), sizeof(code_t)); + return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7)); } unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const @@ -2318,7 +2318,7 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned insCode = emitInsCode(ins); unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, imm12), sizeof(code_t)); + return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, imm12)); } unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const @@ -2332,13 +2332,13 @@ unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1 unsigned insCode = emitInsCode(ins); unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2, imm12), sizeof(code_t)); + return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2, imm12)); } unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const { unsigned insCode = emitInsCode(ins); - return emitOutput_Instr(dst, insEncodeUTypeInstr(insCode, rd, imm20), sizeof(code_t)); + return emitOutput_Instr(dst, insEncodeUTypeInstr(insCode, rd, imm20)); } unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const @@ -2352,13 +2352,13 @@ unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1 unsigned insCode = emitInsCode(ins); unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13), sizeof(code_t)); + return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13)); } unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm21) const { unsigned insCode = emitInsCode(ins); - return emitOutput_Instr(dst, insEncodeJTypeInstr(insCode, rd, imm21), sizeof(code_t)); + return emitOutput_Instr(dst, insEncodeJTypeInstr(insCode, rd, imm21)); } void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, From 37604029ac017f268ba179e334a31dbccd74432d Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 14:55:10 +0100 Subject: [PATCH 027/106] Added emit output rellocation --- src/coreclr/jit/emitriscv64.cpp | 42 ++++++++++++++++++++------------- src/coreclr/jit/emitriscv64.h | 2 ++ 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index c6385342725de7..bba77668479e11 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2421,6 +2421,30 @@ ssize_t emitter::emitOutputInstrJumpDistance(const BYTE* dst, const BYTE* src, c return distVal; } +unsigned emitter::emitOutput_Rellocation(BYTE* dst, const instrDesc* id, instruction* ins) +{ + BYTE* const dstBase = dst; + const regNumber reg1 = id->idReg1(); + + dst += emitOutput_UTypeInstr(dst, INS_auipc, reg1, 0); + + if (id->idIsCnsReloc()) + { + *ins = INS_addi; + } + else + { + assert(id->idIsDspReloc()); + *ins = INS_ld; + } + + dst += emitOutput_ITypeInstr(dst, *ins, reg1, reg1, 0); + + emitRecordRelocation(dstBase, id->idAddr()->iiaAddr, IMAGE_REL_RISCV64_PC); + + return dst - dstBase; +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor @@ -2449,23 +2473,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { case INS_OPTS_RELOC: { - const regNumber reg1 = id->idReg1(); - - dst += emitOutput_UTypeInstr(dst, INS_auipc, reg1, 0); - - if (id->idIsCnsReloc()) - { - ins = INS_addi; - } - else - { - assert(id->idIsDspReloc()); - ins = INS_ld; - } - dst += emitOutput_ITypeInstr(dst, ins, reg1, reg1, 0); - - emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_RISCV64_PC); - + dst += emitOutput_Rellocation(dst, id, &ins); sz = sizeof(instrDesc); } break; diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 95655b8e2c91b8..34b2a6881b16c9 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -109,6 +109,8 @@ unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm2 unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const; unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm21) const; +unsigned emitOutput_Rellocation(BYTE* dst, const instrDesc* id, instruction* ins); + /************************************************************************/ /* Public inline informational methods */ /************************************************************************/ From e0a89cc2f5ab66170ca8b76ea9a2999f8f2a83b6 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 16:06:22 +0100 Subject: [PATCH 028/106] Minor changes --- src/coreclr/jit/emitriscv64.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index bba77668479e11..b25e28800b1528 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2465,18 +2465,16 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) instruction ins; size_t sz; // = emitSizeOfInsDsc(id); - assert(REG_NA == (int)REG_NA); + assert(REG_NA == static_cast(REG_NA)); insOpts insOp = id->idInsOpt(); switch (insOp) { case INS_OPTS_RELOC: - { dst += emitOutput_Rellocation(dst, id, &ins); sz = sizeof(instrDesc); - } - break; + break; case INS_OPTS_I: { ssize_t imm = (ssize_t)(id->idAddr()->iiaAddr); From 9cb8a7149544f7b1ee6ed91ad2e31a2eb124cf45 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 16:59:41 +0100 Subject: [PATCH 029/106] Added emitOutputInstr_Addi8 --- src/coreclr/jit/emitriscv64.cpp | 40 +++++++++++++++++++++++++++++---- src/coreclr/jit/emitriscv64.h | 4 +++- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index b25e28800b1528..c863c5b531e988 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2421,7 +2421,7 @@ ssize_t emitter::emitOutputInstrJumpDistance(const BYTE* dst, const BYTE* src, c return distVal; } -unsigned emitter::emitOutput_Rellocation(BYTE* dst, const instrDesc* id, instruction* ins) +BYTE* emitter::emitOutputInstr_Rellocation(BYTE* dst, const instrDesc* id, instruction* ins) { BYTE* const dstBase = dst; const regNumber reg1 = id->idReg1(); @@ -2442,7 +2442,38 @@ unsigned emitter::emitOutput_Rellocation(BYTE* dst, const instrDesc* id, instruc emitRecordRelocation(dstBase, id->idAddr()->iiaAddr, IMAGE_REL_RISCV64_PC); - return dst - dstBase; + return dst; +} + +BYTE* emitter::emitOutputInstr_Addi(BYTE* dst, const instrDesc* id) +{ + ssize_t immediate = static_cast(id->idAddr()->iiaAddr); + const regNumber reg1 = id->idReg1(); + + switch (id->idCodeSize()) + { + case 8: + dst = emitOutputInstr_Addi8(dst, id, immediate, reg1); + break; + } + return dst; +} + +BYTE* emitter::emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) +{ + if (id->idReg2()) + { + // special for INT64_MAX or UINT32_MAX + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, REG_R0, 0xfff); + ssize_t shiftValue = (immediate == INT64_MAX) ? 1 : 32; + dst += emitOutput_RTypeInstr(dst, INS_srli, reg1, reg1, shiftValue); + } + else + { + dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, immediate + 0x800); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, immediate & 0xfff); + } + return dst; } /***************************************************************************** @@ -2472,11 +2503,12 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) switch (insOp) { case INS_OPTS_RELOC: - dst += emitOutput_Rellocation(dst, id, &ins); - sz = sizeof(instrDesc); + dst = emitOutputInstr_Rellocation(dst, id, &ins); + sz = sizeof(instrDesc); break; case INS_OPTS_I: { + ins = INS_addi; ssize_t imm = (ssize_t)(id->idAddr()->iiaAddr); regNumber reg1 = id->idReg1(); diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 34b2a6881b16c9..cd6caac2175d55 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -109,7 +109,9 @@ unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm2 unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const; unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm21) const; -unsigned emitOutput_Rellocation(BYTE* dst, const instrDesc* id, instruction* ins); +BYTE* emitOutputInstr_Rellocation(BYTE* dst, const instrDesc* id, instruction* ins); +BYTE* emitOutputInstr_Addi(BYTE* dst, const instrDesc* id); +BYTE* emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); /************************************************************************/ /* Public inline informational methods */ From abb73ab0781816d593a70e65321286b39118a035 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 19 Dec 2023 17:24:59 +0100 Subject: [PATCH 030/106] Implemented further addi32 --- src/coreclr/jit/emitriscv64.cpp | 49 ++++++++++++++++++++++++++++++--- src/coreclr/jit/emitriscv64.h | 1 + 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index c863c5b531e988..e7df05c7e0cfc8 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2445,6 +2445,32 @@ BYTE* emitter::emitOutputInstr_Rellocation(BYTE* dst, const instrDesc* id, instr return dst; } +static ssize_t TakeImm20(ssize_t immediate) +{ + static constexpr unsigned kImm20Mask = 0xfffff; + + return (immediate >> 12) & kImm20Mask; +} + +static ssize_t TakeImm12(ssize_t immediate) +{ + static constexpr unsigned kImm12Mask = 0xfff; + + return immediate & 0xfff; +} + +static ssize_t TakeUpperWord(ssize_t immediate) +{ + return immediate >> 32; +} + +static ssize_t TakeLowerWord(ssize_t immediate) +{ + static constexpr size_t kWordMask = 0xffffffff; + + return immediate & kWordMask; +} + BYTE* emitter::emitOutputInstr_Addi(BYTE* dst, const instrDesc* id) { ssize_t immediate = static_cast(id->idAddr()->iiaAddr); @@ -2453,10 +2479,14 @@ BYTE* emitter::emitOutputInstr_Addi(BYTE* dst, const instrDesc* id) switch (id->idCodeSize()) { case 8: - dst = emitOutputInstr_Addi8(dst, id, immediate, reg1); + return emitOutputInstr_Addi8(dst, id, immediate, reg1); + case 32: + return emitOutputInstr_Addi32(dst, id, immediate, reg1); + default: break; } - return dst; + unreached(); + return nullptr; } BYTE* emitter::emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) @@ -2470,12 +2500,23 @@ BYTE* emitter::emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t imm } else { - dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, immediate + 0x800); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, immediate & 0xfff); + dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, TakeImm20(immediate)); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, TakeImm12(immediate)); } return dst; } +BYTE* emitter::emitOutputInstr_Addi32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) +{ + ssize_t upperWord = TakeUpperWord(immediate); + dst += emitOutput_UTypeInstr(dst, INS_lui, reg, TakeImm20(upperWord)); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, TakeImm12(upperWord)); + ssize_t lowerWord = TakeLowerWord(immediate); + dst += emitOutput_RTypeInstr(dst, INS_slli, reg1, reg1, 11); + // TODO + return dst; +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index cd6caac2175d55..151d1fd95957eb 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -112,6 +112,7 @@ unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm2 BYTE* emitOutputInstr_Rellocation(BYTE* dst, const instrDesc* id, instruction* ins); BYTE* emitOutputInstr_Addi(BYTE* dst, const instrDesc* id); BYTE* emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); +BYTE* emitOutputInstr_Addi32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); /************************************************************************/ /* Public inline informational methods */ From bdf048941dce848a4f90734a16ec0f0168ecacbf Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 20 Dec 2023 10:09:08 +0100 Subject: [PATCH 031/106] Reverted changes from la --- src/coreclr/jit/emit.h | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index c6134353ed3f61..9495605fd9594c 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -936,7 +936,7 @@ class emitter // TODO-Cleanup: We should really add a DEBUG-only tag to this union so we can add asserts // about reading what we think is here, to avoid unexpected corruption issues. -#if !defined(TARGET_ARM64) && !defined(TARGET_LOONGARCH64) && !defined(TARGET_RISCV64) +#if !defined(TARGET_ARM64) && !defined(TARGET_LOONGARCH64) emitLclVarAddr iiaLclVar; #endif BasicBlock* iiaBBlabel; @@ -990,18 +990,18 @@ class emitter regNumber _idReg3 : REGNUM_BITS; regNumber _idReg4 : REGNUM_BITS; }; -#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#elif defined(TARGET_LOONGARCH64) struct { + unsigned int iiaEncodedInstr; // instruction's binary encoding. regNumber _idReg3 : REGNUM_BITS; regNumber _idReg4 : REGNUM_BITS; - unsigned int iiaEncodedInstr; // instruction's binary encoding. }; struct { - emitLclVarAddr iiaLclVar; int iiaJmpOffset; // temporary saving the offset of jmp or data. + emitLclVarAddr iiaLclVar; }; void iiaSetInstrEncode(unsigned int encode) @@ -1021,6 +1021,22 @@ class emitter { return iiaJmpOffset; } +#elif defined(TARGET_RISCV64) + struct + { + regNumber _idReg3 : REGNUM_BITS; + regNumber _idReg4 : REGNUM_BITS; + unsigned int iiaEncodedInstr; // instruction's binary encoding. + }; + + void iiaSetInstrEncode(unsigned int encode) + { + iiaEncodedInstr = encode; + } + unsigned int iiaGetInstrEncode() const + { + return iiaEncodedInstr; + } #endif // defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) } _idAddrUnion; From c1a0c4a96eb62c4a14f15b07f1c426b3f1523a1d Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 20 Dec 2023 10:23:32 +0100 Subject: [PATCH 032/106] Fixed format bug --- src/coreclr/jit/emit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 9495605fd9594c..af8012e1dba020 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1139,7 +1139,7 @@ class emitter } #elif defined(TARGET_LOONGARCH64) - unsigned idCodeSize() const + unsigned idCodeSize() const { return _idCodeSize; } From 50f99d3cc67685ed2834150ae41e98f55014a2f9 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 20 Dec 2023 10:24:15 +0100 Subject: [PATCH 033/106] Fixed comment --- src/coreclr/jit/emit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index af8012e1dba020..148339bae4fc5a 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1037,7 +1037,7 @@ class emitter { return iiaEncodedInstr; } -#endif // defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#endif // defined(TARGET_RISCV64) } _idAddrUnion; From 694e53d2610af32d03e07d9365607e4784032d5f Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 09:22:50 +0100 Subject: [PATCH 034/106] Renamed some of the emitters --- src/coreclr/jit/emitriscv64.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index e7df05c7e0cfc8..deaf1760e08f78 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2445,26 +2445,34 @@ BYTE* emitter::emitOutputInstr_Rellocation(BYTE* dst, const instrDesc* id, instr return dst; } -static ssize_t TakeImm20(ssize_t immediate) +static ssize_t Upper20BitsOfWord(ssize_t word) { static constexpr unsigned kImm20Mask = 0xfffff; return (immediate >> 12) & kImm20Mask; } -static ssize_t TakeImm12(ssize_t immediate) +static ssize_t Upper20BitsOfWordSignExtend(ssize_t word) +{ + static constexpr unsigned kImm20Mask = 0xfffff; + static constexpr unsigned kSignExtend = 1 << 11; + + return ((immediate + kSignExtend) >> 12) & kImm20Mask; +} + +static ssize_t Lower12BitsOfWord(ssize_t word) { static constexpr unsigned kImm12Mask = 0xfff; - return immediate & 0xfff; + return immediate & kImm12Mask; } -static ssize_t TakeUpperWord(ssize_t immediate) +static ssize_t UpperWordOfDoubleWord(ssize_t immediate) { return immediate >> 32; } -static ssize_t TakeLowerWord(ssize_t immediate) +static ssize_t LowerWordOfDoubleWord(ssize_t immediate) { static constexpr size_t kWordMask = 0xffffffff; @@ -2500,8 +2508,8 @@ BYTE* emitter::emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t imm } else { - dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, TakeImm20(immediate)); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, TakeImm12(immediate)); + dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, Upper20BitsOfWord(immediate)); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, Lower12BitsOfWord(immediate)); } return dst; } @@ -2509,8 +2517,8 @@ BYTE* emitter::emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t imm BYTE* emitter::emitOutputInstr_Addi32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) { ssize_t upperWord = TakeUpperWord(immediate); - dst += emitOutput_UTypeInstr(dst, INS_lui, reg, TakeImm20(upperWord)); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, TakeImm12(upperWord)); + dst += emitOutput_UTypeInstr(dst, INS_lui, reg, Upper20BitsOfWord(upperWord)); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, Lower12BitsOfWord(upperWord)); ssize_t lowerWord = TakeLowerWord(immediate); dst += emitOutput_RTypeInstr(dst, INS_slli, reg1, reg1, 11); // TODO From a348d73aa50e8a4cdedd95d4930d0e3a3371d43a Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 09:31:28 +0100 Subject: [PATCH 035/106] Added some comments --- src/coreclr/jit/emitriscv64.cpp | 49 +++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index deaf1760e08f78..d7ab54ea8f3b7e 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2291,6 +2291,14 @@ static constexpr unsigned kInstructionOpcodeMask = 0x7f; static constexpr unsigned kInstructionFunct3Mask = 0x7000; static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; + +/***************************************************************************** + * + * Emit a 32-bit RISCV64 R-Type instruction to the given buffer. Returns a + * length of an encoded instruction opcode + * + */ + unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const { #ifdef DEBUG @@ -2307,6 +2315,13 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7)); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 I-Type instruction to the given buffer. Returns a + * length of an encoded instruction opcode + * + */ + unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const { #ifdef DEBUG @@ -2321,6 +2336,13 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, imm12)); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 S-Type instruction to the given buffer. Returns a + * length of an encoded instruction opcode + * + */ + unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const { #ifdef DEBUG @@ -2335,12 +2357,26 @@ unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1 return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2, imm12)); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 U-Type instruction to the given buffer. Returns a + * length of an encoded instruction opcode + * + */ + unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const { unsigned insCode = emitInsCode(ins); return emitOutput_Instr(dst, insEncodeUTypeInstr(insCode, rd, imm20)); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 B-Type instruction to the given buffer. Returns a + * length of an encoded instruction opcode + * + */ + unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const { #ifdef DEBUG @@ -2355,6 +2391,13 @@ unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1 return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13)); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 J-Type instruction to the given buffer. Returns a + * length of an encoded instruction opcode + * + */ + unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm21) const { unsigned insCode = emitInsCode(ins); @@ -2386,6 +2429,12 @@ void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, dstAddr = emitOffsetToPtr(dstOffs); } +/***************************************************************************** + * + * Calculates a current jump instruction distance + * + */ + ssize_t emitter::emitOutputInstrJumpDistance(const BYTE* dst, const BYTE* src, const insGroup* ig, instrDescJmp* jmp) { UNATIVE_OFFSET srcOffs = emitCurCodeOffs(src); From daf5c2a80777fbc2e791f0abad645f2f28dfc8fd Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 10:52:54 +0100 Subject: [PATCH 036/106] Improved implementation and finished addi32 --- src/coreclr/jit/emitriscv64.cpp | 56 ++++++++++++++++++++++----------- src/coreclr/jit/utils.h | 10 ++++++ 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index d7ab54ea8f3b7e..e0f7f68fd93b22 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2494,26 +2494,42 @@ BYTE* emitter::emitOutputInstr_Rellocation(BYTE* dst, const instrDesc* id, instr return dst; } -static ssize_t Upper20BitsOfWord(ssize_t word) +static constexpr size_t NBitMask(uint8_t bits) { + return (bits == 63) ? 0xefffffffffffffff : (static_cast(1) << (bits + 1)) - 1; +} + +template +static ssize_t LowerNBitsOfWord(ssize_t word) { - static constexpr unsigned kImm20Mask = 0xfffff; + static_assert(MaskSize < 32, "Given mask size is bigger tham the word itself"); + static_assert(MaskSize > 0, "Given mask size cannot be zero"); + + static constexpr size_t kMask = NBitMask(MaskSize); - return (immediate >> 12) & kImm20Mask; + return word & kMask; } -static ssize_t Upper20BitsOfWordSignExtend(ssize_t word) +template +static ssize_t UpperNBitsOfWord(ssize_t word) { - static constexpr unsigned kImm20Mask = 0xfffff; - static constexpr unsigned kSignExtend = 1 << 11; + static_assert(MaskSize < 32, "Given mask size is bigger tham the word itself"); + static_assert(MaskSize > 0, "Given mask size cannot be zero"); - return ((immediate + kSignExtend) >> 12) & kImm20Mask; + static constexpr size_t kMask = NBitMask(MaskSize); + static constexpr size_t kShift = 32 - MaskSize; + + return (word >> kShift) & kMask; } -static ssize_t Lower12BitsOfWord(ssize_t word) +template +static ssize_t UpperNBitsOfWordSignExtend(ssize_t word) { - static constexpr unsigned kImm12Mask = 0xfff; + static_assert(MaskSize < 32, "Given mask size is bigger tham the word itself"); + static_assert(MaskSize > 0, "Given mask size cannot be zero"); + + static constexpr unsigned kSignExtend = 1 << (32 - MaskSize - 1); - return immediate & kImm12Mask; + return UpperNBitsOfWord(word + kSignExtend); } static ssize_t UpperWordOfDoubleWord(ssize_t immediate) @@ -2530,7 +2546,7 @@ static ssize_t LowerWordOfDoubleWord(ssize_t immediate) BYTE* emitter::emitOutputInstr_Addi(BYTE* dst, const instrDesc* id) { - ssize_t immediate = static_cast(id->idAddr()->iiaAddr); + ssize_t immediate = BitCast(id->idAddr()->iiaAddr); const regNumber reg1 = id->idReg1(); switch (id->idCodeSize()) @@ -2557,20 +2573,24 @@ BYTE* emitter::emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t imm } else { - dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, Upper20BitsOfWord(immediate)); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, Lower12BitsOfWord(immediate)); + dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, UpperNBitsOfWordSignExtend<20>(immediate)); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<12>(immediate)); } return dst; } BYTE* emitter::emitOutputInstr_Addi32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) { - ssize_t upperWord = TakeUpperWord(immediate); - dst += emitOutput_UTypeInstr(dst, INS_lui, reg, Upper20BitsOfWord(upperWord)); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, Lower12BitsOfWord(upperWord)); - ssize_t lowerWord = TakeLowerWord(immediate); + ssize_t upperWord = UpperWordOfDoubleWord(immediate); + dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, UpperNBitsOfWordSignExtend<20>(upperWord)); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<12>(upperWord)); + ssize_t lowerWord = LowerWordOfDoubleWord(immediate); + dst += emitOutput_RTypeInstr(dst, INS_slli, reg1, reg1, 11); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<11>(lowerWord >> 21)); dst += emitOutput_RTypeInstr(dst, INS_slli, reg1, reg1, 11); - // TODO + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<11>(lowerWord >> 10)); + dst += emitOutput_RTypeInstr(dst, INS_slli, reg1, reg1, 10); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<10>(lowerWord)); return dst; } diff --git a/src/coreclr/jit/utils.h b/src/coreclr/jit/utils.h index 1eaa16d67ba81e..921be13daf0569 100644 --- a/src/coreclr/jit/utils.h +++ b/src/coreclr/jit/utils.h @@ -1086,4 +1086,14 @@ bool CastFromFloatOverflows(float fromValue, var_types toType); bool CastFromDoubleOverflows(double fromValue, var_types toType); } +template +T BitCast(const U& value) +{ + static_assert(sizeof(U) == sizeof(T), "T and U have to have the same size"); + + T result; + memcpy(&result, &value, sizeof(T)); + return result; +} + #endif // _UTILS_H_ From e4689618355063e74db9de022ca7835a50c61817 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 10:58:39 +0100 Subject: [PATCH 037/106] Microimprovements --- src/coreclr/jit/emitriscv64.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index e0f7f68fd93b22..e3a303b4435211 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2512,21 +2512,14 @@ static ssize_t LowerNBitsOfWord(ssize_t word) template static ssize_t UpperNBitsOfWord(ssize_t word) { - static_assert(MaskSize < 32, "Given mask size is bigger tham the word itself"); - static_assert(MaskSize > 0, "Given mask size cannot be zero"); - - static constexpr size_t kMask = NBitMask(MaskSize); static constexpr size_t kShift = 32 - MaskSize; - return (word >> kShift) & kMask; + return LowerNBitsOfWord(word >> kShift); } template static ssize_t UpperNBitsOfWordSignExtend(ssize_t word) { - static_assert(MaskSize < 32, "Given mask size is bigger tham the word itself"); - static_assert(MaskSize > 0, "Given mask size cannot be zero"); - static constexpr unsigned kSignExtend = 1 << (32 - MaskSize - 1); return UpperNBitsOfWord(word + kSignExtend); From 8d9141832dac5fdc76347c8ee7c58b5ae7362c4d Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 11:10:32 +0100 Subject: [PATCH 038/106] Quickfix to upperNBitsOfWord --- 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 e3a303b4435211..059d9a50d9d8ad 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2514,7 +2514,7 @@ static ssize_t UpperNBitsOfWord(ssize_t word) { static constexpr size_t kShift = 32 - MaskSize; - return LowerNBitsOfWord(word >> kShift); + return LowerNBitsOfWord(word >> kShift); } template From 5b350c28366cf8264f03d8bc11ae49748f2b18f7 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 11:25:45 +0100 Subject: [PATCH 039/106] Finished substituting instr_optsi --- src/coreclr/jit/emitriscv64.cpp | 177 ++++++-------------------------- src/coreclr/jit/emitriscv64.h | 8 +- 2 files changed, 38 insertions(+), 147 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 059d9a50d9d8ad..0b1a44a0dddea5 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2291,7 +2291,6 @@ static constexpr unsigned kInstructionOpcodeMask = 0x7f; static constexpr unsigned kInstructionFunct3Mask = 0x7000; static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; - /***************************************************************************** * * Emit a 32-bit RISCV64 R-Type instruction to the given buffer. Returns a @@ -2470,31 +2469,8 @@ ssize_t emitter::emitOutputInstrJumpDistance(const BYTE* dst, const BYTE* src, c return distVal; } -BYTE* emitter::emitOutputInstr_Rellocation(BYTE* dst, const instrDesc* id, instruction* ins) +static constexpr size_t NBitMask(uint8_t bits) { - BYTE* const dstBase = dst; - const regNumber reg1 = id->idReg1(); - - dst += emitOutput_UTypeInstr(dst, INS_auipc, reg1, 0); - - if (id->idIsCnsReloc()) - { - *ins = INS_addi; - } - else - { - assert(id->idIsDspReloc()); - *ins = INS_ld; - } - - dst += emitOutput_ITypeInstr(dst, *ins, reg1, reg1, 0); - - emitRecordRelocation(dstBase, id->idAddr()->iiaAddr, IMAGE_REL_RISCV64_PC); - - return dst; -} - -static constexpr size_t NBitMask(uint8_t bits) { return (bits == 63) ? 0xefffffffffffffff : (static_cast(1) << (bits + 1)) - 1; } @@ -2537,7 +2513,31 @@ static ssize_t LowerWordOfDoubleWord(ssize_t immediate) return immediate & kWordMask; } -BYTE* emitter::emitOutputInstr_Addi(BYTE* dst, const instrDesc* id) +BYTE* emitter::emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins) +{ + BYTE* const dstBase = dst; + const regNumber reg1 = id->idReg1(); + + dst += emitOutput_UTypeInstr(dst, INS_auipc, reg1, 0); + + if (id->idIsCnsReloc()) + { + *ins = INS_addi; + } + else + { + assert(id->idIsDspReloc()); + *ins = INS_ld; + } + + dst += emitOutput_ITypeInstr(dst, *ins, reg1, reg1, 0); + + emitRecordRelocation(dstBase, id->idAddr()->iiaAddr, IMAGE_REL_RISCV64_PC); + + return dst; +} + +BYTE* emitter::emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id) { ssize_t immediate = BitCast(id->idAddr()->iiaAddr); const regNumber reg1 = id->idReg1(); @@ -2545,9 +2545,9 @@ BYTE* emitter::emitOutputInstr_Addi(BYTE* dst, const instrDesc* id) switch (id->idCodeSize()) { case 8: - return emitOutputInstr_Addi8(dst, id, immediate, reg1); + return emitOutputInstr_OptsI8(dst, id, immediate, reg1); case 32: - return emitOutputInstr_Addi32(dst, id, immediate, reg1); + return emitOutputInstr_OptsI32(dst, id, immediate, reg1); default: break; } @@ -2555,7 +2555,7 @@ BYTE* emitter::emitOutputInstr_Addi(BYTE* dst, const instrDesc* id) return nullptr; } -BYTE* emitter::emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) +BYTE* emitter::emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) { if (id->idReg2()) { @@ -2572,7 +2572,7 @@ BYTE* emitter::emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t imm return dst; } -BYTE* emitter::emitOutputInstr_Addi32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) +BYTE* emitter::emitOutputInstr_OptsI32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) { ssize_t upperWord = UpperWordOfDoubleWord(immediate); dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, UpperNBitsOfWordSignExtend<20>(upperWord)); @@ -2614,123 +2614,14 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) switch (insOp) { case INS_OPTS_RELOC: - dst = emitOutputInstr_Rellocation(dst, id, &ins); + dst = emitOutputInstr_OptsReloc(dst, id, &ins); sz = sizeof(instrDesc); break; case INS_OPTS_I: - { - ins = INS_addi; - ssize_t imm = (ssize_t)(id->idAddr()->iiaAddr); - regNumber reg1 = id->idReg1(); - - switch (id->idCodeSize()) - { - case 8: - { - if (id->idReg2()) - { // special for INT64_MAX or UINT32_MAX; - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)REG_R0 << 15; - code |= 0xfff << 10; - - *(code_t*)dstRW = code; - dstRW += 4; - - ssize_t ui6 = (imm == INT64_MAX) ? 1 : 32; - code = emitInsCode(INS_srli); - code |= ((code_t)(reg1 << 7) | ((code_t)(reg1 << 15)) | (ui6 << 20)); - *(code_t*)dstRW = code; - } - else - { - code = emitInsCode(INS_lui); - code |= (code_t)(reg1 << 7); - code |= ((code_t)((imm + 0x800) >> 12) & 0xfffff) << 12; - - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)(imm & 0xfff) << 20; - *(code_t*)dstRW = code; - } - break; - } - case 32: - { - ssize_t high = (imm >> 32) & 0xffffffff; - code = emitInsCode(INS_lui); - code |= (code_t)reg1 << 7; - code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; - - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)(high & 0xfff) << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - ssize_t low = imm & 0xffffffff; - - code = emitInsCode(INS_slli); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)11 << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)((low >> 21) & 0x7ff) << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)11 << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)((low >> 10) & 0x7ff) << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)10 << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)((low)&0x3ff) << 20; - *(code_t*)dstRW = code; - break; - } - default: - unreached(); - break; - } - + dst = emitOutputInstr_OptsI(dst, id); ins = INS_addi; - dstRW += 4; - - sz = sizeof(instrDesc); - } - break; + sz = sizeof(instrDesc); + break; case INS_OPTS_RC: { // Reference to JIT data diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 151d1fd95957eb..b5b071e30bedaa 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -109,10 +109,10 @@ unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm2 unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const; unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm21) const; -BYTE* emitOutputInstr_Rellocation(BYTE* dst, const instrDesc* id, instruction* ins); -BYTE* emitOutputInstr_Addi(BYTE* dst, const instrDesc* id); -BYTE* emitOutputInstr_Addi8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); -BYTE* emitOutputInstr_Addi32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); +BYTE* emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins); +BYTE* emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id); +BYTE* emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); +BYTE* emitOutputInstr_OptsI32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); /************************************************************************/ /* Public inline informational methods */ From 4aaf35fd60f1c8454a439c430f32a0cd0392ee9a Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 11:32:27 +0100 Subject: [PATCH 040/106] Fixed bug in mask --- 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 0b1a44a0dddea5..810af412707b0b 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2471,7 +2471,7 @@ ssize_t emitter::emitOutputInstrJumpDistance(const BYTE* dst, const BYTE* src, c static constexpr size_t NBitMask(uint8_t bits) { - return (bits == 63) ? 0xefffffffffffffff : (static_cast(1) << (bits + 1)) - 1; + return (static_cast(1) << bits) - 1; } template @@ -2508,7 +2508,7 @@ static ssize_t UpperWordOfDoubleWord(ssize_t immediate) static ssize_t LowerWordOfDoubleWord(ssize_t immediate) { - static constexpr size_t kWordMask = 0xffffffff; + static constexpr size_t kWordMask = NBitMask(32); return immediate & kWordMask; } From 3a7764b2e0509029b36ead871af703ed8a959e03 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 12:03:35 +0100 Subject: [PATCH 041/106] Added emitOutputInstr_OptsRcReloc and prelimiary parent function --- src/coreclr/jit/emitriscv64.cpp | 52 +++++++++++++++++++++++++++++++++ src/coreclr/jit/emitriscv64.h | 2 ++ 2 files changed, 54 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 810af412707b0b..23180ef93d6f99 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2587,6 +2587,58 @@ BYTE* emitter::emitOutputInstr_OptsI32(BYTE* dst, const instrDesc* id, ssize_t i return dst; } +BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instruction* ins) +{ +#ifdef DEBUG + assert(id->idAddr()->iiaIsJitDataOffset()); + assert(id->idGCref() == GCT_NONE); + + int dataOffs = id->idAddr()->iiaGetJitDataOffset(); + assert(dataOffs >= 0); + + ssize_t immediate = emitGetInsSc(id); + assert((immediate >= 0) && (immediate < 0x4000)); // 0x4000 is arbitrary, currently 'imm' is always 0. + + unsigned offset = static_cast(dataOffs + immediate); + assert(offset < emitDataSize()); +#endif // DEBUG + + *ins = id->idIns(); + regNumber reg1 = id->idReg1(); + + if (id->idIsReloc()) + { + return emitOutputInstr_OptsRcReloc(dst, id, ins, reg1); + } + return nullptr; +} + +BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instruction* ins, regNumber reg1) +{ + ssize_t immediate = BitCast(emitConsBlock) - BitCast(dst); + assert(immediate > 0); + assert((immediate & 0x03) == 0); + + ssize_t offset = LowerNBitsOfWord<12>(immediate); + assert(isValidSimm20(UpperNBitsOfWordSignExtend<20>(immediate))); + + regNumber rsvdReg = codeGen->rsGetRsvdReg(); + dst += emitOutput_UTypeInstr(dst, INS_auipc, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); + + if (*ins == INS_jal) + { + assert(isGeneralRegister(reg1)); + *ins = INS_addi; + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, rsvdReg, offset); + } + else + { + assert(((reg1 & NBitMask(7)) == reg1)); + dst += emitOutput_ITypeInstr(dst, *ins, reg1, rsvdReg, offset); + } + return dst; +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index b5b071e30bedaa..c42e2e5647c9bd 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -113,6 +113,8 @@ BYTE* emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins BYTE* emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id); BYTE* emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); BYTE* emitOutputInstr_OptsI32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); +BYTE* emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instruction* ins); +BYTE* emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instruction* ins, regNumber reg1); /************************************************************************/ /* Public inline informational methods */ From 6899d5bf616ec4be5f0a3684c021fd3b88b08361 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 12:24:43 +0100 Subject: [PATCH 042/106] Added emitOutput_OptsRcNoReloc --- src/coreclr/jit/emitriscv64.cpp | 31 +++++++++++++++++++++++++------ src/coreclr/jit/emitriscv64.h | 1 + 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 23180ef93d6f99..d72b7d2547caf4 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2589,7 +2589,6 @@ BYTE* emitter::emitOutputInstr_OptsI32(BYTE* dst, const instrDesc* id, ssize_t i BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instruction* ins) { -#ifdef DEBUG assert(id->idAddr()->iiaIsJitDataOffset()); assert(id->idGCref() == GCT_NONE); @@ -2601,7 +2600,6 @@ BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instructio unsigned offset = static_cast(dataOffs + immediate); assert(offset < emitDataSize()); -#endif // DEBUG *ins = id->idIns(); regNumber reg1 = id->idReg1(); @@ -2610,7 +2608,7 @@ BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instructio { return emitOutputInstr_OptsRcReloc(dst, id, ins, reg1); } - return nullptr; + return emitOutputInstr_OptsRcNoReloc(dst, id, ins, offset, reg1); } BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instruction* ins, regNumber reg1) @@ -2630,12 +2628,33 @@ BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instr assert(isGeneralRegister(reg1)); *ins = INS_addi; dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, rsvdReg, offset); + return dst; } - else + assert(((reg1 & NBitMask(7)) == reg1)); + dst += emitOutput_ITypeInstr(dst, *ins, reg1, rsvdReg, offset); + return dst; +} + +BYTE* emitter::emitOutputInstr_OptsRcNoReloc( + BYTE* dst, const instrDesc* id, instruction* ins, unsigned offset, regNumber reg1) +{ + ssize_t immediate = BitCast(emitConsBlock) + offset; + assert((immediate >> 40) == 0); + regNumber rsvdReg = codeGen->rsGetRsvdReg(); + ssize_t high = immediate >> 11; + + if (*ins == INS_jal) { - assert(((reg1 & NBitMask(7)) == reg1)); - dst += emitOutput_ITypeInstr(dst, *ins, reg1, rsvdReg, offset); + dst += emitOutput_UTypeInstr(INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(high)); + dst += emitOutput_ITypeInstr(INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(high)); + dst += emitOutput_RTypeInstr(INS_ssli, rsvdReg, rsvdReg, 11); + dst += emitOutput_ITypeInstr(INS_addi, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); + return dst; } + dst += emitOutput_UTypeInstr(INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(high)); + dst += emitOutput_ITypeInstr(INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(high)); + dst += emitOutput_RTypeInstr(INS_slli, rsvdReg, rsvdReg, 11); + dst += emitOutput_ITypeInstr(*ins, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); return dst; } diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index c42e2e5647c9bd..a592e88dd14757 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -115,6 +115,7 @@ BYTE* emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, BYTE* emitOutputInstr_OptsI32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); BYTE* emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instruction* ins, regNumber reg1); +BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, const instrDesc* id, instruction* ins, unsigned offset, regNumber reg1); /************************************************************************/ /* Public inline informational methods */ From 2a7c35446c69cc49bbd2fd81f2f91f0bc87e64d8 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 13:06:49 +0100 Subject: [PATCH 043/106] Improvements in OptsRc --- src/coreclr/jit/emitriscv64.cpp | 27 ++++++++++----------------- src/coreclr/jit/emitriscv64.h | 2 +- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index d72b7d2547caf4..4ec25cbf821f8b 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2608,7 +2608,7 @@ BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instructio { return emitOutputInstr_OptsRcReloc(dst, id, ins, reg1); } - return emitOutputInstr_OptsRcNoReloc(dst, id, ins, offset, reg1); + return emitOutputInstr_OptsRcNoReloc(dst, id, *ins, offset, reg1); } BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instruction* ins, regNumber reg1) @@ -2623,38 +2623,31 @@ BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instr regNumber rsvdReg = codeGen->rsGetRsvdReg(); dst += emitOutput_UTypeInstr(dst, INS_auipc, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); + instruction lastIns = *ins; + if (*ins == INS_jal) { assert(isGeneralRegister(reg1)); - *ins = INS_addi; - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, rsvdReg, offset); - return dst; + *ins = lastIns = INS_addi; } - assert(((reg1 & NBitMask(7)) == reg1)); - dst += emitOutput_ITypeInstr(dst, *ins, reg1, rsvdReg, offset); + dst += emitOutput_ITypeInstr(dst, lastIns, reg1, rsvdReg, offset); return dst; } BYTE* emitter::emitOutputInstr_OptsRcNoReloc( - BYTE* dst, const instrDesc* id, instruction* ins, unsigned offset, regNumber reg1) + BYTE* dst, const instrDesc* id, instruction ins, unsigned offset, regNumber reg1) { ssize_t immediate = BitCast(emitConsBlock) + offset; assert((immediate >> 40) == 0); regNumber rsvdReg = codeGen->rsGetRsvdReg(); - ssize_t high = immediate >> 11; - if (*ins == INS_jal) - { - dst += emitOutput_UTypeInstr(INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(high)); - dst += emitOutput_ITypeInstr(INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(high)); - dst += emitOutput_RTypeInstr(INS_ssli, rsvdReg, rsvdReg, 11); - dst += emitOutput_ITypeInstr(INS_addi, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); - return dst; - } + instruction lastIns = (ins == INS_jal) ? INS_addi : ins; + ssize_t high = immediate >> 11; + dst += emitOutput_UTypeInstr(INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(high)); dst += emitOutput_ITypeInstr(INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(high)); dst += emitOutput_RTypeInstr(INS_slli, rsvdReg, rsvdReg, 11); - dst += emitOutput_ITypeInstr(*ins, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); + dst += emitOutput_ITypeInstr(lastIns, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); return dst; } diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index a592e88dd14757..0cdb920b68d7f5 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -115,7 +115,7 @@ BYTE* emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, BYTE* emitOutputInstr_OptsI32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); BYTE* emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instruction* ins, regNumber reg1); -BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, const instrDesc* id, instruction* ins, unsigned offset, regNumber reg1); +BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, const instrDesc* id, instruction ins, unsigned offset, regNumber reg1); /************************************************************************/ /* Public inline informational methods */ From dca50f0aa7eadc860adfe2d1233c05363735c45a Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 13:23:31 +0100 Subject: [PATCH 044/106] Fixes and introduced an emitOutputInstr_OptsRc --- src/coreclr/jit/emit.cpp | 2 +- src/coreclr/jit/emit.h | 2 +- src/coreclr/jit/emitriscv64.cpp | 158 +++----------------------------- src/coreclr/jit/emitriscv64.h | 2 +- 4 files changed, 15 insertions(+), 149 deletions(-) diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 27056d0d710382..30789c41e4d176 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -9732,7 +9732,7 @@ void emitter::emitRemoveLastInstruction() * emitGetInsSC: Get the instruction's constant value. */ -cnsval_ssize_t emitter::emitGetInsSC(instrDesc* id) +cnsval_ssize_t emitter::emitGetInsSC(const instrDesc* id) const { #ifdef TARGET_ARM // should it be TARGET_ARMARCH? Why do we need this? Note that on ARM64 we store scaled immediates // for some formats diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 87c57113a6513a..c0f87835d6dc88 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -2079,7 +2079,7 @@ class emitter static const IS_INFO emitGetSchedInfo(insFormat f); #endif // TARGET_XARCH - cnsval_ssize_t emitGetInsSC(instrDesc* id); + cnsval_ssize_t emitGetInsSC(const instrDesc* id) const; unsigned emitInsCount; /************************************************************************/ diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 4ec25cbf821f8b..35d32d4321fe6a 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2595,7 +2595,7 @@ BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instructio int dataOffs = id->idAddr()->iiaGetJitDataOffset(); assert(dataOffs >= 0); - ssize_t immediate = emitGetInsSc(id); + ssize_t immediate = emitGetInsSC(id); assert((immediate >= 0) && (immediate < 0x4000)); // 0x4000 is arbitrary, currently 'imm' is always 0. unsigned offset = static_cast(dataOffs + immediate); @@ -2608,7 +2608,7 @@ BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instructio { return emitOutputInstr_OptsRcReloc(dst, id, ins, reg1); } - return emitOutputInstr_OptsRcNoReloc(dst, id, *ins, offset, reg1); + return emitOutputInstr_OptsRcNoReloc(dst, id, ins, offset, reg1); } BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instruction* ins, regNumber reg1) @@ -2635,19 +2635,19 @@ BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instr } BYTE* emitter::emitOutputInstr_OptsRcNoReloc( - BYTE* dst, const instrDesc* id, instruction ins, unsigned offset, regNumber reg1) + BYTE* dst, const instrDesc* id, instruction* ins, unsigned offset, regNumber reg1) { ssize_t immediate = BitCast(emitConsBlock) + offset; assert((immediate >> 40) == 0); regNumber rsvdReg = codeGen->rsGetRsvdReg(); - instruction lastIns = (ins == INS_jal) ? INS_addi : ins; - ssize_t high = immediate >> 11; + instruction lastIns = (*ins == INS_jal) ? (*ins = INS_addi) : *ins; + UINT32 high = immediate >> 11; - dst += emitOutput_UTypeInstr(INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(high)); - dst += emitOutput_ITypeInstr(INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(high)); - dst += emitOutput_RTypeInstr(INS_slli, rsvdReg, rsvdReg, 11); - dst += emitOutput_ITypeInstr(lastIns, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); + dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(high)); + dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(high)); + dst += emitOutput_RTypeInstr(dst, INS_slli, rsvdReg, rsvdReg, 11); + dst += emitOutput_ITypeInstr(dst, lastIns, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); return dst; } @@ -2687,143 +2687,9 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) sz = sizeof(instrDesc); break; case INS_OPTS_RC: - { - // Reference to JIT data - assert(id->idAddr()->iiaIsJitDataOffset()); - assert(id->idGCref() == GCT_NONE); - - int doff = id->idAddr()->iiaGetJitDataOffset(); - assert(doff >= 0); - - ssize_t imm = emitGetInsSC(id); - assert((imm >= 0) && (imm < 0x4000)); // 0x4000 is arbitrary, currently 'imm' is always 0. - - unsigned dataOffs = (unsigned)(doff + imm); - - assert(dataOffs < emitDataSize()); - - ins = id->idIns(); - regNumber reg1 = id->idReg1(); - - if (id->idIsReloc()) - { - // get the addr-offset of the data. - imm = (ssize_t)emitConsBlock - (ssize_t)(dstRW - writeableOffset) + dataOffs; - assert(imm > 0); - assert(!(imm & 3)); - - doff = (int)(imm & 0xfff); - assert(isValidSimm20((imm + 0x800) >> 12)); - -#ifdef DEBUG - code = emitInsCode(INS_auipc); - assert(code == 0x00000017); -#endif - code = 0x00000017 | (codeGen->rsGetRsvdReg() << 7); - *(code_t*)dstRW = code | ((code_t)((imm + 0x800) & 0xfffff000)); - dstRW += 4; - - if (ins == INS_jal) - { - assert(isGeneralRegister(reg1)); - ins = INS_addi; -#ifdef DEBUG - code = emitInsCode(INS_addi); - assert(code == 0x00000013); -#endif - code = 0x00000013 | (codeGen->rsGetRsvdReg() << 15); - *(code_t*)dstRW = code | ((code_t)reg1 << 7) | (((code_t)doff & 0xfff) << 20); - } - else - { - code = emitInsCode(ins); - code |= (code_t)(reg1 & 0x1f) << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)(doff & 0xfff) << 20; - *(code_t*)dstRW = code; - } - dstRW += 4; - } - else - { - // get the addr of the data. - imm = (ssize_t)emitConsBlock + dataOffs; - - code = emitInsCode(INS_lui); - if (ins == INS_jal) - { - assert((imm >> 40) == 0); - - doff = imm & 0x7ff; - - UINT32 high = imm >> 11; - - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)(((high + 0x800) >> 12) << 12); - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)(high & 0xFFF) << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)11 << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - ins = INS_addi; - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)doff << 20; - *(code_t*)dstRW = code; - dstRW += 4; - } - else - { - assert((imm >> 40) == 0); - - doff = imm & 0x7ff; - UINT32 high = imm >> 11; - - code |= (code_t)(codeGen->rsGetRsvdReg() << 7); - code |= (code_t)(((high + 0x800) >> 12) << 12); - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)(high & 0xFFF) << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)11 << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(ins); - code |= (code_t)(reg1 & 0x1f) << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)doff << 20; - *(code_t*)dstRW = code; - dstRW += 4; - } - } - - sz = sizeof(instrDesc); - } - break; - + dst = emitOutputInstr_OptsRc(dst, id, &ins); + sz = sizeof(instrDesc); + break; case INS_OPTS_RL: { insGroup* tgtIG = (insGroup*)emitCodeGetCookie(id->idAddr()->iiaBBlabel); diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 0cdb920b68d7f5..a592e88dd14757 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -115,7 +115,7 @@ BYTE* emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, BYTE* emitOutputInstr_OptsI32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); BYTE* emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instruction* ins, regNumber reg1); -BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, const instrDesc* id, instruction ins, unsigned offset, regNumber reg1); +BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, const instrDesc* id, instruction* ins, unsigned offset, regNumber reg1); /************************************************************************/ /* Public inline informational methods */ From 851b75accbe71641bdd1da96e6cfbb5ef52d453f Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 13:32:06 +0100 Subject: [PATCH 045/106] Added emitOutputInstr_OptsRl and removed unused args from other functions --- src/coreclr/jit/emitriscv64.cpp | 32 +++++++++++++++++++++++++------- src/coreclr/jit/emitriscv64.h | 10 ++++++---- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 35d32d4321fe6a..b22b2b7941a09b 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2555,7 +2555,7 @@ BYTE* emitter::emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id) return nullptr; } -BYTE* emitter::emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) +BYTE* emitter::emitOutputInstr_OptsI8(BYTE* dst, ssize_t immediate, regNumber reg1) { if (id->idReg2()) { @@ -2572,7 +2572,7 @@ BYTE* emitter::emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t im return dst; } -BYTE* emitter::emitOutputInstr_OptsI32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) +BYTE* emitter::emitOutputInstr_OptsI32(BYTE* dst, ssize_t immediate, regNumber reg1) { ssize_t upperWord = UpperWordOfDoubleWord(immediate); dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, UpperNBitsOfWordSignExtend<20>(upperWord)); @@ -2606,12 +2606,12 @@ BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instructio if (id->idIsReloc()) { - return emitOutputInstr_OptsRcReloc(dst, id, ins, reg1); + return emitOutputInstr_OptsRcReloc(dst, ins, reg1); } - return emitOutputInstr_OptsRcNoReloc(dst, id, ins, offset, reg1); + return emitOutputInstr_OptsRcNoReloc(dst, ins, offset, reg1); } -BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instruction* ins, regNumber reg1) +BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, instruction* ins, regNumber reg1) { ssize_t immediate = BitCast(emitConsBlock) - BitCast(dst); assert(immediate > 0); @@ -2634,8 +2634,7 @@ BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instr return dst; } -BYTE* emitter::emitOutputInstr_OptsRcNoReloc( - BYTE* dst, const instrDesc* id, instruction* ins, unsigned offset, regNumber reg1) +BYTE* emitter::emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsigned offset, regNumber reg1) { ssize_t immediate = BitCast(emitConsBlock) + offset; assert((immediate >> 40) == 0); @@ -2651,6 +2650,25 @@ BYTE* emitter::emitOutputInstr_OptsRcNoReloc( return dst; } +BYTE* emitter::emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins) +{ + insGroup* targetInsGroup = static_cast(emitCodeGetCookie(id->idAddr()->iiaBBlabel)); + id->idAddr()->iiaIGlabel = targetInsGroup; + + regNumber reg1 = id->idReg1(); + assert(isGeneralRegister(reg1)); + if (id->idIsReloc()) + { + return emitOutputInstr_OptsRlReloc(dst, targetInsGroup->igOffs, ins); + } + return nullptr; +} + +BYTE* emitter::emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, instruction* ins, regNumber reg1) +{ + +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index a592e88dd14757..cb2144339c3f46 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -111,11 +111,13 @@ unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm2 BYTE* emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id); -BYTE* emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); -BYTE* emitOutputInstr_OptsI32(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); +BYTE* emitOutputInstr_OptsI8(BYTE* dst, ssize_t immediate, regNumber reg1); +BYTE* emitOutputInstr_OptsI32(BYTE* dst, ssize_t immediate, regNumber reg1); BYTE* emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instruction* ins); -BYTE* emitOutputInstr_OptsRcReloc(BYTE* dst, const instrDesc* id, instruction* ins, regNumber reg1); -BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, const instrDesc* id, instruction* ins, unsigned offset, regNumber reg1); +BYTE* emitOutputInstr_OptsRcReloc(BYTE* dst, instruction* ins, regNumber reg1); +BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsigned offset, regNumber reg1); +BYTE* emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins); +BYTE* emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, instruction* ins, regNumber reg1); /************************************************************************/ /* Public inline informational methods */ From 2296c9d17645dbc62c0221a1b3b282b6dfc5e79f Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 13:40:07 +0100 Subject: [PATCH 046/106] Added emitOutputInstr_OptsRlReloc --- src/coreclr/jit/emitriscv64.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index b22b2b7941a09b..1381f3f50c50fe 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2617,9 +2617,6 @@ BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, instruction* ins, regNumbe assert(immediate > 0); assert((immediate & 0x03) == 0); - ssize_t offset = LowerNBitsOfWord<12>(immediate); - assert(isValidSimm20(UpperNBitsOfWordSignExtend<20>(immediate))); - regNumber rsvdReg = codeGen->rsGetRsvdReg(); dst += emitOutput_UTypeInstr(dst, INS_auipc, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); @@ -2630,7 +2627,7 @@ BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, instruction* ins, regNumbe assert(isGeneralRegister(reg1)); *ins = lastIns = INS_addi; } - dst += emitOutput_ITypeInstr(dst, lastIns, reg1, rsvdReg, offset); + dst += emitOutput_ITypeInstr(dst, lastIns, reg1, rsvdReg, LowerNBitsOfWord<12>(immediate)); return dst; } @@ -2659,14 +2656,19 @@ BYTE* emitter::emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins assert(isGeneralRegister(reg1)); if (id->idIsReloc()) { - return emitOutputInstr_OptsRlReloc(dst, targetInsGroup->igOffs, ins); + return emitOutputInstr_OptsRlReloc(dst, BitCast(targetInsGroup->igOffs), ins); } return nullptr; } BYTE* emitter::emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, instruction* ins, regNumber reg1) { + ssize_t immediate = BitCast(emitCodeBlock) + igOffs - BitCast(dst); + assert((immediate)&0x03 == 0); // Is 32-bit instruction + dst += emitOutput_UTypeInstr(dst, INS_auipc, reg1, UpperNBitsOfWordSignExtend<20>(immediate)); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<12>(immediate)); + return dst; } /***************************************************************************** From 4b11390ab9cf5dda579bf7a3bf49dd1da362bcaf Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 14:37:37 +0100 Subject: [PATCH 047/106] Finished emitOutputInstr_OptsRcNoReloc --- src/coreclr/jit/emitriscv64.cpp | 59 ++++++++++++++++++++++++++------- src/coreclr/jit/emitriscv64.h | 7 ++-- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 1381f3f50c50fe..eea66ff84204c9 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2496,7 +2496,7 @@ static ssize_t UpperNBitsOfWord(ssize_t word) template static ssize_t UpperNBitsOfWordSignExtend(ssize_t word) { - static constexpr unsigned kSignExtend = 1 << (32 - MaskSize - 1); + static constexpr unsigned kSignExtend = 1 << (31 - MaskSize); return UpperNBitsOfWord(word + kSignExtend); } @@ -2513,6 +2513,21 @@ static ssize_t LowerWordOfDoubleWord(ssize_t immediate) return immediate & kWordMask; } +template +static ssize_t DoubleWordSignExtend(ssize_t doubleWord) +{ + static constexpr size_t kLowerSignExtend = 1 << (31 - LowerMaskSize); + static constexpr size_t kUpperSignExtend = static_cast(1) << (63 - UpperMaskSize); + + return doubleWord + kLowerSignExtend + kUpperSignExtend; +} + +template +static ssize_t UpperWordOfDoubleWordSignExtend(ssize_t doubleWord) +{ + return UpperWordOfDoubleWord(DoubleWordSignExtend(doubleWord)); +} + BYTE* emitter::emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins) { BYTE* const dstBase = dst; @@ -2547,7 +2562,7 @@ BYTE* emitter::emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id) case 8: return emitOutputInstr_OptsI8(dst, id, immediate, reg1); case 32: - return emitOutputInstr_OptsI32(dst, id, immediate, reg1); + return emitOutputInstr_OptsI32(dst, immediate, reg1); default: break; } @@ -2555,14 +2570,14 @@ BYTE* emitter::emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id) return nullptr; } -BYTE* emitter::emitOutputInstr_OptsI8(BYTE* dst, ssize_t immediate, regNumber reg1) +BYTE* emitter::emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) { if (id->idReg2()) { // special for INT64_MAX or UINT32_MAX dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, REG_R0, 0xfff); ssize_t shiftValue = (immediate == INT64_MAX) ? 1 : 32; - dst += emitOutput_RTypeInstr(dst, INS_srli, reg1, reg1, shiftValue); + dst += emitOutput_ITypeInstr(dst, INS_srli, reg1, reg1, shiftValue); } else { @@ -2578,11 +2593,11 @@ BYTE* emitter::emitOutputInstr_OptsI32(BYTE* dst, ssize_t immediate, regNumber r dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, UpperNBitsOfWordSignExtend<20>(upperWord)); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<12>(upperWord)); ssize_t lowerWord = LowerWordOfDoubleWord(immediate); - dst += emitOutput_RTypeInstr(dst, INS_slli, reg1, reg1, 11); + dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 11); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<11>(lowerWord >> 21)); - dst += emitOutput_RTypeInstr(dst, INS_slli, reg1, reg1, 11); + dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 11); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<11>(lowerWord >> 10)); - dst += emitOutput_RTypeInstr(dst, INS_slli, reg1, reg1, 10); + dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 10); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<10>(lowerWord)); return dst; } @@ -2642,7 +2657,7 @@ BYTE* emitter::emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsign dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(high)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(high)); - dst += emitOutput_RTypeInstr(dst, INS_slli, rsvdReg, rsvdReg, 11); + dst += emitOutput_ITypeInstr(dst, INS_slli, rsvdReg, rsvdReg, 11); dst += emitOutput_ITypeInstr(dst, lastIns, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); return dst; } @@ -2654,23 +2669,43 @@ BYTE* emitter::emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins regNumber reg1 = id->idReg1(); assert(isGeneralRegister(reg1)); + ssize_t igOffs = targetInsGroup->igOffs; + if (id->idIsReloc()) { - return emitOutputInstr_OptsRlReloc(dst, BitCast(targetInsGroup->igOffs), ins); + *ins = INS_addi; + return emitOutputInstr_OptsRlReloc(dst, igOffs, reg1); } - return nullptr; + *ins = INS_add; + return emitOutputInstr_OptsRlNoReloc(dst, igOffs, reg1); } -BYTE* emitter::emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, instruction* ins, regNumber reg1) +BYTE* emitter::emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber reg1) { ssize_t immediate = BitCast(emitCodeBlock) + igOffs - BitCast(dst); - assert((immediate)&0x03 == 0); // Is 32-bit instruction + assert((immediate & 0x03) == 0); dst += emitOutput_UTypeInstr(dst, INS_auipc, reg1, UpperNBitsOfWordSignExtend<20>(immediate)); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<12>(immediate)); return dst; } +BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumber reg1) +{ + ssize_t immediate = BitCast(emitCodeBlock) + igOffs; + assert((immediate >> (32 + 20)) == 0); + + regNumber rsvdReg = codeGen->rsGetRsvdReg(); + ssize_t upperSignExt = UpperWordOfDoubleWordSignExtend<12, 24>(immediate); + + dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); + dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(immediate)); + dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, REG_ZERO, LowerNBitsOfWord<12>(upperSignExt)); + dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 32); + dst += emitOutput_RTypeInstr(dst, INS_add, reg1, reg1, rsvdReg); + return dst; +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index cb2144339c3f46..7f86e90423d8fe 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -111,13 +111,16 @@ unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm2 BYTE* emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id); -BYTE* emitOutputInstr_OptsI8(BYTE* dst, ssize_t immediate, regNumber reg1); +BYTE* emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); BYTE* emitOutputInstr_OptsI32(BYTE* dst, ssize_t immediate, regNumber reg1); BYTE* emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsRcReloc(BYTE* dst, instruction* ins, regNumber reg1); BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsigned offset, regNumber reg1); BYTE* emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins); -BYTE* emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, instruction* ins, regNumber reg1); +BYTE* emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); +BYTE* emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); + +static constexpr unsigned kZeroRegister = 0; /************************************************************************/ /* Public inline informational methods */ From 33a0fc3dcb84d09ceb8e62a8cceedca831941853 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 14:49:01 +0100 Subject: [PATCH 048/106] Fixed bugs and finished opts rl --- src/coreclr/jit/emitriscv64.cpp | 94 +++++---------------------------- src/coreclr/jit/emitriscv64.h | 12 ++--- 2 files changed, 18 insertions(+), 88 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index eea66ff84204c9..2a0edb68f2cb3f 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2298,7 +2298,7 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; * */ -unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const +unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const { #ifdef DEBUG static constexpr unsigned kInstructionMask = @@ -2321,7 +2321,7 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, * */ -unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const +unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const { #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; @@ -2342,7 +2342,7 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, * */ -unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const +unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const { #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; @@ -2363,7 +2363,7 @@ unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1 * */ -unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const +unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm20) const { unsigned insCode = emitInsCode(ins); return emitOutput_Instr(dst, insEncodeUTypeInstr(insCode, rd, imm20)); @@ -2376,7 +2376,7 @@ unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, * */ -unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const +unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const { #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; @@ -2397,7 +2397,7 @@ unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1 * */ -unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm21) const +unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm21) const { unsigned insCode = emitInsCode(ins); return emitOutput_Instr(dst, insEncodeJTypeInstr(insCode, rd, imm21)); @@ -2517,9 +2517,9 @@ template static ssize_t DoubleWordSignExtend(ssize_t doubleWord) { static constexpr size_t kLowerSignExtend = 1 << (31 - LowerMaskSize); - static constexpr size_t kUpperSignExtend = static_cast(1) << (63 - UpperMaskSize); + static constexpr size_t kUpperSignExtend = static_cast(1) << (31 - UpperMaskSize); - return doubleWord + kLowerSignExtend + kUpperSignExtend; + return doubleWord + (kLowerSignExtend | kUpperSignExtend); } template @@ -2696,7 +2696,7 @@ BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumbe assert((immediate >> (32 + 20)) == 0); regNumber rsvdReg = codeGen->rsGetRsvdReg(); - ssize_t upperSignExt = UpperWordOfDoubleWordSignExtend<12, 24>(immediate); + ssize_t upperSignExt = UpperWordOfDoubleWordSignExtend<0, 12>(immediate); dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(immediate)); @@ -2746,79 +2746,9 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) sz = sizeof(instrDesc); break; case INS_OPTS_RL: - { - insGroup* tgtIG = (insGroup*)emitCodeGetCookie(id->idAddr()->iiaBBlabel); - id->idAddr()->iiaIGlabel = tgtIG; - - regNumber reg1 = id->idReg1(); - assert(isGeneralRegister(reg1)); - - if (id->idIsReloc()) - { - ssize_t imm = (ssize_t)tgtIG->igOffs; - imm = (ssize_t)emitCodeBlock + imm - (ssize_t)(dstRW - writeableOffset); - assert((imm & 3) == 0); - - int doff = (int)(imm & 0xfff); - assert(isValidSimm20((imm + 0x800) >> 12)); - - code = 0x00000017; - *(code_t*)dstRW = code | (code_t)reg1 << 7 | ((imm + 0x800) & 0xfffff000); - dstRW += 4; -#ifdef DEBUG - code = emitInsCode(INS_auipc); - assert(code == 0x00000017); - code = emitInsCode(INS_addi); - assert(code == 0x00000013); -#endif - ins = INS_addi; - *(code_t*)dstRW = 0x00000013 | ((code_t)reg1 << 7) | ((code_t)reg1 << 15) | ((doff & 0xfff) << 20); - } - else - { - ssize_t imm = (ssize_t)tgtIG->igOffs + (ssize_t)emitCodeBlock; - assert((imm >> (32 + 20)) == 0); - - code = emitInsCode(INS_lui); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= ((code_t)((imm + 0x800) >> 12) & 0xfffff) << 12; - - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)(imm & 0xfff) << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (((imm + 0x80000800) >> 32) & 0xfff) << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)32 << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - ins = INS_add; - code = emitInsCode(INS_add); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)codeGen->rsGetRsvdReg() << 20; - *(code_t*)dstRW = code; - } - - dstRW += 4; - - sz = sizeof(instrDesc); - } - break; + dst = emitOutputInstr_OptsRl(dst, id, &ins); + sz = sizeof(instrDesc); + break; case INS_OPTS_JALR: { instrDescJmp* jmp = (instrDescJmp*)id; diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 7f86e90423d8fe..170b2c9b4fa91f 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -102,12 +102,12 @@ static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, int imm20); static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm13); static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); -unsigned emitOutput_RTypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, unsigned rs2) const; -unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, unsigned rd, unsigned rs1, int imm12) const; -unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm12) const; -unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm20) const; -unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, unsigned rs1, unsigned rs2, int imm13) const; -unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, unsigned rd, int imm21) const; +unsigned emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const; +unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const; +unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const; +unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm20) const; +unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const; +unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm21) const; BYTE* emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id); From 429783f79bae23492666239c3473b8a54f706cfd Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 15:14:53 +0100 Subject: [PATCH 049/106] Added emitOutputInstr_OptsJalr --- src/coreclr/jit/emitriscv64.cpp | 23 +++++++++++++++++++++++ src/coreclr/jit/emitriscv64.h | 1 + 2 files changed, 24 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 2a0edb68f2cb3f..311091177e0bde 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2706,6 +2706,29 @@ BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumbe return dst; } +BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, const instrDescJmp* jmp, const insGroup* ig, instruction* ins) +{ + regNumber reg1 = id->idReg1(); + ssize_t immediate = emitOutputInstrJumpDistance(dst + writeableOffset, dst, ig, jmp) - 4; + assert((immediate & 0x03) == 0); + + *ins = jmp->idIns(); + assert(jmp->idCodeSize() > 4); // The original INS_OPTS_JALR: not used by now!!! + switch (jmp->idCodeSize()) + { + case 8: + return nullptr; + case 24: + return nullptr; + case 28: + return nullptr; + default: + break; + } + unreached(); + return nullptr; +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 170b2c9b4fa91f..5c735ead89af89 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -119,6 +119,7 @@ BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsigned offset BYTE* emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); BYTE* emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); +BYTE* emitOutputInstr_OptsJalr(BYTE* dst, const instrDescJmp* jmp, const insGroup* ig, instruction* ins); static constexpr unsigned kZeroRegister = 0; From 0cc47817e5baac38e1d1204bf486ca4964cf9b9a Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 15:33:46 +0100 Subject: [PATCH 050/106] Added emitOutputInstr_OptsJalr8 --- src/coreclr/jit/emitriscv64.cpp | 20 +++++++++++++++++++- src/coreclr/jit/emitriscv64.h | 1 + 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 311091177e0bde..74cadf70f46647 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2717,7 +2717,7 @@ BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, const instrDescJmp* jmp, cons switch (jmp->idCodeSize()) { case 8: - return nullptr; + return emitOutputInstr_OptsJalr8(dst, jmp, ins, immediate, reg1); case 24: return nullptr; case 28: @@ -2729,6 +2729,24 @@ BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, const instrDescJmp* jmp, cons return nullptr; } +static instruction ReverseBranchCondition(instruction ins) +{ + return ins ^ 0x1000; +} + +BYTE* emitter::emitOutputInstr_OptsJalr8( + BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate, regNumber reg1) +{ + assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || (INS_bnez == ins) || + (INS_beqz == ins)); + + regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? jmp->idReg2() : REG_R0; + + dst += emitOutput_BTypeInstr(ReverseBranchCondition(ins), reg1, reg2, 0x10); + dst += emitOutput_JTypeInstr(INS_Jal, REG_ZER0, immediate); + return dst; +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 5c735ead89af89..484656effdcd0f 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -120,6 +120,7 @@ BYTE* emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); BYTE* emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); BYTE* emitOutputInstr_OptsJalr(BYTE* dst, const instrDescJmp* jmp, const insGroup* ig, instruction* ins); +BYTE* emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate, regNumber reg1); static constexpr unsigned kZeroRegister = 0; From dcc623a9d6c2949a9023929e81be836779f3c024 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 15:46:31 +0100 Subject: [PATCH 051/106] Added special comparation inverter --- src/coreclr/jit/emitriscv64.cpp | 34 +++++++++++++++++++++++++++------ src/coreclr/jit/emitriscv64.h | 2 ++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 74cadf70f46647..a2bbc279374394 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2390,6 +2390,33 @@ unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13)); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 B-Type instruction with inverted comparation to + * the given buffer. Returns a length of an encoded instruction opcode + * + * Note: Replaces: + * - beqz with bnez and vice versa + * - beq with bne and vide versa + * - blt with bge and vide versa + * - bltu with bgeu and vice versa + */ + +unsigned emitter::emitOutput_BTypeInstr_InvertComparation( + BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const +{ +#ifdef DEBUG + static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; + + assert((ins & kInstructionMask) == 0); +#endif // DEBUG + + unsigned insCode = emitInsCode(ins) ^ 0x1000; + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13)); +} + /***************************************************************************** * * Emit a 32-bit RISCV64 J-Type instruction to the given buffer. Returns a @@ -2729,11 +2756,6 @@ BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, const instrDescJmp* jmp, cons return nullptr; } -static instruction ReverseBranchCondition(instruction ins) -{ - return ins ^ 0x1000; -} - BYTE* emitter::emitOutputInstr_OptsJalr8( BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate, regNumber reg1) { @@ -2742,7 +2764,7 @@ BYTE* emitter::emitOutputInstr_OptsJalr8( regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? jmp->idReg2() : REG_R0; - dst += emitOutput_BTypeInstr(ReverseBranchCondition(ins), reg1, reg2, 0x10); + dst += emitOutput_BTypeInstr_InvertComparation(ins, reg1, reg2, 0x10); dst += emitOutput_JTypeInstr(INS_Jal, REG_ZER0, immediate); return dst; } diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 484656effdcd0f..7c40656767628e 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -107,6 +107,8 @@ unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumb unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const; unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm20) const; unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const; +unsigned emitOutput_BTypeInstr_InvertComparation( + BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const; unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm21) const; BYTE* emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins); From 0308aa36ac5da9abc1f78d7b13054309bdae3522 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 16:24:48 +0100 Subject: [PATCH 052/106] Add emitOutputInstr_OptsJalr24 --- src/coreclr/jit/emitriscv64.cpp | 40 ++++++++++++++++++++++++++++----- src/coreclr/jit/emitriscv64.h | 3 ++- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index a2bbc279374394..4a4ba204292771 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2549,6 +2549,14 @@ static ssize_t DoubleWordSignExtend(ssize_t doubleWord) return doubleWord + (kLowerSignExtend | kUpperSignExtend); } +template +static ssize_t UpperWordDoubleWordSignExtend(ssize_t doubleWord) +{ + static constexpr size_t kUpperSignExtend = static_cast(1) << (31 - UpperMaskSize); + + return UpperWordOfDoubleWord(doubleWord + kUpperSignExtend); +} + template static ssize_t UpperWordOfDoubleWordSignExtend(ssize_t doubleWord) { @@ -2733,9 +2741,8 @@ BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumbe return dst; } -BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, const instrDescJmp* jmp, const insGroup* ig, instruction* ins) +BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insGroup* ig, instruction* ins) { - regNumber reg1 = id->idReg1(); ssize_t immediate = emitOutputInstrJumpDistance(dst + writeableOffset, dst, ig, jmp) - 4; assert((immediate & 0x03) == 0); @@ -2744,9 +2751,9 @@ BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, const instrDescJmp* jmp, cons switch (jmp->idCodeSize()) { case 8: - return emitOutputInstr_OptsJalr8(dst, jmp, ins, immediate, reg1); + return emitOutputInstr_OptsJalr8(dst, jmp, *ins, immediate, jmp->idReg1()); case 24: - return nullptr; + return emitOutputInstr_OptsJalr24(dst, *ins, immediate); case 28: return nullptr; default: @@ -2764,8 +2771,29 @@ BYTE* emitter::emitOutputInstr_OptsJalr8( regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? jmp->idReg2() : REG_R0; - dst += emitOutput_BTypeInstr_InvertComparation(ins, reg1, reg2, 0x10); - dst += emitOutput_JTypeInstr(INS_Jal, REG_ZER0, immediate); + dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, reg1, reg2, 0x10); + dst += emitOutput_JTypeInstr(dst, INS_jal, REG_ZERO, immediate); + return dst; +} + +BYTE* emitter::emitOutputInstr_OptsJalr24(BYTE* dst, instruction ins, ssize_t immediate) +{ + assert((ins == INS_jal) || (ins == INS_j)); + // Make target address with offset, then jump (JALR) with the target address + immediate -= 2 * 4; + ssize_t high = UpperWordDoubleWordSignExtend<0>(immediate); + + dst += emitOutput_UTypeInstr(dst, INS_lui, REG_RA, UpperNBitsOfWordSignExtend<20>(high)); + dst += emitOutput_ITypeInstr(dst, INS_addi, REG_RA, REG_RA, LowerNBitsOfWord<12>(high)); + dst += emitOutput_ITypeInstr(dst, INS_slli, REG_RA, REG_RA, 32); + + regNumber rsvdReg = codeGen->rsGetRsvdReg(); + ssize_t low = LowerWordOfDoubleWord(immediate); + + dst += emitOutput_UTypeInstr(dst, INS_auipc, rsvdReg, UpperNBitsOfWordSignExtend<20>(low)); + dst += emitOutput_RTypeInstr(dst, INS_add, rsvdReg, REG_RA, rsvdReg); + dst += emitOutput_ITypeInstr(dst, INS_jalr, REG_RA, rsvdReg, LowerNBitsOfWord<12>(low)); + return dst; } diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 7c40656767628e..f4f2fa0a37fba6 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -121,8 +121,9 @@ BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsigned offset BYTE* emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); BYTE* emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); -BYTE* emitOutputInstr_OptsJalr(BYTE* dst, const instrDescJmp* jmp, const insGroup* ig, instruction* ins); +BYTE* emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insGroup* ig, instruction* ins); BYTE* emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate, regNumber reg1); +BYTE* emitOutputInstr_OptsJalr24(BYTE* dst, instruction ins, ssize_t immediate); static constexpr unsigned kZeroRegister = 0; From f5f956203974b14fd495fdfd09f8a54c6f008e83 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 16:42:18 +0100 Subject: [PATCH 053/106] Added emitOutputInstr_OptsJalr28 --- src/coreclr/jit/emitriscv64.cpp | 38 +++++++++++++++++++++++++++------ src/coreclr/jit/emitriscv64.h | 3 ++- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 4a4ba204292771..c42f91195becd2 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2743,7 +2743,7 @@ BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumbe BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insGroup* ig, instruction* ins) { - ssize_t immediate = emitOutputInstrJumpDistance(dst + writeableOffset, dst, ig, jmp) - 4; + ssize_t immediate = emitOutputInstrJumpDistance(dst + writeableOffset, dst, ig, jmp) - 4; assert((immediate & 0x03) == 0); *ins = jmp->idIns(); @@ -2751,11 +2751,11 @@ BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insG switch (jmp->idCodeSize()) { case 8: - return emitOutputInstr_OptsJalr8(dst, jmp, *ins, immediate, jmp->idReg1()); + return emitOutputInstr_OptsJalr8(dst, jmp, *ins, immediate); case 24: return emitOutputInstr_OptsJalr24(dst, *ins, immediate); case 28: - return nullptr; + return emitOutputInstr_OptsJalr28(dst, jmp, *ins, immediate); default: break; } @@ -2763,15 +2763,14 @@ BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insG return nullptr; } -BYTE* emitter::emitOutputInstr_OptsJalr8( - BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate, regNumber reg1) +BYTE* emitter::emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate) { assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || (INS_bnez == ins) || (INS_beqz == ins)); regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? jmp->idReg2() : REG_R0; - dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, reg1, reg2, 0x10); + dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, jmp->idReg1(), reg2, 0x10); dst += emitOutput_JTypeInstr(dst, INS_jal, REG_ZERO, immediate); return dst; } @@ -2788,7 +2787,32 @@ BYTE* emitter::emitOutputInstr_OptsJalr24(BYTE* dst, instruction ins, ssize_t im dst += emitOutput_ITypeInstr(dst, INS_slli, REG_RA, REG_RA, 32); regNumber rsvdReg = codeGen->rsGetRsvdReg(); - ssize_t low = LowerWordOfDoubleWord(immediate); + ssize_t low = LowerWordOfDoubleWord(immediate); + + dst += emitOutput_UTypeInstr(dst, INS_auipc, rsvdReg, UpperNBitsOfWordSignExtend<20>(low)); + dst += emitOutput_RTypeInstr(dst, INS_add, rsvdReg, REG_RA, rsvdReg); + dst += emitOutput_ITypeInstr(dst, INS_jalr, REG_RA, rsvdReg, LowerNBitsOfWord<12>(low)); + + return dst; +} + +BYTE* emitter::emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate) +{ + assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || (INS_bnez == ins) || + (INS_beqz == ins)); + // Make target address with offset, then jump (JALR) with the target address + immediate -= 2 * 4; + + regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? id->idReg2() : REG_R0; + ssize_t high = UpperWordDoubleWordSignExtend<0>(immediate); + + dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, jmp->idReg1(), reg2, 0x1c); + dst += emitOutput_UTypeInstr(dst, INS_lui, REG_RA, UpperNBitsOfWordSignExtend<20>(high)); + dst += emitOutput_ITypeInstr(dst, INS_addi, REG_RA, REG_RA, LowerNBitsOfWord<12>(high)); + dst += emitOutput_ITypeInstr(dst, INS_slli, REG_RA, REG_RA, 32); + + regNumber rsvdReg = codeGen->rsGetRsvdReg(); + ssize_t low = LowerWordOfDoubleWord(immediate); dst += emitOutput_UTypeInstr(dst, INS_auipc, rsvdReg, UpperNBitsOfWordSignExtend<20>(low)); dst += emitOutput_RTypeInstr(dst, INS_add, rsvdReg, REG_RA, rsvdReg); diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index f4f2fa0a37fba6..e1a241a4ef4920 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -122,8 +122,9 @@ BYTE* emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); BYTE* emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); BYTE* emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insGroup* ig, instruction* ins); -BYTE* emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate, regNumber reg1); +BYTE* emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); BYTE* emitOutputInstr_OptsJalr24(BYTE* dst, instruction ins, ssize_t immediate); +BYTE* emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); static constexpr unsigned kZeroRegister = 0; From 4bf37a0f34781ebec45e51d7733e760b60a58ac5 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 16:46:21 +0100 Subject: [PATCH 054/106] Improved emitOutputInstr_OptsJalr28 --- src/coreclr/jit/emitriscv64.cpp | 22 ++++------------------ src/coreclr/jit/emitriscv64.h | 2 +- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index c42f91195becd2..aa6be8bb0fedb3 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2753,7 +2753,8 @@ BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insG case 8: return emitOutputInstr_OptsJalr8(dst, jmp, *ins, immediate); case 24: - return emitOutputInstr_OptsJalr24(dst, *ins, immediate); + assert((*ins == INS_jal) || (*ins == INS_j)); + return emitOutputInstr_OptsJalr24(dst, immediate); case 28: return emitOutputInstr_OptsJalr28(dst, jmp, *ins, immediate); default: @@ -2775,9 +2776,8 @@ BYTE* emitter::emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, ins return dst; } -BYTE* emitter::emitOutputInstr_OptsJalr24(BYTE* dst, instruction ins, ssize_t immediate) +BYTE* emitter::emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate) { - assert((ins == INS_jal) || (ins == INS_j)); // Make target address with offset, then jump (JALR) with the target address immediate -= 2 * 4; ssize_t high = UpperWordDoubleWordSignExtend<0>(immediate); @@ -2800,25 +2800,11 @@ BYTE* emitter::emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, in { assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || (INS_bnez == ins) || (INS_beqz == ins)); - // Make target address with offset, then jump (JALR) with the target address - immediate -= 2 * 4; regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? id->idReg2() : REG_R0; - ssize_t high = UpperWordDoubleWordSignExtend<0>(immediate); - dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, jmp->idReg1(), reg2, 0x1c); - dst += emitOutput_UTypeInstr(dst, INS_lui, REG_RA, UpperNBitsOfWordSignExtend<20>(high)); - dst += emitOutput_ITypeInstr(dst, INS_addi, REG_RA, REG_RA, LowerNBitsOfWord<12>(high)); - dst += emitOutput_ITypeInstr(dst, INS_slli, REG_RA, REG_RA, 32); - - regNumber rsvdReg = codeGen->rsGetRsvdReg(); - ssize_t low = LowerWordOfDoubleWord(immediate); - dst += emitOutput_UTypeInstr(dst, INS_auipc, rsvdReg, UpperNBitsOfWordSignExtend<20>(low)); - dst += emitOutput_RTypeInstr(dst, INS_add, rsvdReg, REG_RA, rsvdReg); - dst += emitOutput_ITypeInstr(dst, INS_jalr, REG_RA, rsvdReg, LowerNBitsOfWord<12>(low)); - - return dst; + return emitOutputIntr_OptsJalr24(dst, immediate); } /***************************************************************************** diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index e1a241a4ef4920..e44a65ce2020f5 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -123,7 +123,7 @@ BYTE* emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); BYTE* emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumber reg1); BYTE* emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insGroup* ig, instruction* ins); BYTE* emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); -BYTE* emitOutputInstr_OptsJalr24(BYTE* dst, instruction ins, ssize_t immediate); +BYTE* emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate); BYTE* emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); static constexpr unsigned kZeroRegister = 0; From a11b90022214922680522e18e98992cb95f670ab Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 22 Dec 2023 16:52:18 +0100 Subject: [PATCH 055/106] Enabled new opts jalr impl --- src/coreclr/jit/emitriscv64.cpp | 177 +------------------------------- 1 file changed, 4 insertions(+), 173 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index aa6be8bb0fedb3..9858b908e9a2cf 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2771,7 +2771,7 @@ BYTE* emitter::emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, ins regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? jmp->idReg2() : REG_R0; - dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, jmp->idReg1(), reg2, 0x10); + dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, jmp->idReg1(), reg2, 0x8); dst += emitOutput_JTypeInstr(dst, INS_jal, REG_ZERO, immediate); return dst; } @@ -2851,178 +2851,9 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) sz = sizeof(instrDesc); break; case INS_OPTS_JALR: - { - instrDescJmp* jmp = (instrDescJmp*)id; - - regNumber reg1 = id->idReg1(); - { - ssize_t imm = emitOutputInstrJumpDistance(dstRW, dst, ig, jmp); - imm -= 4; - - assert((imm & 0x3) == 0); - - ins = jmp->idIns(); - assert(jmp->idCodeSize() > 4); // The original INS_OPTS_JALR: not used by now!!! - switch (jmp->idCodeSize()) - { - case 8: - { - 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); - // 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; - 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)REG_RA << 7; // use REG_RA for returning - 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; - - // 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; - 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)REG_RA << 7; // use REG_RA for returning - code |= (code_t)tmpReg2 << 15; - code |= (code_t)(low & 0xfff) << 20; - *(code_t*)dstRW = code; - dstRW += 4; - - break; - } - - default: - unreached(); - break; - } - } - sz = sizeof(instrDescJmp); - } - break; + dst = emitOutputInstr_OptsJalr(dst, static_cast(id), ig, &ins); + sz = sizeof(instrDescJmp); + break; case INS_OPTS_J_cond: { ssize_t imm = emitOutputInstrJumpDistance(dstRW, dst, ig, static_cast(id)); From aa4ed43aee7070287eecb3e5504b4a94eaf771c4 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 3 Jan 2024 10:05:21 +0100 Subject: [PATCH 056/106] Added emitOutputInstr_OptsJCond --- src/coreclr/jit/emitriscv64.cpp | 33 ++++++++++++++------------------- src/coreclr/jit/emitriscv64.h | 1 + 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 9858b908e9a2cf..9eaeaef6a7bdcb 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2807,6 +2807,17 @@ BYTE* emitter::emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, in return emitOutputIntr_OptsJalr24(dst, immediate); } +BYTE* emitter::emitOutputInstr_OptsJCond(BYTE* dst, const instrDesc* id, instruction* ins, BYTE* dstRw) +{ + ssize_t immediate = emitOutputInstrJumpDistance(dstRW, dst, ig, static_cast(id)); + assert((immediate & 0x01) == 0); + + *ins = id->idIns(); + + dst += emitOutput_BTypeInstr(dst, ins, id->idReg1(), id->idReg2(), immediate); + return dst; +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor @@ -2855,25 +2866,9 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) sz = sizeof(instrDescJmp); break; case INS_OPTS_J_cond: - { - ssize_t imm = emitOutputInstrJumpDistance(dstRW, dst, ig, static_cast(id)); - assert(isValidSimm13(imm)); - assert(!(imm & 1)); - - ins = id->idIns(); - code = emitInsCode(ins); - code |= ((code_t)id->idReg1()) << 15; - code |= ((code_t)id->idReg2()) << 20; - 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; - - sz = sizeof(instrDescJmp); - } - break; + dst = emitOutputInstr_OptsJCond(dst, id, &ins, dstRW); + sz = sizeof(instrDescJmp); + break; case INS_OPTS_J: // jal/j/jalr/bnez/beqz/beq/bne/blt/bge/bltu/bgeu dstRW-relative. { diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index e44a65ce2020f5..a86b514d619749 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -125,6 +125,7 @@ BYTE* emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insGroup* ig, BYTE* emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); BYTE* emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate); BYTE* emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); +BYTE* emitOutputInstr_OptsJCond(BYTE* dst, const instrDesc* id, instruction* ins, BYTE* dstRw); static constexpr unsigned kZeroRegister = 0; From 4e41b9a537a93e2baa7417b299147d9e824316d8 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 3 Jan 2024 11:16:55 +0100 Subject: [PATCH 057/106] Added emitOutputInstr_OptsJ --- src/coreclr/jit/emitriscv64.cpp | 48 ++++++++++++++++++++++++++++++--- src/coreclr/jit/emitriscv64.h | 5 ++-- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 9eaeaef6a7bdcb..f2173f861b1598 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2807,14 +2807,56 @@ BYTE* emitter::emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, in return emitOutputIntr_OptsJalr24(dst, immediate); } -BYTE* emitter::emitOutputInstr_OptsJCond(BYTE* dst, const instrDesc* id, instruction* ins, BYTE* dstRw) +BYTE* emitter::emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins, BYTE* dstRw) { ssize_t immediate = emitOutputInstrJumpDistance(dstRW, dst, ig, static_cast(id)); assert((immediate & 0x01) == 0); *ins = id->idIns(); - dst += emitOutput_BTypeInstr(dst, ins, id->idReg1(), id->idReg2(), immediate); + dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), id->idReg2(), immediate); + return dst; +} + +BYTE* emitter::emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins, BYTE* dstRW) +{ + ssize_t immediate = emitOutputInstrJumpDistance(dstRW, dst, ig, static_cast(id)); + assert((immediate & 0x03) == 0); + + *ins = id->idIns(); + + switch (*ins) + { + case INS_jal: + dst += emitOutput_JTypeInstr(dst, INS_jal, REG_RA, immediate); + break; + case INS_j: + dst += emitOutput_JTypeInstr(dst, INS_j, REG_ZERO, immediate); + break; + case INS_jalr: + dst += emitOutput_ITypeInstr(dst, INS_jalr, id->idReg1(), id->idReg2(), immediate); + break; + case INS_bnez: + FALLTHROUGH; + case INS_beqz: + dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), REG_ZERO, immediate); + break; + case INS_beq: + FALLTHROUGH; + case INS_bne: + FALLTHROUGH; + case INS_blt: + FALLTHROUGH; + case INS_bge: + FALLTHROUGH; + case INS_bltu: + FALLTHROUGH; + case INS_bgeu: + dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), id->idReg2(), immediate); + break; + default: + unreached(); + } return dst; } @@ -2866,7 +2908,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) sz = sizeof(instrDescJmp); break; case INS_OPTS_J_cond: - dst = emitOutputInstr_OptsJCond(dst, id, &ins, dstRW); + dst = emitOutputInstr_OptsJCond(dst, id, ig, &ins, dstRW); sz = sizeof(instrDescJmp); break; case INS_OPTS_J: diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index a86b514d619749..f0a3eabe66b515 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -125,9 +125,8 @@ BYTE* emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insGroup* ig, BYTE* emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); BYTE* emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate); BYTE* emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); -BYTE* emitOutputInstr_OptsJCond(BYTE* dst, const instrDesc* id, instruction* ins, BYTE* dstRw); - -static constexpr unsigned kZeroRegister = 0; +BYTE* emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins, BYTE* dstRw); +BYTE* emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins, BYTE* dstRW); /************************************************************************/ /* Public inline informational methods */ From 7b0dc156cfcd5a1401f9c33907ae5e4ce2f77a03 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 3 Jan 2024 11:19:56 +0100 Subject: [PATCH 058/106] Replaced old code with the new one --- src/coreclr/jit/emitriscv64.cpp | 61 ++------------------------------- 1 file changed, 2 insertions(+), 59 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index f2173f861b1598..f4d4d132220868 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2913,65 +2913,8 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) break; case INS_OPTS_J: // jal/j/jalr/bnez/beqz/beq/bne/blt/bge/bltu/bgeu dstRW-relative. - { - ssize_t imm = emitOutputInstrJumpDistance(dstRW, dst, ig, static_cast(id)); - assert((imm & 3) == 0); - - ins = id->idIns(); - 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; - code |= ((imm >> 20) & 0x1) << 31; - code |= REG_RA << 7; - } - else if (ins == INS_j) - { - assert(isValidSimm21(imm)); - code |= ((imm >> 12) & 0xff) << 12; - code |= ((imm >> 11) & 0x1) << 20; - code |= ((imm >> 1) & 0x3ff) << 21; - code |= ((imm >> 20) & 0x1) << 31; - } - else if (ins == INS_jalr) - { - 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) - { - assert(isValidSimm13(imm)); - code |= (code_t)id->idReg1() << 15; - code |= ((imm >> 11) & 0x1) << 7; - code |= ((imm >> 1) & 0xf) << 8; - code |= ((imm >> 5) & 0x3f) << 25; - code |= ((imm >> 12) & 0x1) << 31; - } - 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; - code |= ((imm >> 1) & 0xf) << 8; - code |= ((imm >> 5) & 0x3f) << 25; - code |= ((imm >> 12) & 0x1) << 31; - } - else - { - unreached(); - } - - *(code_t*)dstRW = code; - dstRW += 4; - - sz = sizeof(instrDescJmp); - } + dst = emitOutputInstr_OptsJ(dst, id, ig, &ins, dstRW); + sz = sizeof(instrDescJmp); break; case INS_OPTS_C: if (id->idIsLargeCall()) From a4b3a26abcfb282941b945db5b7d719489a64fff Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 3 Jan 2024 11:29:34 +0100 Subject: [PATCH 059/106] Added emitOutputInstr_OptsC --- src/coreclr/jit/emitriscv64.cpp | 38 +++++++++++++++++---------------- src/coreclr/jit/emitriscv64.h | 3 ++- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index f4d4d132220868..993ad46a8c725f 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -1463,7 +1463,7 @@ void emitter::emitIns_Call(EmitCallType callType, * Output a call instruction. */ -unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code) +unsigned emitter::emitOutputCall(const insGroup* ig, BYTE* dst, instrDesc* id, code_t code) { unsigned char callInstrSize = sizeof(code_t); // 4 bytes regMaskTP gcrefRegs; @@ -2860,6 +2860,22 @@ BYTE* emitter::emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* i return dst; } +BYTE* emitter::emitOutputInstr_OptsC(BYTE* dst, const instrDesc* id, const insGroup* ig, size_t* size) +{ + if (id->idIsLargeCall()) + { + *size = sizeof(instrDescCGCA); + } + else + { + assert(!id->idIsLargeDsp()); + assert(!id->idIsLargeCns()); + *size = sizeof(instrDesc); + } + dst += emitOutputCall(ig, dst, id, 0); + return dst; +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor @@ -2917,25 +2933,11 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) sz = sizeof(instrDescJmp); break; case INS_OPTS_C: - if (id->idIsLargeCall()) - { - /* Must be a "fat" call descriptor */ - sz = sizeof(instrDescCGCA); - } - else - { - assert(!id->idIsLargeDsp()); - assert(!id->idIsLargeCns()); - sz = sizeof(instrDesc); - } - dstRW += emitOutputCall(ig, *dp, id, 0); - - dstRW2 = dstRW; + dst = emitOutputInstr_OptsC(dst, id, ig, &sz); ins = INS_nop; + dstRW2 = dst + writeableOffset; // TODO remove break; - - // case INS_OPTS_NONE: - default: + default: // case INS_OPTS_NONE: *(code_t*)dstRW = id->idAddr()->iiaGetInstrEncode(); dstRW += 4; ins = id->idIns(); diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index f0a3eabe66b515..ff365ad4e7dcff 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -127,6 +127,7 @@ BYTE* emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate); BYTE* emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); BYTE* emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins, BYTE* dstRw); BYTE* emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins, BYTE* dstRW); +BYTE* emitOutputInstr_OptsC(BYTE* dst, const instrDesc* id, const insGroup* ig, size_t* size); /************************************************************************/ /* Public inline informational methods */ @@ -319,7 +320,7 @@ void emitIns_Call(EmitCallType callType, ssize_t disp = 0, bool isJump = false); -unsigned emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code); +unsigned emitOutputCall(const insGroup* ig, BYTE* dst, instrDesc* id, code_t code); unsigned get_curTotalCodeSize(); // bytes of code From 8267ae77cba205cdd4d0d81df615a64ef53e6d07 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 3 Jan 2024 11:33:51 +0100 Subject: [PATCH 060/106] Fixed last piece of switch --- 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 993ad46a8c725f..252135fbdab253 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2938,8 +2938,8 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) dstRW2 = dst + writeableOffset; // TODO remove break; default: // case INS_OPTS_NONE: - *(code_t*)dstRW = id->idAddr()->iiaGetInstrEncode(); - dstRW += 4; + dst += emitOutput_Instr(dst, id->idAddr()->iiaGetInstrEncode()); + emitInsCode() ins = id->idIns(); sz = emitSizeOfInsDsc(id); break; From 9e9d6d47a5a799d1b1bd800e09969d40a012f2ff Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 3 Jan 2024 11:52:40 +0100 Subject: [PATCH 061/106] Removed old code --- src/coreclr/jit/emitriscv64.cpp | 48 +++++++++++++++------------------ src/coreclr/jit/emitriscv64.h | 6 ++--- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 252135fbdab253..4167d7dcc80f7f 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2461,7 +2461,7 @@ void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, * */ -ssize_t emitter::emitOutputInstrJumpDistance(const BYTE* dst, const BYTE* src, const insGroup* ig, instrDescJmp* jmp) +ssize_t emitter::emitOutputInstrJumpDistance(const BYTE* src, const insGroup* ig, instrDescJmp* jmp) { UNATIVE_OFFSET srcOffs = emitCurCodeOffs(src); const BYTE* srcAddr = emitOffsetToPtr(srcOffs); @@ -2807,9 +2807,9 @@ BYTE* emitter::emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, in return emitOutputIntr_OptsJalr24(dst, immediate); } -BYTE* emitter::emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins, BYTE* dstRw) +BYTE* emitter::emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins) { - ssize_t immediate = emitOutputInstrJumpDistance(dstRW, dst, ig, static_cast(id)); + ssize_t immediate = emitOutputInstrJumpDistance(dst, ig, static_cast(id)); assert((immediate & 0x01) == 0); *ins = id->idIns(); @@ -2818,9 +2818,9 @@ BYTE* emitter::emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGrou return dst; } -BYTE* emitter::emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins, BYTE* dstRW) +BYTE* emitter::emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins) { - ssize_t immediate = emitOutputInstrJumpDistance(dstRW, dst, ig, static_cast(id)); + ssize_t immediate = emitOutputInstrJumpDistance(dst, ig, static_cast(id)); assert((immediate & 0x03) == 0); *ins = id->idIns(); @@ -2887,12 +2887,8 @@ BYTE* emitter::emitOutputInstr_OptsC(BYTE* dst, const instrDesc* id, const insGr size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { - BYTE* dst = *dp; - BYTE* dstRW = *dp + writeableOffset; - BYTE* dstRW2 = dstRW + 4; // addr for updating gc info if needed. - const BYTE* const odstRW = dstRW; - const BYTE* const odst = *dp; - code_t code = 0; + BYTE* dst = *dp; + const BYTE* const odst = *dp; instruction ins; size_t sz; // = emitSizeOfInsDsc(id); @@ -2924,24 +2920,22 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) sz = sizeof(instrDescJmp); break; case INS_OPTS_J_cond: - dst = emitOutputInstr_OptsJCond(dst, id, ig, &ins, dstRW); + dst = emitOutputInstr_OptsJCond(dst, id, ig, &ins); sz = sizeof(instrDescJmp); break; case INS_OPTS_J: // jal/j/jalr/bnez/beqz/beq/bne/blt/bge/bltu/bgeu dstRW-relative. - dst = emitOutputInstr_OptsJ(dst, id, ig, &ins, dstRW); + dst = emitOutputInstr_OptsJ(dst, id, ig, &ins); sz = sizeof(instrDescJmp); break; case INS_OPTS_C: - dst = emitOutputInstr_OptsC(dst, id, ig, &sz); - ins = INS_nop; - dstRW2 = dst + writeableOffset; // TODO remove + dst = emitOutputInstr_OptsC(dst, id, ig, &sz); + ins = INS_nop; break; default: // case INS_OPTS_NONE: dst += emitOutput_Instr(dst, id->idAddr()->iiaGetInstrEncode()); - emitInsCode() - ins = id->idIns(); - sz = emitSizeOfInsDsc(id); + emitInsCode() ins = id->idIns(); + sz = emitSizeOfInsDsc(id); break; } @@ -2954,11 +2948,11 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) // We assume that "idReg1" is the primary destination register for all instructions if (id->idGCref() != GCT_NONE) { - emitGCregLiveUpd(id->idGCref(), id->idReg1(), dstRW2 - writeableOffset); + emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst); } else { - emitGCregDeadUpd(id->idReg1(), dstRW2 - writeableOffset); + emitGCregDeadUpd(id->idReg1(), dst); } } @@ -2972,7 +2966,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) int adr = emitComp->lvaFrameAddress(varNum, &FPbased); if (id->idGCref() != GCT_NONE) { - emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dstRW2 - writeableOffset DEBUG_ARG(varNum)); + emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst DEBUG_ARG(varNum)); } else { @@ -2989,7 +2983,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) vt = tmpDsc->tdTempType(); } if (vt == TYP_REF || vt == TYP_BYREF) - emitGCvarDeadUpd(adr + ofs, dstRW2 - writeableOffset DEBUG_ARG(varNum)); + emitGCvarDeadUpd(adr + ofs, dst DEBUG_ARG(varNum)); } // if (emitInsWritesToLclVarStackLocPair(id)) //{ @@ -3028,7 +3022,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) #else // !DUMP_GC_TABLES bool dspOffs = !emitComp->opts.disDiffable; #endif // !DUMP_GC_TABLES - emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dstRW - odstRW), ig); + emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - odst), ig); } if (emitComp->compDebugBreak) @@ -3043,15 +3037,15 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) #else // !DEBUG if (emitComp->opts.disAsm) { - emitDispIns(id, false, false, true, emitCurCodeOffs(odst), *dp, (dstRW - odstRW), ig); + emitDispIns(id, false, false, true, emitCurCodeOffs(odst), *dp, (dst - odst), ig); } #endif // !DEBUG /* All instructions are expected to generate code */ - assert(*dp != (dstRW - writeableOffset)); + assert(*dp != dst); - *dp = dstRW - writeableOffset; + *dp = dst; return sz; } diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index ff365ad4e7dcff..8b0f4ce4b4a6fd 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -81,7 +81,7 @@ void emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTr // Emit the 32-bit RISCV64 instruction 'code' into the 'dst' buffer unsigned emitOutput_Instr(BYTE* dst, code_t code) const; -ssize_t emitOutputInstrJumpDistance(const BYTE* dst, const BYTE* src, const insGroup* ig, instrDescJmp* jmp); +ssize_t emitOutputInstrJumpDistance(const BYTE* src, const insGroup* ig, instrDescJmp* jmp); void emitOutputInstrJumpDistanceHelper(const insGroup* ig, instrDescJmp* jmp, UNATIVE_OFFSET& dstOffs, @@ -125,8 +125,8 @@ BYTE* emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insGroup* ig, BYTE* emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); BYTE* emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate); BYTE* emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); -BYTE* emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins, BYTE* dstRw); -BYTE* emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins, BYTE* dstRW); +BYTE* emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins); +BYTE* emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins); BYTE* emitOutputInstr_OptsC(BYTE* dst, const instrDesc* id, const insGroup* ig, size_t* size); /************************************************************************/ From 8fbc91d55842fcbbfc35aeb6c7d59404a901c442 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 3 Jan 2024 12:01:35 +0100 Subject: [PATCH 062/106] Simplified code --- src/coreclr/jit/emitriscv64.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 4167d7dcc80f7f..4c43cb486eb847 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2889,8 +2889,8 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { BYTE* dst = *dp; const BYTE* const odst = *dp; - instruction ins; - size_t sz; // = emitSizeOfInsDsc(id); + instruction ins = 0; + size_t sz = 0; assert(REG_NA == static_cast(REG_NA)); @@ -2934,8 +2934,8 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) break; default: // case INS_OPTS_NONE: dst += emitOutput_Instr(dst, id->idAddr()->iiaGetInstrEncode()); - emitInsCode() ins = id->idIns(); - sz = emitSizeOfInsDsc(id); + ins = id->idIns(); + sz = sizeof(instrDesc); break; } From 89da41b33062df3b8ab7757751f8ca68ae541bdb Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 3 Jan 2024 12:38:57 +0100 Subject: [PATCH 063/106] Other fixes --- src/coreclr/jit/emitriscv64.cpp | 10 +++++----- src/coreclr/jit/emitriscv64.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 4c43cb486eb847..5af5c461379eb8 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2743,7 +2743,7 @@ BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumbe BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insGroup* ig, instruction* ins) { - ssize_t immediate = emitOutputInstrJumpDistance(dst + writeableOffset, dst, ig, jmp) - 4; + ssize_t immediate = emitOutputInstrJumpDistance(dst, ig, jmp) - 4; assert((immediate & 0x03) == 0); *ins = jmp->idIns(); @@ -2801,10 +2801,10 @@ BYTE* emitter::emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, in assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || (INS_bnez == ins) || (INS_beqz == ins)); - regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? id->idReg2() : REG_R0; + regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? jmp->idReg2() : REG_R0; dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, jmp->idReg1(), reg2, 0x1c); - return emitOutputIntr_OptsJalr24(dst, immediate); + return emitOutputInstr_OptsJalr24(dst, immediate); } BYTE* emitter::emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins) @@ -2860,7 +2860,7 @@ BYTE* emitter::emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* i return dst; } -BYTE* emitter::emitOutputInstr_OptsC(BYTE* dst, const instrDesc* id, const insGroup* ig, size_t* size) +BYTE* emitter::emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* ig, size_t* size) { if (id->idIsLargeCall()) { @@ -2889,7 +2889,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { BYTE* dst = *dp; const BYTE* const odst = *dp; - instruction ins = 0; + instruction ins; size_t sz = 0; assert(REG_NA == static_cast(REG_NA)); diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 8b0f4ce4b4a6fd..0968a6026afca8 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -127,7 +127,7 @@ BYTE* emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate); BYTE* emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate); BYTE* emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins); BYTE* emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins); -BYTE* emitOutputInstr_OptsC(BYTE* dst, const instrDesc* id, const insGroup* ig, size_t* size); +BYTE* emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* ig, size_t* size); /************************************************************************/ /* Public inline informational methods */ From 338a7bb76790e770d2ebc3d8defc89824843e606 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 3 Jan 2024 12:53:43 +0100 Subject: [PATCH 064/106] Fixes in emitOutput_* instr --- src/coreclr/jit/emitriscv64.cpp | 38 ++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 5af5c461379eb8..6c3b3e5a0c7131 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2300,17 +2300,18 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const { + unsigned insCode = emitInsCode(ins); + #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask | kInstructionFunct7Mask; - assert((ins & kInstructionMask) == 0); + assert((insCode & kInstructionMask) == 0); #endif // DEBUG - unsigned insCode = emitInsCode(ins); - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 25; + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 25; return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7)); } @@ -2323,15 +2324,16 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const { + unsigned insCode = emitInsCode(ins); + #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; - assert((ins & kInstructionMask) == 0); + assert((insCode & kInstructionMask) == 0); #endif // DEBUG - unsigned insCode = emitInsCode(ins); - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, imm12)); } @@ -2344,15 +2346,16 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const { + unsigned insCode = emitInsCode(ins); + #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; - assert((ins & kInstructionMask) == 0); + assert((insCode & kInstructionMask) == 0); #endif // DEBUG - unsigned insCode = emitInsCode(ins); - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2, imm12)); } @@ -2378,15 +2381,16 @@ unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const { + unsigned insCode = emitInsCode(ins); + #ifdef DEBUG static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; - assert((ins & kInstructionMask) == 0); + assert((insCode & kInstructionMask) == 0); #endif // DEBUG - unsigned insCode = emitInsCode(ins); - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13)); } From 83e052aacda13acb3a2798f32b2c2e43c0522b37 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 3 Jan 2024 13:59:28 +0100 Subject: [PATCH 065/106] Fixed bitmask bug --- src/coreclr/jit/emitriscv64.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 6c3b3e5a0c7131..24e9ccc7e0a9d1 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2304,7 +2304,7 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd #ifdef DEBUG static constexpr unsigned kInstructionMask = - kInstructionOpcodeMask | kInstructionFunct3Mask | kInstructionFunct7Mask; + ~(kInstructionOpcodeMask | kInstructionFunct3Mask | kInstructionFunct7Mask); assert((insCode & kInstructionMask) == 0); #endif // DEBUG @@ -2327,7 +2327,7 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned insCode = emitInsCode(ins); #ifdef DEBUG - static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; + static constexpr unsigned kInstructionMask = ~(kInstructionOpcodeMask | kInstructionFunct3Mask); assert((insCode & kInstructionMask) == 0); #endif // DEBUG @@ -2349,7 +2349,7 @@ unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs unsigned insCode = emitInsCode(ins); #ifdef DEBUG - static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; + static constexpr unsigned kInstructionMask = ~(kInstructionOpcodeMask | kInstructionFunct3Mask); assert((insCode & kInstructionMask) == 0); #endif // DEBUG @@ -2384,7 +2384,7 @@ unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs unsigned insCode = emitInsCode(ins); #ifdef DEBUG - static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; + static constexpr unsigned kInstructionMask = ~(kInstructionOpcodeMask | kInstructionFunct3Mask); assert((insCode & kInstructionMask) == 0); #endif // DEBUG @@ -2409,15 +2409,16 @@ unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs unsigned emitter::emitOutput_BTypeInstr_InvertComparation( BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const { + unsigned insCode = emitInsCode(ins) ^ 0x1000; + #ifdef DEBUG - static constexpr unsigned kInstructionMask = kInstructionOpcodeMask | kInstructionFunct3Mask; + static constexpr unsigned kInstructionMask = ~(kInstructionOpcodeMask | kInstructionFunct3Mask); - assert((ins & kInstructionMask) == 0); + assert((insCode & kInstructionMask) == 0); #endif // DEBUG - unsigned insCode = emitInsCode(ins) ^ 0x1000; - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13)); } From 3dddca6071c7e9c4b4eb924d89d80f47146c92f9 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 8 Jan 2024 11:51:05 +0100 Subject: [PATCH 066/106] Added temporary reinforced assers --- src/coreclr/jit/emitriscv64.cpp | 675 +++++++++++++++++++++++++++++++- src/coreclr/jit/emitriscv64.h | 9 + 2 files changed, 682 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 5c8aeb30c477a4..1553057607899b 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2222,7 +2222,7 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(rd, 5); isValidSimm20(imm20); - return opcode | (rd << 7) | ((imm20 >> 12) << 12); + return opcode | (rd << 7) | (imm20 << 12); } /***************************************************************************** @@ -2739,7 +2739,7 @@ BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumbe assert((immediate >> (32 + 20)) == 0); regNumber rsvdReg = codeGen->rsGetRsvdReg(); - ssize_t upperSignExt = UpperWordOfDoubleWordSignExtend<0, 12>(immediate); + ssize_t upperSignExt = UpperWordOfDoubleWordSignExtend<20, 12>(immediate); dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(immediate)); @@ -2884,6 +2884,670 @@ BYTE* emitter::emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* i return dst; } +void emitter::assertOptsReloc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) { + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; + size_t clock_of_clocks = 0; + instruction ins; + + regNumber reg1 = id->idReg1(); + + *(code_t*)mock_ptr = 0x00000017 | (code_t)(reg1 << 7); + + mock_ptr += 4; + + if (id->idIsCnsReloc()) + { + ins = INS_addi; + *(code_t*)mock_ptr = 0x00000013 | (code_t)(reg1 << 7) | (code_t)(reg1 << 15); + } + else + { + assert(id->idIsDspReloc()); + ins = INS_ld; + *(code_t*)mock_ptr = 0x00003003 | (code_t)(reg1 << 7) | (code_t)(reg1 << 15); + } + + mock_ptr += 4; + clock_of_clocks += 8; + + assert(clock_of_clocks == buf_size); + assert(ins == cur_ins); + for (size_t i = 0;i < buf_size; ++i) { + assert((dst + writeableOffset)[i] == mock_dst[i]); + } +} + +void emitter::assertOptsI(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) +{ + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; + instruction ins; + ssize_t imm = (ssize_t)(id->idAddr()->iiaAddr); + regNumber reg1 = id->idReg1(); + code_t code; + + switch (id->idCodeSize()) + { + case 8: + { + if (id->idReg2()) + { // special for INT64_MAX or UINT32_MAX; + code = emitInsCode(INS_addi); + code |= (code_t)reg1 << 7; + code |= (code_t)REG_R0 << 15; + code |= 0xfff << 10; + + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + ssize_t ui6 = (imm == INT64_MAX) ? 1 : 32; + code = emitInsCode(INS_srli); + code |= ((code_t)(reg1 << 7) | ((code_t)(reg1 << 15)) | (ui6 << 20)); + *(code_t*)mock_ptr = code; + } + else + { + code = emitInsCode(INS_lui); + code |= (code_t)(reg1 << 7); + code |= ((code_t)((imm + 0x800) >> 12) & 0xfffff) << 12; + + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)reg1 << 7; + code |= (code_t)reg1 << 15; + code |= (code_t)(imm & 0xfff) << 20; + *(code_t*)mock_ptr = code; + } + break; + } + case 32: + { + ssize_t high = (imm >> 32) & 0xffffffff; + code = emitInsCode(INS_lui); + code |= (code_t)reg1 << 7; + code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; + + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)reg1 << 7; + code |= (code_t)reg1 << 15; + code |= (code_t)(high & 0xfff) << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + ssize_t low = imm & 0xffffffff; + + code = emitInsCode(INS_slli); + code |= (code_t)reg1 << 7; + code |= (code_t)reg1 << 15; + code |= (code_t)11 << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)reg1 << 7; + code |= (code_t)reg1 << 15; + code |= (code_t)((low >> 21) & 0x7ff) << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_slli); + code |= (code_t)reg1 << 7; + code |= (code_t)reg1 << 15; + code |= (code_t)11 << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)reg1 << 7; + code |= (code_t)reg1 << 15; + code |= (code_t)((low >> 10) & 0x7ff) << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_slli); + code |= (code_t)reg1 << 7; + code |= (code_t)reg1 << 15; + code |= (code_t)10 << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)reg1 << 7; + code |= (code_t)reg1 << 15; + code |= (code_t)((low)&0x3ff) << 20; + *(code_t*)mock_ptr = code; + break; + } + default: + unreached(); + break; + } + + ins = INS_addi; + mock_ptr += 4; + + assert((mock_ptr - mock_dst) == buf_size); + assert(cur_ins == ins); + for (size_t i = 0;i < buf_size; ++i) { + assert((dst + writeableOffset)[i] == mock_dst[i]); + } +} + +void emitter::assertOptsRc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) +{ + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; + instruction ins; + code_t code; + + assert(id->idAddr()->iiaIsJitDataOffset()); + assert(id->idGCref() == GCT_NONE); + + int doff = id->idAddr()->iiaGetJitDataOffset(); + assert(doff >= 0); + + ssize_t imm = emitGetInsSC(id); + assert((imm >= 0) && (imm < 0x4000)); // 0x4000 is arbitrary, currently 'imm' is always 0. + + unsigned dataOffs = (unsigned)(doff + imm); + + assert(dataOffs < emitDataSize()); + + ins = id->idIns(); + regNumber reg1 = id->idReg1(); + + if (id->idIsReloc()) + { + // get the addr-offset of the data. + imm = (ssize_t)emitConsBlock - (ssize_t)(dst) + dataOffs; + assert(imm > 0); + assert(!(imm & 3)); + + doff = (int)(imm & 0xfff); + assert(isValidSimm20((imm + 0x800) >> 12)); + +#ifdef DEBUG + code = emitInsCode(INS_auipc); + assert(code == 0x00000017); +#endif + code = 0x00000017 | (codeGen->rsGetRsvdReg() << 7); + *(code_t*)mock_ptr = code | ((code_t)((imm + 0x800) & 0xfffff000)); + mock_ptr += 4; + + if (ins == INS_jal) + { + assert(isGeneralRegister(reg1)); + ins = INS_addi; +#ifdef DEBUG + code = emitInsCode(INS_addi); + assert(code == 0x00000013); +#endif + code = 0x00000013 | (codeGen->rsGetRsvdReg() << 15); + *(code_t*)mock_ptr = code | ((code_t)reg1 << 7) | (((code_t)doff & 0xfff) << 20); + } + else + { + code = emitInsCode(ins); + code |= (code_t)(reg1 & 0x1f) << 7; + code |= (code_t)codeGen->rsGetRsvdReg() << 15; + code |= (code_t)(doff & 0xfff) << 20; + *(code_t*)mock_ptr = code; + } + mock_ptr += 4; + } + else + { + // get the addr of the data. + imm = (ssize_t)emitConsBlock + dataOffs; + + code = emitInsCode(INS_lui); + if (ins == INS_jal) + { + assert((imm >> 40) == 0); + + doff = imm & 0x7ff; + + UINT32 high = imm >> 11; + + code |= (code_t)codeGen->rsGetRsvdReg() << 7; + code |= (code_t)(((high + 0x800) >> 12) << 12); + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)codeGen->rsGetRsvdReg() << 7; + code |= (code_t)codeGen->rsGetRsvdReg() << 15; + code |= (code_t)(high & 0xFFF) << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_slli); + code |= (code_t)codeGen->rsGetRsvdReg() << 7; + code |= (code_t)codeGen->rsGetRsvdReg() << 15; + code |= (code_t)11 << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + ins = INS_addi; + code = emitInsCode(INS_addi); + code |= (code_t)reg1 << 7; + code |= (code_t)codeGen->rsGetRsvdReg() << 15; + code |= (code_t)doff << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + } + else + { + assert((imm >> 40) == 0); + + doff = imm & 0x7ff; + UINT32 high = imm >> 11; + + code |= (code_t)(codeGen->rsGetRsvdReg() << 7); + code |= (code_t)(((high + 0x800) >> 12) << 12); + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)codeGen->rsGetRsvdReg() << 7; + code |= (code_t)codeGen->rsGetRsvdReg() << 15; + code |= (code_t)(high & 0xFFF) << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_slli); + code |= (code_t)codeGen->rsGetRsvdReg() << 7; + code |= (code_t)codeGen->rsGetRsvdReg() << 15; + code |= (code_t)11 << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(ins); + code |= (code_t)(reg1 & 0x1f) << 7; + code |= (code_t)codeGen->rsGetRsvdReg() << 15; + code |= (code_t)doff << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + } + } + + assert((mock_ptr - mock_dst) == buf_size); + assert(cur_ins == ins); + for (size_t i = 0;i < buf_size; ++i) { + assert((dst + writeableOffset)[i] == mock_dst[i]); + } +} + +void emitter::assertOptsRl(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) +{ + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; + instruction ins; + code_t code; + + insGroup* tgtIG = (insGroup*)id->idAddr()->iiaIGlabel; + + regNumber reg1 = id->idReg1(); + assert(isGeneralRegister(reg1)); + + if (id->idIsReloc()) + { + ssize_t imm = (ssize_t)tgtIG->igOffs; + imm = (ssize_t)emitCodeBlock + imm - (ssize_t)(dst); + assert((imm & 3) == 0); + + int doff = (int)(imm & 0xfff); + assert(isValidSimm20((imm + 0x800) >> 12)); + + code = 0x00000017; + *(code_t*)mock_ptr = code | (code_t)reg1 << 7 | ((imm + 0x800) & 0xfffff000); + mock_ptr += 4; +#ifdef DEBUG + code = emitInsCode(INS_auipc); + assert(code == 0x00000017); + code = emitInsCode(INS_addi); + assert(code == 0x00000013); +#endif + ins = INS_addi; + *(code_t*)mock_ptr = 0x00000013 | ((code_t)reg1 << 7) | ((code_t)reg1 << 15) | ((doff & 0xfff) << 20); + } + else + { + ssize_t imm = (ssize_t)tgtIG->igOffs + (ssize_t)emitCodeBlock; + assert((imm >> (32 + 20)) == 0); + + code = emitInsCode(INS_lui); + code |= (code_t)codeGen->rsGetRsvdReg() << 7; + code |= ((code_t)((imm + 0x800) >> 12) & 0xfffff) << 12; + + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)codeGen->rsGetRsvdReg() << 7; + code |= (code_t)codeGen->rsGetRsvdReg() << 15; + code |= (code_t)(imm & 0xfff) << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)reg1 << 7; + code |= (((imm + 0x80000800) >> 32) & 0xfff) << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_slli); + code |= (code_t)reg1 << 7; + code |= (code_t)reg1 << 15; + code |= (code_t)32 << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + ins = INS_add; + code = emitInsCode(INS_add); + code |= (code_t)reg1 << 7; + code |= (code_t)reg1 << 15; + code |= (code_t)codeGen->rsGetRsvdReg() << 20; + *(code_t*)mock_ptr = code; + } + + mock_ptr += 4; + + assert((mock_ptr - mock_dst) == buf_size); + assert(cur_ins == ins); + + for (size_t i = 0;i < buf_size; ++i) { + assert((dst + writeableOffset)[i] == mock_dst[i]); + } +} + +void emitter::assertOptsJarl(BYTE* dst, size_t buf_size, instrDescJmp* jmp, const insGroup* ig, const instrDesc* id, instruction cur_ins) +{ + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; + instruction ins; + code_t code; + + regNumber reg1 = id->idReg1(); + { + ssize_t imm = emitOutputInstrJumpDistance(dst, ig, jmp); + imm -= 4; + + assert((imm & 0x3) == 0); + + ins = jmp->idIns(); + assert(jmp->idCodeSize() > 4); // The original INS_OPTS_JALR: not used by now!!! + switch (jmp->idCodeSize()) + { + case 8: + { + 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*)mock_ptr = code; + mock_ptr += 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*)mock_ptr = code; + mock_ptr += 4; + break; + } + 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; + code = emitInsCode(INS_lui); + code |= (code_t)tmpReg1 << 7; + code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; + + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)tmpReg1 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)(high & 0xfff) << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_slli); + code |= (code_t)tmpReg1 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)32 << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 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*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_add); + code |= (code_t)tmpReg2 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)tmpReg2 << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 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*)mock_ptr = code; + mock_ptr += 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*)mock_ptr = code; + mock_ptr += 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; + code = emitInsCode(INS_lui); + code |= (code_t)tmpReg1 << 7; + code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; + + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)tmpReg1 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)(high & 0xfff) << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_slli); + code |= (code_t)tmpReg1 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)32 << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 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*)mock_ptr = code; + mock_ptr += 4; + + code = emitInsCode(INS_add); + code |= (code_t)tmpReg2 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)tmpReg2 << 20; + *(code_t*)mock_ptr = code; + mock_ptr += 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*)mock_ptr = code; + mock_ptr += 4; + + break; + } + + default: + unreached(); + break; + } + } + + assert((mock_ptr - mock_dst) == buf_size); + assert(cur_ins == ins); + + for (size_t i = 0;i < buf_size; ++i) { + assert((dst + writeableOffset)[i] == mock_dst[i]); + } +} + +void emitter::assertOptsJCond(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins) +{ + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; + instruction ins; + code_t code; + + ssize_t imm = emitOutputInstrJumpDistance(dst, ig, static_cast(id)); + assert(isValidSimm13(imm)); + assert(!(imm & 1)); + + ins = id->idIns(); + code = emitInsCode(ins); + code |= ((code_t)id->idReg1()) << 15; + code |= ((code_t)id->idReg2()) << 20; + code |= ((imm >> 11) & 0x1) << 7; + code |= ((imm >> 1) & 0xf) << 8; + code |= ((imm >> 5) & 0x3f) << 25; + code |= ((imm >> 12) & 0x1) << 31; + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + assert(cur_ins == ins); + + for (size_t i = 0;i < buf_size; ++i) { + assert((dst + writeableOffset)[i] == mock_dst[i]); + } +} + +void emitter::assertOptsJ(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins) +{ + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; + instruction ins; + code_t code; + + ssize_t imm = emitOutputInstrJumpDistance(dst, ig, static_cast(id)); + assert((imm & 3) == 0); + + ins = id->idIns(); + 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; + code |= ((imm >> 20) & 0x1) << 31; + code |= REG_RA << 7; + } + else if (ins == INS_j) + { + assert(isValidSimm21(imm)); + code |= ((imm >> 12) & 0xff) << 12; + code |= ((imm >> 11) & 0x1) << 20; + code |= ((imm >> 1) & 0x3ff) << 21; + code |= ((imm >> 20) & 0x1) << 31; + } + else if (ins == INS_jalr) + { + 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) + { + assert(isValidSimm13(imm)); + code |= (code_t)id->idReg1() << 15; + code |= ((imm >> 11) & 0x1) << 7; + code |= ((imm >> 1) & 0xf) << 8; + code |= ((imm >> 5) & 0x3f) << 25; + code |= ((imm >> 12) & 0x1) << 31; + } + 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; + code |= ((imm >> 1) & 0xf) << 8; + code |= ((imm >> 5) & 0x3f) << 25; + code |= ((imm >> 12) & 0x1) << 31; + } + else + { + unreached(); + } + + *(code_t*)mock_ptr = code; + mock_ptr += 4; + + assert(cur_ins == ins); + + for (size_t i = 0;i < buf_size; ++i) { + assert((dst + writeableOffset)[i] == mock_dst[i]); + } +} + /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor @@ -2908,33 +3572,40 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { case INS_OPTS_RELOC: dst = emitOutputInstr_OptsReloc(dst, id, &ins); + assertOptsReloc(*dp, dst - *dp, id, ins); sz = sizeof(instrDesc); break; case INS_OPTS_I: dst = emitOutputInstr_OptsI(dst, id); ins = INS_addi; sz = sizeof(instrDesc); + assertOptsI(*dp, dst - *dp, id, ins); break; case INS_OPTS_RC: dst = emitOutputInstr_OptsRc(dst, id, &ins); sz = sizeof(instrDesc); + assertOptsRc(*dp, dst - *dp, id, ins); break; case INS_OPTS_RL: dst = emitOutputInstr_OptsRl(dst, id, &ins); + assertOptsRl(*dp, dst - *dp, id, ins); sz = sizeof(instrDesc); break; case INS_OPTS_JALR: dst = emitOutputInstr_OptsJalr(dst, static_cast(id), ig, &ins); sz = sizeof(instrDescJmp); + assertOptsJarl(*dp, dst - *dp, static_cast(id), ig, id, ins); break; case INS_OPTS_J_cond: dst = emitOutputInstr_OptsJCond(dst, id, ig, &ins); sz = sizeof(instrDescJmp); + assertOptsJCond(*dp, dst - *dp, ig, id, ins); break; case INS_OPTS_J: // jal/j/jalr/bnez/beqz/beq/bne/blt/bge/bltu/bgeu dstRW-relative. dst = emitOutputInstr_OptsJ(dst, id, ig, &ins); sz = sizeof(instrDescJmp); + assertOptsJ(*dp, dst - *dp, ig, id, ins); break; case INS_OPTS_C: dst = emitOutputInstr_OptsC(dst, id, ig, &sz); diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 0968a6026afca8..f46bea08157a4c 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -129,6 +129,15 @@ BYTE* emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, in BYTE* emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins); BYTE* emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* ig, size_t* size); + +void assertOptsReloc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); +void assertOptsI(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); +void assertOptsRc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); +void assertOptsRl(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); +void assertOptsJarl(BYTE* dst, size_t buf_size, instrDescJmp* jmp, const insGroup* ig, const instrDesc* id, instruction cur_ins); +void assertOptsJCond(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins); +void assertOptsJ(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins); + /************************************************************************/ /* Public inline informational methods */ /************************************************************************/ From 8ab3b4c3cfcf6149f099542638a3f587d48ae0e8 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 8 Jan 2024 15:41:40 +0100 Subject: [PATCH 067/106] Added shift ins --- src/coreclr/jit/emitriscv64.cpp | 115 ++++++++++++++++++++------------ src/coreclr/jit/emitriscv64.h | 1 + 2 files changed, 72 insertions(+), 44 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 1553057607899b..d4297e5edb8d97 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2337,7 +2337,25 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, imm12)); + return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd & 0x1f, funct3, rs1 & 0x1f, imm12)); +} + +unsigned emitOutput_ITypeInstr_Shift(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int shamt) const +{ + unsigned insCode = emitInsCode(ins); + +#ifdef DEBUG + static constexpr unsigned kInstructionMask = + ~(kInstructionOpcodeMask | kInstructionFunct3Mask | kInstructionFunct7Mask); + + assert((insCode & kInstructionMask) == 0); + assert(shamt < 32); +#endif // DEBUG + + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 20; // prepared for masking + return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, shamt | funct7)); } /***************************************************************************** @@ -2884,10 +2902,11 @@ BYTE* emitter::emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* i return dst; } -void emitter::assertOptsReloc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) { - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; - size_t clock_of_clocks = 0; +void emitter::assertOptsReloc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) +{ + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; + size_t clock_of_clocks = 0; instruction ins; regNumber reg1 = id->idReg1(); @@ -2898,13 +2917,13 @@ void emitter::assertOptsReloc(BYTE* dst, size_t buf_size, const instrDesc* id, i if (id->idIsCnsReloc()) { - ins = INS_addi; + ins = INS_addi; *(code_t*)mock_ptr = 0x00000013 | (code_t)(reg1 << 7) | (code_t)(reg1 << 15); } else { assert(id->idIsDspReloc()); - ins = INS_ld; + ins = INS_ld; *(code_t*)mock_ptr = 0x00003003 | (code_t)(reg1 << 7) | (code_t)(reg1 << 15); } @@ -2913,19 +2932,20 @@ void emitter::assertOptsReloc(BYTE* dst, size_t buf_size, const instrDesc* id, i assert(clock_of_clocks == buf_size); assert(ins == cur_ins); - for (size_t i = 0;i < buf_size; ++i) { + for (size_t i = 0; i < buf_size; ++i) + { assert((dst + writeableOffset)[i] == mock_dst[i]); } } void emitter::assertOptsI(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) { - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; instruction ins; - ssize_t imm = (ssize_t)(id->idAddr()->iiaAddr); - regNumber reg1 = id->idReg1(); - code_t code; + ssize_t imm = (ssize_t)(id->idAddr()->iiaAddr); + regNumber reg1 = id->idReg1(); + code_t code; switch (id->idCodeSize()) { @@ -3034,17 +3054,18 @@ void emitter::assertOptsI(BYTE* dst, size_t buf_size, const instrDesc* id, instr assert((mock_ptr - mock_dst) == buf_size); assert(cur_ins == ins); - for (size_t i = 0;i < buf_size; ++i) { + for (size_t i = 0; i < buf_size; ++i) + { assert((dst + writeableOffset)[i] == mock_dst[i]); } } void emitter::assertOptsRc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) { - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; instruction ins; - code_t code; + code_t code; assert(id->idAddr()->iiaIsJitDataOffset()); assert(id->idGCref() == GCT_NONE); @@ -3076,7 +3097,7 @@ void emitter::assertOptsRc(BYTE* dst, size_t buf_size, const instrDesc* id, inst code = emitInsCode(INS_auipc); assert(code == 0x00000017); #endif - code = 0x00000017 | (codeGen->rsGetRsvdReg() << 7); + code = 0x00000017 | (codeGen->rsGetRsvdReg() << 7); *(code_t*)mock_ptr = code | ((code_t)((imm + 0x800) & 0xfffff000)); mock_ptr += 4; @@ -3088,7 +3109,7 @@ void emitter::assertOptsRc(BYTE* dst, size_t buf_size, const instrDesc* id, inst code = emitInsCode(INS_addi); assert(code == 0x00000013); #endif - code = 0x00000013 | (codeGen->rsGetRsvdReg() << 15); + code = 0x00000013 | (codeGen->rsGetRsvdReg() << 15); *(code_t*)mock_ptr = code | ((code_t)reg1 << 7) | (((code_t)doff & 0xfff) << 20); } else @@ -3179,19 +3200,20 @@ void emitter::assertOptsRc(BYTE* dst, size_t buf_size, const instrDesc* id, inst assert((mock_ptr - mock_dst) == buf_size); assert(cur_ins == ins); - for (size_t i = 0;i < buf_size; ++i) { + for (size_t i = 0; i < buf_size; ++i) + { assert((dst + writeableOffset)[i] == mock_dst[i]); } } void emitter::assertOptsRl(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) { - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; instruction ins; - code_t code; + code_t code; - insGroup* tgtIG = (insGroup*)id->idAddr()->iiaIGlabel; + insGroup* tgtIG = (insGroup*)id->idAddr()->iiaIGlabel; regNumber reg1 = id->idReg1(); assert(isGeneralRegister(reg1)); @@ -3205,7 +3227,7 @@ void emitter::assertOptsRl(BYTE* dst, size_t buf_size, const instrDesc* id, inst int doff = (int)(imm & 0xfff); assert(isValidSimm20((imm + 0x800) >> 12)); - code = 0x00000017; + code = 0x00000017; *(code_t*)mock_ptr = code | (code_t)reg1 << 7 | ((imm + 0x800) & 0xfffff000); mock_ptr += 4; #ifdef DEBUG @@ -3214,7 +3236,7 @@ void emitter::assertOptsRl(BYTE* dst, size_t buf_size, const instrDesc* id, inst code = emitInsCode(INS_addi); assert(code == 0x00000013); #endif - ins = INS_addi; + ins = INS_addi; *(code_t*)mock_ptr = 0x00000013 | ((code_t)reg1 << 7) | ((code_t)reg1 << 15) | ((doff & 0xfff) << 20); } else @@ -3262,17 +3284,19 @@ void emitter::assertOptsRl(BYTE* dst, size_t buf_size, const instrDesc* id, inst assert((mock_ptr - mock_dst) == buf_size); assert(cur_ins == ins); - for (size_t i = 0;i < buf_size; ++i) { + for (size_t i = 0; i < buf_size; ++i) + { assert((dst + writeableOffset)[i] == mock_dst[i]); } } -void emitter::assertOptsJarl(BYTE* dst, size_t buf_size, instrDescJmp* jmp, const insGroup* ig, const instrDesc* id, instruction cur_ins) +void emitter::assertOptsJarl( + BYTE* dst, size_t buf_size, instrDescJmp* jmp, const insGroup* ig, const instrDesc* id, instruction cur_ins) { - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; instruction ins; - code_t code; + code_t code; regNumber reg1 = id->idReg1(); { @@ -3288,7 +3312,7 @@ void emitter::assertOptsJarl(BYTE* dst, size_t buf_size, instrDescJmp* jmp, cons case 8: { assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || - (INS_bnez == ins) || (INS_beqz == 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)); @@ -3369,7 +3393,7 @@ void emitter::assertOptsJarl(BYTE* dst, size_t buf_size, instrDescJmp* jmp, cons case 28: { assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || - (INS_bnez == ins) || (INS_beqz == 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)); @@ -3444,17 +3468,18 @@ void emitter::assertOptsJarl(BYTE* dst, size_t buf_size, instrDescJmp* jmp, cons assert((mock_ptr - mock_dst) == buf_size); assert(cur_ins == ins); - for (size_t i = 0;i < buf_size; ++i) { + for (size_t i = 0; i < buf_size; ++i) + { assert((dst + writeableOffset)[i] == mock_dst[i]); } } void emitter::assertOptsJCond(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins) { - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; instruction ins; - code_t code; + code_t code; ssize_t imm = emitOutputInstrJumpDistance(dst, ig, static_cast(id)); assert(isValidSimm13(imm)); @@ -3473,17 +3498,18 @@ void emitter::assertOptsJCond(BYTE* dst, size_t buf_size, const insGroup* ig, in assert(cur_ins == ins); - for (size_t i = 0;i < buf_size; ++i) { + for (size_t i = 0; i < buf_size; ++i) + { assert((dst + writeableOffset)[i] == mock_dst[i]); } } void emitter::assertOptsJ(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins) { - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; + BYTE mock_dst[1024]; + BYTE* mock_ptr = mock_dst; instruction ins; - code_t code; + code_t code; ssize_t imm = emitOutputInstrJumpDistance(dst, ig, static_cast(id)); assert((imm & 3) == 0); @@ -3543,7 +3569,8 @@ void emitter::assertOptsJ(BYTE* dst, size_t buf_size, const insGroup* ig, instrD assert(cur_ins == ins); - for (size_t i = 0;i < buf_size; ++i) { + for (size_t i = 0; i < buf_size; ++i) + { assert((dst + writeableOffset)[i] == mock_dst[i]); } } @@ -3573,7 +3600,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) case INS_OPTS_RELOC: dst = emitOutputInstr_OptsReloc(dst, id, &ins); assertOptsReloc(*dp, dst - *dp, id, ins); - sz = sizeof(instrDesc); + sz = sizeof(instrDesc); break; case INS_OPTS_I: dst = emitOutputInstr_OptsI(dst, id); @@ -3589,7 +3616,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) case INS_OPTS_RL: dst = emitOutputInstr_OptsRl(dst, id, &ins); assertOptsRl(*dp, dst - *dp, id, ins); - sz = sizeof(instrDesc); + sz = sizeof(instrDesc); break; case INS_OPTS_JALR: dst = emitOutputInstr_OptsJalr(dst, static_cast(id), ig, &ins); diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index f46bea08157a4c..ad00247b5add26 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -104,6 +104,7 @@ static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); unsigned emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const; unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const; +unsigned emitOutput_ITypeInstr_Shift(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int shamt) const; unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const; unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm20) const; unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const; From 38132309628e615513b177f87d92cc97f856ac8d Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 8 Jan 2024 15:49:28 +0100 Subject: [PATCH 068/106] Improved shift func --- src/coreclr/jit/emitriscv64.cpp | 34 +++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index d4297e5edb8d97..ef9851850b7be9 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2345,11 +2345,37 @@ unsigned emitOutput_ITypeInstr_Shift(BYTE* dst, instruction ins, regNumber rs1, unsigned insCode = emitInsCode(ins); #ifdef DEBUG - static constexpr unsigned kInstructionMask = - ~(kInstructionOpcodeMask | kInstructionFunct3Mask | kInstructionFunct7Mask); + switch (ins) + { + case INS_slli: + FALLTHROUGH; + case INS_srli: + FALLTHROUGH; + case INS_srai: + { + static constexpr unsigned kInstructionMask = + ~(kInstructionOpcodeMask | kInstructionFunct3Mask | (kInstructionFunct7Mask - 1)); - assert((insCode & kInstructionMask) == 0); - assert(shamt < 32); + assert((insCode & kInstructionMask) == 0); + assert(shamt < 64); + } + break; + case INS_slliw: + FALLTHROUGH; + case INS_srliw: + FALLTHROUGH; + case INS_sraiw: + { + static constexpr unsigned kInstructionMask = + ~(kInstructionOpcodeMask | kInstructionFunct3Mask | kInstructionFunct7Mask); + + assert((insCode & kInstructionMask) == 0); + assert(shamt < 32); + } + break; + default: + unreached(); + } #endif // DEBUG unsigned opcode = insCode & kInstructionOpcodeMask; From ee5feab61c972fe0686a584d1cc766478377a2da Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 8 Jan 2024 15:52:02 +0100 Subject: [PATCH 069/106] Inserted shift func --- src/coreclr/jit/emitriscv64.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index ef9851850b7be9..f3e6f76a51d47e 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2664,7 +2664,7 @@ BYTE* emitter::emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t im // special for INT64_MAX or UINT32_MAX dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, REG_R0, 0xfff); ssize_t shiftValue = (immediate == INT64_MAX) ? 1 : 32; - dst += emitOutput_ITypeInstr(dst, INS_srli, reg1, reg1, shiftValue); + dst += emitOutput_ITypeInstr_Shift(dst, INS_srli, reg1, reg1, shiftValue); } else { @@ -2680,11 +2680,11 @@ BYTE* emitter::emitOutputInstr_OptsI32(BYTE* dst, ssize_t immediate, regNumber r dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, UpperNBitsOfWordSignExtend<20>(upperWord)); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<12>(upperWord)); ssize_t lowerWord = LowerWordOfDoubleWord(immediate); - dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 11); + dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, reg1, reg1, 11); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<11>(lowerWord >> 21)); - dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 11); + dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, reg1, reg1, 11); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<11>(lowerWord >> 10)); - dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 10); + dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, reg1, reg1, 10); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<10>(lowerWord)); return dst; } @@ -2744,7 +2744,7 @@ BYTE* emitter::emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsign dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(high)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(high)); - dst += emitOutput_ITypeInstr(dst, INS_slli, rsvdReg, rsvdReg, 11); + dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, rsvdReg, rsvdReg, 11); dst += emitOutput_ITypeInstr(dst, lastIns, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); return dst; } @@ -2788,7 +2788,7 @@ BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumbe dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(immediate)); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, REG_ZERO, LowerNBitsOfWord<12>(upperSignExt)); - dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 32); + dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, reg1, reg1, 32); dst += emitOutput_RTypeInstr(dst, INS_add, reg1, reg1, rsvdReg); return dst; } @@ -2836,7 +2836,7 @@ BYTE* emitter::emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate) dst += emitOutput_UTypeInstr(dst, INS_lui, REG_RA, UpperNBitsOfWordSignExtend<20>(high)); dst += emitOutput_ITypeInstr(dst, INS_addi, REG_RA, REG_RA, LowerNBitsOfWord<12>(high)); - dst += emitOutput_ITypeInstr(dst, INS_slli, REG_RA, REG_RA, 32); + dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, REG_RA, REG_RA, 32); regNumber rsvdReg = codeGen->rsGetRsvdReg(); ssize_t low = LowerWordOfDoubleWord(immediate); From 6b9ec0d0f92bdff3171744a38e99ced8b3a93413 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 8 Jan 2024 15:53:26 +0100 Subject: [PATCH 070/106] Fixed minor bug --- 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 f3e6f76a51d47e..6bba938b394d32 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2340,7 +2340,7 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd & 0x1f, funct3, rs1 & 0x1f, imm12)); } -unsigned emitOutput_ITypeInstr_Shift(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int shamt) const +unsigned emitter::emitOutput_ITypeInstr_Shift(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int shamt) const { unsigned insCode = emitInsCode(ins); From c849405270db0ef973f03c7a4693743e569ebaf2 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 8 Jan 2024 15:54:43 +0100 Subject: [PATCH 071/106] Other fixes --- src/coreclr/jit/emitriscv64.cpp | 3 ++- src/coreclr/jit/emitriscv64.h | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 6bba938b394d32..9ae7285321c2b2 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2340,7 +2340,8 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd & 0x1f, funct3, rs1 & 0x1f, imm12)); } -unsigned emitter::emitOutput_ITypeInstr_Shift(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int shamt) const +unsigned emitter::emitOutput_ITypeInstr_Shift( + BYTE* dst, instruction ins, regNumber rd, regNumber rs1, unsigned shamt) const { unsigned insCode = emitInsCode(ins); diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index ad00247b5add26..dcd3fcc2234f95 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -104,7 +104,7 @@ static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); unsigned emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const; unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const; -unsigned emitOutput_ITypeInstr_Shift(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int shamt) const; +unsigned emitOutput_ITypeInstr_Shift(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, unsigned shamt) const; unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const; unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm20) const; unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const; @@ -130,12 +130,12 @@ BYTE* emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, in BYTE* emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins); BYTE* emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* ig, size_t* size); - void assertOptsReloc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); void assertOptsI(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); void assertOptsRc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); void assertOptsRl(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); -void assertOptsJarl(BYTE* dst, size_t buf_size, instrDescJmp* jmp, const insGroup* ig, const instrDesc* id, instruction cur_ins); +void assertOptsJarl( + BYTE* dst, size_t buf_size, instrDescJmp* jmp, const insGroup* ig, const instrDesc* id, instruction cur_ins); void assertOptsJCond(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins); void assertOptsJ(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins); From bddb8353bd746b1b83095921284ea3181f167d4a Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 8 Jan 2024 16:49:41 +0100 Subject: [PATCH 072/106] Added checks to r type emitter --- src/coreclr/jit/emitriscv64.cpp | 111 +++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 9ae7285321c2b2..146d2bb1dd936e 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2294,6 +2294,112 @@ static constexpr unsigned kInstructionOpcodeMask = 0x7f; static constexpr unsigned kInstructionFunct3Mask = 0x7000; static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; +static bool IsIntegralRegister(regNumber reg) { + return (reg >= 0) && (reg <= 31); +} + +static bool IsFloatRegister(regNumber reg) { + return (reg >= FBASE) && (reg <= (FBASE + 31)); +} + +static void CheckIfInstructionIsValidForRTypeInstr(instruction ins, regNumber rd, regNumber rs1, regNumber rs2) { + switch (ins) { + case INS_addw: + FALLTHROUGH; + case INS_subw: + FALLTHROUGH; + case INS_sllw: + FALLTHROUGH; + case INS_slrw: + FALLTHROUGH; + case INS_sraw: + FALLTHROUGH; + case INS_mul: + FALLTHROUGH; + case INS_mulh: + FALLTHROUGH; + case INS_mulhsu: + FALLTHROUGH; + case INS_mulhu: + FALLTHROUGH; + case INS_div: + FALLTHROUGH; + case INS_divu: + FALLTHROUGH; + case INS_rem: + FALLTHROUGH; + case INS_remu: + FALLTHROUGH; + case INS_mulw: + FALLTHROUGH; + case INS_divw: + FALLTHROUGH; + case INS_divuw: + FALLTHROUGH; + case INS_remw: + FALLTHROUGH; + case INS_remuw: + assert(IsIntegralRegister(rd)); + assert(IsIntegralRegister(rs1)); + assert(IsIntegralRegister(rs2)); + break; + case INS_fadd_s: + FALLTHROUGH; + case INS_fsub_s: + FALLTHROUGH; + case INS_fmul_s: + FALLTHROUGH; + case INS_fdiv_s: + FALLTHROUGH; + case INS_sgnj_s: + FALLTHROUGH; + case INS_sgnjn_s: + FALLTHROUGH; + case INS_sgnjx_s: + FALLTHROUGH; + case INS_fmin_s: + FALLTHROUGH; + case INS_fmax_s: + FALLTHROUGH; + case INS_feq_s: + FALLTHROUGH; + case INS_flt_s: + FALLTHROUGH; + case INS_fle_s: + FALLTHROUGH; + case INS_fadd_d: + FALLTHROUGH; + case INS_fsub_d: + FALLTHROUGH; + case INS_fmul_d: + FALLTHROUGH; + case INS_fdiv_d: + FALLTHROUGH; + case INS_sgnj_d: + FALLTHROUGH; + case INS_sgnjn_d: + FALLTHROUGH; + case INS_sgnjx_d: + FALLTHROUGH; + case INS_fmin_d: + FALLTHROUGH; + case INS_fmax_d: + FALLTHROUGH; + case INS_feq_d: + FALLTHROUGH; + case INS_flt_d: + FALLTHROUGH; + case INS_fle_d: + assert(IsFloatRegister(rd)); + assert(IsFloatRegister(rs1)); + assert(IsFloatRegister(rs2)); + break; + default: + NO_WAY("Illegal ins within emitOutput_RTypeInstr!"); + break; + } +} + /***************************************************************************** * * Emit a 32-bit RISCV64 R-Type instruction to the given buffer. Returns a @@ -2310,6 +2416,8 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd ~(kInstructionOpcodeMask | kInstructionFunct3Mask | kInstructionFunct7Mask); assert((insCode & kInstructionMask) == 0); + + CheckIfInstructionIsValidForRTypeInstr(ins, rd, rs1, rs2); #endif // DEBUG unsigned opcode = insCode & kInstructionOpcodeMask; @@ -2375,7 +2483,8 @@ unsigned emitter::emitOutput_ITypeInstr_Shift( } break; default: - unreached(); + NO_WAY("Illegal ins within emitOutput_ITypeInstr_Shift!"); + return; } #endif // DEBUG From 3fedc7a841e2d3f0c87a9ba65773167272b0cc41 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 09:43:38 +0100 Subject: [PATCH 073/106] Improved sanity checks in the emitOutput_RTypeInstr --- src/coreclr/jit/emitriscv64.cpp | 49 +++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 146d2bb1dd936e..48cadf49328a89 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2302,15 +2302,35 @@ static bool IsFloatRegister(regNumber reg) { return (reg >= FBASE) && (reg <= (FBASE + 31)); } -static void CheckIfInstructionIsValidForRTypeInstr(instruction ins, regNumber rd, regNumber rs1, regNumber rs2) { +static void RTypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber rs1, regNumber rs2) { switch (ins) { + case INS_add: + FALLTHROUGH; + case INS_sub: + FALLTHROUGH; + case INS_sll: + FALLTHROUGH; + case INS_slt: + FALLTHROUGH; + case INS_sltu: + FALLTHROUGH; + case INS_xor: + FALLTHROUGH; + case INS_srl: + FALLTHROUGH; + case INS_sra: + FALLTHROUGH; + case INS_or: + FALLTHROUGH; + case INS_and: + FALLTHROUGH; case INS_addw: FALLTHROUGH; case INS_subw: FALLTHROUGH; case INS_sllw: FALLTHROUGH; - case INS_slrw: + case INS_srlw: FALLTHROUGH; case INS_sraw: FALLTHROUGH; @@ -2351,11 +2371,11 @@ static void CheckIfInstructionIsValidForRTypeInstr(instruction ins, regNumber rd FALLTHROUGH; case INS_fdiv_s: FALLTHROUGH; - case INS_sgnj_s: + case INS_fsgnj_s: FALLTHROUGH; - case INS_sgnjn_s: + case INS_fsgnjn_s: FALLTHROUGH; - case INS_sgnjx_s: + case INS_fsgnjx_s: FALLTHROUGH; case INS_fmin_s: FALLTHROUGH; @@ -2375,11 +2395,11 @@ static void CheckIfInstructionIsValidForRTypeInstr(instruction ins, regNumber rd FALLTHROUGH; case INS_fdiv_d: FALLTHROUGH; - case INS_sgnj_d: + case INS_fsgnj_d: FALLTHROUGH; - case INS_sgnjn_d: + case INS_fsgnjn_d: FALLTHROUGH; - case INS_sgnjx_d: + case INS_fsgnjx_d: FALLTHROUGH; case INS_fmin_d: FALLTHROUGH; @@ -2409,17 +2429,10 @@ static void CheckIfInstructionIsValidForRTypeInstr(instruction ins, regNumber rd unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const { - unsigned insCode = emitInsCode(ins); - #ifdef DEBUG - static constexpr unsigned kInstructionMask = - ~(kInstructionOpcodeMask | kInstructionFunct3Mask | kInstructionFunct7Mask); - - assert((insCode & kInstructionMask) == 0); - - CheckIfInstructionIsValidForRTypeInstr(ins, rd, rs1, rs2); + RTypeInstructionSanityCheck(ins, rd, rs1, rs2); #endif // DEBUG - + unsigned insCode = emitInsCode(ins); unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 25; @@ -2484,7 +2497,7 @@ unsigned emitter::emitOutput_ITypeInstr_Shift( break; default: NO_WAY("Illegal ins within emitOutput_ITypeInstr_Shift!"); - return; + break; } #endif // DEBUG From 34b6a286b7673557a7bce4112721aaa4c9cba719 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 10:05:30 +0100 Subject: [PATCH 074/106] Added ITypeInstr sanity checks --- src/coreclr/jit/emitriscv64.cpp | 90 ++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 48cadf49328a89..d286049b519c7f 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2294,16 +2294,22 @@ static constexpr unsigned kInstructionOpcodeMask = 0x7f; static constexpr unsigned kInstructionFunct3Mask = 0x7000; static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; -static bool IsIntegralRegister(regNumber reg) { +#ifdef DEBUG + +static bool IsIntegralRegister(regNumber reg) +{ return (reg >= 0) && (reg <= 31); } -static bool IsFloatRegister(regNumber reg) { +static bool IsFloatRegister(regNumber reg) +{ return (reg >= FBASE) && (reg <= (FBASE + 31)); } -static void RTypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber rs1, regNumber rs2) { - switch (ins) { +static void RTypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber rs1, regNumber rs2) +{ + switch (ins) + { case INS_add: FALLTHROUGH; case INS_sub: @@ -2414,12 +2420,64 @@ static void RTypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber assert(IsFloatRegister(rs1)); assert(IsFloatRegister(rs2)); break; - default: - NO_WAY("Illegal ins within emitOutput_RTypeInstr!"); - break; + default: + NO_WAY("Illegal ins within emitOutput_RTypeInstr!"); + break; } } +static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber rs1) +{ + switch (ins) + { + case INS_jalr: + FALLTHROUGH; + case INS_lb: + FALLTHROUGH; + case INS_lh: + FALLTHROUGH; + case INS_lw: + FALLTHROUGH; + case INS_lbu: + FALLTHROUGH; + case INS_lhu: + FALLTHROUGH; + case INS_addi: + FALLTHROUGH; + case INS_slti: + FALLTHROUGH; + case INS_sltiu: + FALLTHROUGH; + case INS_xori: + FALLTHROUGH; + case INS_ori: + FALLTHROUGH; + case INS_andi: + FALLTHROUGH; + case INS_lwu: + FALLTHROUGH; + case INS_ld: + FALLTHROUGH; + case INS_addiw: + FALLTHROUGH; + case INS_fence_i: + assert(IsIntegralRegister(rd)); + assert(IsIntegralRegister(rs1)); + break; + case INS_flw: + FALLTHROUGH; + case INS_fld: + assert(IsFloatRegister(rd)); + assert(IsFloatRegister(rs1)); + break; + default: + NO_WAY("Illegal ins within emitOutput_ITypeInstr!"); + break; + } +} + +#endif // DEBUG + /***************************************************************************** * * Emit a 32-bit RISCV64 R-Type instruction to the given buffer. Returns a @@ -2433,9 +2491,9 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd RTypeInstructionSanityCheck(ins, rd, rs1, rs2); #endif // DEBUG unsigned insCode = emitInsCode(ins); - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 25; + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 25; return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7)); } @@ -2448,16 +2506,12 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const { - unsigned insCode = emitInsCode(ins); - #ifdef DEBUG - static constexpr unsigned kInstructionMask = ~(kInstructionOpcodeMask | kInstructionFunct3Mask); - - assert((insCode & kInstructionMask) == 0); + ITypeInstructionSanityCheck(ins, rd, rs1); #endif // DEBUG - - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned insCode = emitInsCode(ins); + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd & 0x1f, funct3, rs1 & 0x1f, imm12)); } From b3b88a469a770b691ce356960b2ce65f884f8f88 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 10:09:11 +0100 Subject: [PATCH 075/106] Moved ITypeInstr_Shift sanity Check --- src/coreclr/jit/emitriscv64.cpp | 69 +++++++++++++++------------------ 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index d286049b519c7f..ac7790321ccfde 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2476,6 +2476,32 @@ static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber } } +static void ITypeShiftInstructionSanityCheck(instruction ins, regNumber rd, regNumber rs1, unsigned shamt) +{ + assert(IsIntegralRegister(rd)); + assert(IsIntegralRegister(rs1)); + switch (ins) + { + case INS_slli: + FALLTHROUGH; + case INS_srli: + FALLTHROUGH; + case INS_srai: + assert(shamt < 64); + break; + case INS_slliw: + FALLTHROUGH; + case INS_srliw: + FALLTHROUGH; + case INS_sraiw: + assert(shamt < 32); + break; + default: + NO_WAY("Illegal ins within emitOutput_ITypeInstr_Shift!"); + break; + } +} + #endif // DEBUG /***************************************************************************** @@ -2518,46 +2544,13 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned emitter::emitOutput_ITypeInstr_Shift( BYTE* dst, instruction ins, regNumber rd, regNumber rs1, unsigned shamt) const { - unsigned insCode = emitInsCode(ins); - #ifdef DEBUG - switch (ins) - { - case INS_slli: - FALLTHROUGH; - case INS_srli: - FALLTHROUGH; - case INS_srai: - { - static constexpr unsigned kInstructionMask = - ~(kInstructionOpcodeMask | kInstructionFunct3Mask | (kInstructionFunct7Mask - 1)); - - assert((insCode & kInstructionMask) == 0); - assert(shamt < 64); - } - break; - case INS_slliw: - FALLTHROUGH; - case INS_srliw: - FALLTHROUGH; - case INS_sraiw: - { - static constexpr unsigned kInstructionMask = - ~(kInstructionOpcodeMask | kInstructionFunct3Mask | kInstructionFunct7Mask); - - assert((insCode & kInstructionMask) == 0); - assert(shamt < 32); - } - break; - default: - NO_WAY("Illegal ins within emitOutput_ITypeInstr_Shift!"); - break; - } + ITypeShiftInstructionSanityCheck(ins, rd, rs1, shamt); #endif // DEBUG - - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 20; // prepared for masking + unsigned insCode = emitInsCode(ins); + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 20; // prepared for masking return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, shamt | funct7)); } From ddefdc28954a5bd040a3e9f4649df838f16cc753 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 10:10:47 +0100 Subject: [PATCH 076/106] Added comment to the emitriscv64 --- 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 ac7790321ccfde..d5ac32592760a6 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2541,6 +2541,13 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd & 0x1f, funct3, rs1 & 0x1f, imm12)); } +/***************************************************************************** + * + * Emit a 32-bit RISCV64 I-Type shift instruction to the given buffer. Returns a + * length of an encoded instruction opcode + * + */ + unsigned emitter::emitOutput_ITypeInstr_Shift( BYTE* dst, instruction ins, regNumber rd, regNumber rs1, unsigned shamt) const { From 7bdb37ef17140a2402b85a49c2c34b9f2c66e766 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 10:24:58 +0100 Subject: [PATCH 077/106] Added S-type sanity checks --- src/coreclr/jit/emitriscv64.cpp | 38 ++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index d5ac32592760a6..203e50e9faab4c 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2467,8 +2467,7 @@ static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber case INS_flw: FALLTHROUGH; case INS_fld: - assert(IsFloatRegister(rd)); - assert(IsFloatRegister(rs1)); + assert((IsFloatRegister(rd) && IsIntegralRegister(rs1))); break; default: NO_WAY("Illegal ins within emitOutput_ITypeInstr!"); @@ -2502,6 +2501,29 @@ static void ITypeShiftInstructionSanityCheck(instruction ins, regNumber rd, regN } } +static void STypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumber rs2) +{ + switch (ins) + { + case INS_sb; FALLTHROUGH; case INS_sh: + FALLTHROUGH; + case INS_sw: + FALLTHROUGH; + case INS_sd: + assert(IsIntegralRegister(rs1)); + assert(IsIntegralRegister(rs2)); + break; + case INS_fsw: + FALLTHROUGH; + case INS_fsd: + assert((IsFloatRegister(rs1) && IsIntegralRegister(rs2))); + break; + default: + NO_WAY("Illegal ins within emitOutput_STypeInstr!"); + break; + } +} + #endif // DEBUG /***************************************************************************** @@ -2570,16 +2592,12 @@ unsigned emitter::emitOutput_ITypeInstr_Shift( unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const { - unsigned insCode = emitInsCode(ins); - #ifdef DEBUG - static constexpr unsigned kInstructionMask = ~(kInstructionOpcodeMask | kInstructionFunct3Mask); - - assert((insCode & kInstructionMask) == 0); + STypeInstructionSanityCheck(ins, rs1, rs2); #endif // DEBUG - - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned insCode = emitInsCode(ins); + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2, imm12)); } From b763720dd30f80fae29795000b1811c13be65c3b Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 10:44:04 +0100 Subject: [PATCH 078/106] Removed Shift ITypeInstr Variant --- src/coreclr/jit/emitriscv64.cpp | 71 ++++++++++++--------------------- src/coreclr/jit/emitriscv64.h | 1 - 2 files changed, 25 insertions(+), 47 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 203e50e9faab4c..8c9c6d84d46328 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2426,7 +2426,7 @@ static void RTypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber } } -static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber rs1) +static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber rs1, int immediate, unsigned opcode) { switch (ins) { @@ -2463,40 +2463,35 @@ static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber case INS_fence_i: assert(IsIntegralRegister(rd)); assert(IsIntegralRegister(rs1)); + assert((opcode & kInstructionFunct7Mask) == 0); break; case INS_flw: FALLTHROUGH; case INS_fld: - assert((IsFloatRegister(rd) && IsIntegralRegister(rs1))); - break; - default: - NO_WAY("Illegal ins within emitOutput_ITypeInstr!"); + assert(IsFloatRegister(rd)); + assert(IsIntegralRegister(rs1)); + assert((opcode & kInstructionFunct7Mask) == 0); break; - } -} - -static void ITypeShiftInstructionSanityCheck(instruction ins, regNumber rd, regNumber rs1, unsigned shamt) -{ - assert(IsIntegralRegister(rd)); - assert(IsIntegralRegister(rs1)); - switch (ins) - { case INS_slli: FALLTHROUGH; case INS_srli: FALLTHROUGH; case INS_srai: - assert(shamt < 64); + assert(0 <= immediate < 64); + assert(IsIntegralRegister(rd)); + assert(IsIntegralRegister(rs1)); break; case INS_slliw: FALLTHROUGH; case INS_srliw: FALLTHROUGH; case INS_sraiw: - assert(shamt < 32); + assert(0 <= immediate < 32); + assert(IsIntegralRegister(rd)); + assert(IsIntegralRegister(rs1)); break; default: - NO_WAY("Illegal ins within emitOutput_ITypeInstr_Shift!"); + NO_WAY("Illegal ins within emitOutput_ITypeInstr!"); break; } } @@ -2505,7 +2500,9 @@ static void STypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumbe { switch (ins) { - case INS_sb; FALLTHROUGH; case INS_sh: + case INS_sb: + FALLTHROUGH; + case INS_sh: FALLTHROUGH; case INS_sw: FALLTHROUGH; @@ -2554,33 +2551,15 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const { -#ifdef DEBUG - ITypeInstructionSanityCheck(ins, rd, rs1); -#endif // DEBUG unsigned insCode = emitInsCode(ins); - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd & 0x1f, funct3, rs1 & 0x1f, imm12)); -} - -/***************************************************************************** - * - * Emit a 32-bit RISCV64 I-Type shift instruction to the given buffer. Returns a - * length of an encoded instruction opcode - * - */ - -unsigned emitter::emitOutput_ITypeInstr_Shift( - BYTE* dst, instruction ins, regNumber rd, regNumber rs1, unsigned shamt) const -{ #ifdef DEBUG - ITypeShiftInstructionSanityCheck(ins, rd, rs1, shamt); + ITypeInstructionSanityCheck(ins, rd, rs1, imm12, imm12, insCode); #endif // DEBUG unsigned insCode = emitInsCode(ins); unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 20; // prepared for masking - return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd, funct3, rs1, shamt | funct7)); + unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 20; // only used by some of the immediate shifts + return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd & 0x1f, funct3, rs1, imm12 | funct7)); } /***************************************************************************** @@ -2859,7 +2838,7 @@ BYTE* emitter::emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t im // special for INT64_MAX or UINT32_MAX dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, REG_R0, 0xfff); ssize_t shiftValue = (immediate == INT64_MAX) ? 1 : 32; - dst += emitOutput_ITypeInstr_Shift(dst, INS_srli, reg1, reg1, shiftValue); + dst += emitOutput_ITypeInstr(dst, INS_srli, reg1, reg1, shiftValue); } else { @@ -2875,11 +2854,11 @@ BYTE* emitter::emitOutputInstr_OptsI32(BYTE* dst, ssize_t immediate, regNumber r dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, UpperNBitsOfWordSignExtend<20>(upperWord)); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<12>(upperWord)); ssize_t lowerWord = LowerWordOfDoubleWord(immediate); - dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, reg1, reg1, 11); + dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 11); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<11>(lowerWord >> 21)); - dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, reg1, reg1, 11); + dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 11); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<11>(lowerWord >> 10)); - dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, reg1, reg1, 10); + dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 10); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<10>(lowerWord)); return dst; } @@ -2939,7 +2918,7 @@ BYTE* emitter::emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsign dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(high)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(high)); - dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, rsvdReg, rsvdReg, 11); + dst += emitOutput_ITypeInstr(dst, INS_slli, rsvdReg, rsvdReg, 11); dst += emitOutput_ITypeInstr(dst, lastIns, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); return dst; } @@ -2983,7 +2962,7 @@ BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumbe dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(immediate)); dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, REG_ZERO, LowerNBitsOfWord<12>(upperSignExt)); - dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, reg1, reg1, 32); + dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 32); dst += emitOutput_RTypeInstr(dst, INS_add, reg1, reg1, rsvdReg); return dst; } @@ -3031,7 +3010,7 @@ BYTE* emitter::emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate) dst += emitOutput_UTypeInstr(dst, INS_lui, REG_RA, UpperNBitsOfWordSignExtend<20>(high)); dst += emitOutput_ITypeInstr(dst, INS_addi, REG_RA, REG_RA, LowerNBitsOfWord<12>(high)); - dst += emitOutput_ITypeInstr_Shift(dst, INS_slli, REG_RA, REG_RA, 32); + dst += emitOutput_ITypeInstr(dst, INS_slli, REG_RA, REG_RA, 32); regNumber rsvdReg = codeGen->rsGetRsvdReg(); ssize_t low = LowerWordOfDoubleWord(immediate); diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index dcd3fcc2234f95..a68a309d963f16 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -104,7 +104,6 @@ static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); unsigned emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const; unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const; -unsigned emitOutput_ITypeInstr_Shift(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, unsigned shamt) const; unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const; unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm20) const; unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const; From a147ef5c947fed968f47c1ced0813d4ecac31a31 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 10:53:54 +0100 Subject: [PATCH 079/106] Fixes --- src/coreclr/jit/emitriscv64.cpp | 46 +++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 8c9c6d84d46328..3bcf5e964ab225 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2513,7 +2513,8 @@ static void STypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumbe case INS_fsw: FALLTHROUGH; case INS_fsd: - assert((IsFloatRegister(rs1) && IsIntegralRegister(rs2))); + assert(IsFloatRegister(rs1)); + assert(IsIntegralRegister(rs2)); break; default: NO_WAY("Illegal ins within emitOutput_STypeInstr!"); @@ -2521,6 +2522,21 @@ static void STypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumbe } } +static void UTypeInstructionSanityCheck(instruction ins, regNumber rd) +{ + switch (ins) + { + case INS_lui: + FALLTHROUGH; + case INS_auipc: + assert(IsIntegralRegister(rd)); + break; + default: + NO_WAY("Illegal ins within emitOutput_UTypeInstr!"); + break; + } +} + #endif // DEBUG /***************************************************************************** @@ -2532,13 +2548,13 @@ static void STypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumbe unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const { + unsigned insCode = emitInsCode(ins); #ifdef DEBUG RTypeInstructionSanityCheck(ins, rd, rs1, rs2); #endif // DEBUG - unsigned insCode = emitInsCode(ins); - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 25; + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 25; return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7)); } @@ -2553,12 +2569,11 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd { unsigned insCode = emitInsCode(ins); #ifdef DEBUG - ITypeInstructionSanityCheck(ins, rd, rs1, imm12, imm12, insCode); + ITypeInstructionSanityCheck(ins, rd, rs1, imm12, insCode); #endif // DEBUG - unsigned insCode = emitInsCode(ins); - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 20; // only used by some of the immediate shifts + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 20; // only used by some of the immediate shifts return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd & 0x1f, funct3, rs1, imm12 | funct7)); } @@ -2571,13 +2586,13 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const { + unsigned insCode = emitInsCode(ins); #ifdef DEBUG STypeInstructionSanityCheck(ins, rs1, rs2); #endif // DEBUG - unsigned insCode = emitInsCode(ins); - unsigned opcode = insCode & kInstructionOpcodeMask; - unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2, imm12)); + unsigned opcode = insCode & kInstructionOpcodeMask; + unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; + return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2 & 0x1f, imm12)); } /***************************************************************************** @@ -2590,6 +2605,9 @@ unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm20) const { unsigned insCode = emitInsCode(ins); +#ifdef DEBUG + UTypeInstructionSanityCheck(ins, rd); +#endif // DEBUG return emitOutput_Instr(dst, insEncodeUTypeInstr(insCode, rd, imm20)); } From c65ec812febe7c5b79f224ae3143bf7e4f21dcfe Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 11:39:00 +0100 Subject: [PATCH 080/106] Added BType sanity check --- src/coreclr/jit/emitriscv64.cpp | 45 ++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 3bcf5e964ab225..efcb1e808af97c 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2537,6 +2537,35 @@ static void UTypeInstructionSanityCheck(instruction ins, regNumber rd) } } +static void BTypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumber rs2) +{ + switch (ins) + { + case INS_beqz: + FALLTHROUGH; + case INS_bnez: + assert((rs1 == REG_ZERO) || (rs2 == REG_ZERO)); + FALLTHROUGH; + case INS_beq: + FALLTHROUGH; + case INS_bne: + FALLTHROUGH; + case INS_blt: + FALLTHROUGH; + case INS_bge: + FALLTHROUGH; + case INS_bltu: + FALLTHROUGH; + case INS_bgeu: + assert(IsIntegralRegister(rs1)); + assert(IsIntegralRegister(rs2)); + break; + default: + NO_WAY("Illegal ins within emitOutput_BTypeInstr!"); + break; + } +} + #endif // DEBUG /***************************************************************************** @@ -2621,13 +2650,9 @@ unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const { unsigned insCode = emitInsCode(ins); - #ifdef DEBUG - static constexpr unsigned kInstructionMask = ~(kInstructionOpcodeMask | kInstructionFunct3Mask); - - assert((insCode & kInstructionMask) == 0); + BTypeInstructionSanityCheck(ins, rs1, rs2); #endif // DEBUG - unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13)); @@ -2640,8 +2665,8 @@ unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs * * Note: Replaces: * - beqz with bnez and vice versa - * - beq with bne and vide versa - * - blt with bge and vide versa + * - beq with bne and vice versa + * - blt with bge and vice versa * - bltu with bgeu and vice versa */ @@ -2649,13 +2674,9 @@ unsigned emitter::emitOutput_BTypeInstr_InvertComparation( BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const { unsigned insCode = emitInsCode(ins) ^ 0x1000; - #ifdef DEBUG - static constexpr unsigned kInstructionMask = ~(kInstructionOpcodeMask | kInstructionFunct3Mask); - - assert((insCode & kInstructionMask) == 0); + BTypeInstructionSanityCheck(ins, rs1, rs2); #endif // DEBUG - unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; return emitOutput_Instr(dst, insEncodeBTypeInstr(opcode, funct3, rs1, rs2, imm13)); From 9d86e2c72cc7b388145fe8d3f6ef4357fb4b9197 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 11:53:07 +0100 Subject: [PATCH 081/106] Added csr operations to sanity checks --- src/coreclr/jit/emitriscv64.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index efcb1e808af97c..d6553b7d7fad0f 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2461,6 +2461,12 @@ static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber case INS_addiw: FALLTHROUGH; case INS_fence_i: + FALLTHROUGH; + case INS_csrrw: + FALLTHROUGH; + case INS_csrrs: + FALLTHROUGH; + case INS_csrrc: assert(IsIntegralRegister(rd)); assert(IsIntegralRegister(rs1)); assert((opcode & kInstructionFunct7Mask) == 0); @@ -2490,6 +2496,13 @@ static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber assert(IsIntegralRegister(rd)); assert(IsIntegralRegister(rs1)); break; + case INS_csrrwi: + FALLTHROUGH; + case INS_csrrsi: + FALLTHROUGH; + case INS_csrrci: + IsIntegralRegister(rd); + break; default: NO_WAY("Illegal ins within emitOutput_ITypeInstr!"); break; From 4e901da387b552fecf01e875fdc465591e51e2c7 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 12:01:00 +0100 Subject: [PATCH 082/106] Added ITypeInstr sanity check --- src/coreclr/jit/emitriscv64.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index d6553b7d7fad0f..f63edc2be3ab60 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2502,6 +2502,7 @@ static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber FALLTHROUGH; case INS_csrrci: IsIntegralRegister(rd); + assert(rs1 < 32); break; default: NO_WAY("Illegal ins within emitOutput_ITypeInstr!"); @@ -2579,6 +2580,22 @@ static void BTypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumbe } } +static void JTypeInstructionSanityCheck(instruction ins, regNumber rd) +{ + switch (ins) + { + case INS_j: + assert(rd == REG_ZERO); + break; + case INS_jal: + assert(IsIntegralRegister(rd)); + break; + default: + NO_WAY("Illegal ins within emitOutput_JTypeInstr!"); + break; + } +} + #endif // DEBUG /***************************************************************************** @@ -2705,6 +2722,9 @@ unsigned emitter::emitOutput_BTypeInstr_InvertComparation( unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm21) const { unsigned insCode = emitInsCode(ins); +#define DEBUG + JTypeInstructionSanityCheck(ins, rd); +#endif // JTypeInstructionSanityCheck return emitOutput_Instr(dst, insEncodeJTypeInstr(insCode, rd, imm21)); } @@ -2713,8 +2733,6 @@ void emitter::emitOutputInstrJumpDistanceHelper(const insGroup* ig, UNATIVE_OFFSET& dstOffs, const BYTE*& dstAddr) const { - // TODO-RISCV64-BUG: Currently the iiaEncodedInstrCount is not set by the riscv impl making distinguishing the jump - // to label and an instruction-count based jumps impossible if (jmp->idAddr()->iiaHasInstrCount()) { assert(ig != nullptr); From 4f2b7f4790a9e356413dad27e2811861889edd4a Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 12:02:18 +0100 Subject: [PATCH 083/106] Fixes --- 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 f63edc2be3ab60..94b86f57e6799d 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2722,7 +2722,7 @@ unsigned emitter::emitOutput_BTypeInstr_InvertComparation( unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm21) const { unsigned insCode = emitInsCode(ins); -#define DEBUG +#ifdef DEBUG JTypeInstructionSanityCheck(ins, rd); #endif // JTypeInstructionSanityCheck return emitOutput_Instr(dst, insEncodeJTypeInstr(insCode, rd, imm21)); From c1970c68a08b5022c159c888e7778a5108177f09 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 15:56:24 +0100 Subject: [PATCH 084/106] Removed duplicated code --- src/coreclr/jit/emitriscv64.cpp | 83 +++++++++++++++------------------ src/coreclr/jit/emitriscv64.h | 10 ++++ 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 94b86f57e6799d..f4cfc304897880 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2296,17 +2296,7 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; #ifdef DEBUG -static bool IsIntegralRegister(regNumber reg) -{ - return (reg >= 0) && (reg <= 31); -} - -static bool IsFloatRegister(regNumber reg) -{ - return (reg >= FBASE) && (reg <= (FBASE + 31)); -} - -static void RTypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber rs1, regNumber rs2) +/*static*/ void emitter::emitOutput_RTypeInstr_SanityCheck(instruction ins, regNumber rd, regNumber rs1, regNumber rs2) { switch (ins) { @@ -2365,9 +2355,9 @@ static void RTypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber case INS_remw: FALLTHROUGH; case INS_remuw: - assert(IsIntegralRegister(rd)); - assert(IsIntegralRegister(rs1)); - assert(IsIntegralRegister(rs2)); + assert(isGeneralRegisterOrR0(rd)); + assert(isGeneralRegisterOrR0(rs1)); + assert(isGeneralRegisterOrR0(rs2)); break; case INS_fadd_s: FALLTHROUGH; @@ -2416,9 +2406,9 @@ static void RTypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber case INS_flt_d: FALLTHROUGH; case INS_fle_d: - assert(IsFloatRegister(rd)); - assert(IsFloatRegister(rs1)); - assert(IsFloatRegister(rs2)); + assert(isFloatReg(rd)); + assert(isFloatReg(rs1)); + assert(isFloatReg(rs2)); break; default: NO_WAY("Illegal ins within emitOutput_RTypeInstr!"); @@ -2426,7 +2416,8 @@ static void RTypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber } } -static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber rs1, int immediate, unsigned opcode) +/*static*/ void emitter::emitOutput_ITypeInstr_SanityCheck( + instruction ins, regNumber rd, regNumber rs1, int immediate, unsigned opcode) { switch (ins) { @@ -2467,15 +2458,15 @@ static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber case INS_csrrs: FALLTHROUGH; case INS_csrrc: - assert(IsIntegralRegister(rd)); - assert(IsIntegralRegister(rs1)); + assert(isGeneralRegisterOrR0(rd)); + assert(isGeneralRegisterOrR0(rs1)); assert((opcode & kInstructionFunct7Mask) == 0); break; case INS_flw: FALLTHROUGH; case INS_fld: - assert(IsFloatRegister(rd)); - assert(IsIntegralRegister(rs1)); + assert(isFloatReg(rd)); + assert(isGeneralRegisterOrR0(rs1)); assert((opcode & kInstructionFunct7Mask) == 0); break; case INS_slli: @@ -2484,8 +2475,8 @@ static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber FALLTHROUGH; case INS_srai: assert(0 <= immediate < 64); - assert(IsIntegralRegister(rd)); - assert(IsIntegralRegister(rs1)); + assert(isGeneralRegisterOrR0(rd)); + assert(isGeneralRegisterOrR0(rs1)); break; case INS_slliw: FALLTHROUGH; @@ -2493,15 +2484,15 @@ static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber FALLTHROUGH; case INS_sraiw: assert(0 <= immediate < 32); - assert(IsIntegralRegister(rd)); - assert(IsIntegralRegister(rs1)); + assert(isGeneralRegisterOrR0(rd)); + assert(isGeneralRegisterOrR0(rs1)); break; case INS_csrrwi: FALLTHROUGH; case INS_csrrsi: FALLTHROUGH; case INS_csrrci: - IsIntegralRegister(rd); + isGeneralRegisterOrR0(rd); assert(rs1 < 32); break; default: @@ -2510,7 +2501,7 @@ static void ITypeInstructionSanityCheck(instruction ins, regNumber rd, regNumber } } -static void STypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumber rs2) +/*static*/ void emitter::emitOutput_STypeInstr_SanityCheck(instruction ins, regNumber rs1, regNumber rs2) { switch (ins) { @@ -2521,14 +2512,14 @@ static void STypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumbe case INS_sw: FALLTHROUGH; case INS_sd: - assert(IsIntegralRegister(rs1)); - assert(IsIntegralRegister(rs2)); + assert(isGeneralRegisterOrR0(rs1)); + assert(isGeneralRegisterOrR0(rs2)); break; case INS_fsw: FALLTHROUGH; case INS_fsd: - assert(IsFloatRegister(rs1)); - assert(IsIntegralRegister(rs2)); + assert(isFloatReg(rs1)); + assert(isGeneralRegisterOrR0(rs2)); break; default: NO_WAY("Illegal ins within emitOutput_STypeInstr!"); @@ -2536,14 +2527,14 @@ static void STypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumbe } } -static void UTypeInstructionSanityCheck(instruction ins, regNumber rd) +/*static*/ void emitter::emitOutput_UTypeInstr_SanityCheck(instruction ins, regNumber rd) { switch (ins) { case INS_lui: FALLTHROUGH; case INS_auipc: - assert(IsIntegralRegister(rd)); + assert(isGeneralRegisterOrR0(rd)); break; default: NO_WAY("Illegal ins within emitOutput_UTypeInstr!"); @@ -2551,7 +2542,7 @@ static void UTypeInstructionSanityCheck(instruction ins, regNumber rd) } } -static void BTypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumber rs2) +/*static*/ void emitter::emitOutput_BTypeInstr_SanityCheck(instruction ins, regNumber rs1, regNumber rs2) { switch (ins) { @@ -2571,8 +2562,8 @@ static void BTypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumbe case INS_bltu: FALLTHROUGH; case INS_bgeu: - assert(IsIntegralRegister(rs1)); - assert(IsIntegralRegister(rs2)); + assert(isGeneralRegisterOrR0(rs1)); + assert(isGeneralRegisterOrR0(rs2)); break; default: NO_WAY("Illegal ins within emitOutput_BTypeInstr!"); @@ -2580,7 +2571,7 @@ static void BTypeInstructionSanityCheck(instruction ins, regNumber rs1, regNumbe } } -static void JTypeInstructionSanityCheck(instruction ins, regNumber rd) +/*static*/ void emitter::emitOutput_JTypeInstr_SanityCheck(instruction ins, regNumber rd) { switch (ins) { @@ -2588,7 +2579,7 @@ static void JTypeInstructionSanityCheck(instruction ins, regNumber rd) assert(rd == REG_ZERO); break; case INS_jal: - assert(IsIntegralRegister(rd)); + assert(isGeneralRegisterOrR0(rd)); break; default: NO_WAY("Illegal ins within emitOutput_JTypeInstr!"); @@ -2609,7 +2600,7 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd { unsigned insCode = emitInsCode(ins); #ifdef DEBUG - RTypeInstructionSanityCheck(ins, rd, rs1, rs2); + emitOutput_RTypeInstr_SanityCheck(ins, rd, rs1, rs2); #endif // DEBUG unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; @@ -2628,7 +2619,7 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd { unsigned insCode = emitInsCode(ins); #ifdef DEBUG - ITypeInstructionSanityCheck(ins, rd, rs1, imm12, insCode); + emitOutput_ITypeInstr_SanityCheck(ins, rd, rs1, imm12, insCode); #endif // DEBUG unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; @@ -2647,7 +2638,7 @@ unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs { unsigned insCode = emitInsCode(ins); #ifdef DEBUG - STypeInstructionSanityCheck(ins, rs1, rs2); + emitOutput_STypeInstr_SanityCheck(ins, rs1, rs2); #endif // DEBUG unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; @@ -2665,7 +2656,7 @@ unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd { unsigned insCode = emitInsCode(ins); #ifdef DEBUG - UTypeInstructionSanityCheck(ins, rd); + emitOutput_UTypeInstr_SanityCheck(ins, rd); #endif // DEBUG return emitOutput_Instr(dst, insEncodeUTypeInstr(insCode, rd, imm20)); } @@ -2681,7 +2672,7 @@ unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs { unsigned insCode = emitInsCode(ins); #ifdef DEBUG - BTypeInstructionSanityCheck(ins, rs1, rs2); + emitOutput_BTypeInstr_SanityCheck(ins, rs1, rs2); #endif // DEBUG unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; @@ -2705,7 +2696,7 @@ unsigned emitter::emitOutput_BTypeInstr_InvertComparation( { unsigned insCode = emitInsCode(ins) ^ 0x1000; #ifdef DEBUG - BTypeInstructionSanityCheck(ins, rs1, rs2); + emitOutput_BTypeInstr_SanityCheck(ins, rs1, rs2); #endif // DEBUG unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; @@ -2723,7 +2714,7 @@ unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd { unsigned insCode = emitInsCode(ins); #ifdef DEBUG - JTypeInstructionSanityCheck(ins, rd); + emitOutput_JTypeInstr_SanityCheck(ins, rd); #endif // JTypeInstructionSanityCheck return emitOutput_Instr(dst, insEncodeJTypeInstr(insCode, rd, imm21)); } diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index a68a309d963f16..155d8b60fd304c 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -102,6 +102,16 @@ static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, int imm20); static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm13); static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); +#ifdef DEBUG +static void emitOutput_RTypeInstr_SanityCheck(instruction ins, regNumber rd, regNumber rs1, regNumber rs2); +static void emitOutput_ITypeInstr_SanityCheck( + instruction ins, regNumber rd, regNumber rs1, int immediate, unsigned opcode); +static void emitOutput_STypeInstr_SanityCheck(instruction ins, regNumber rs1, regNumber rs2); +static void emitOutput_UTypeInstr_SanityCheck(instruction ins, regNumber rd); +static void emitOutput_BTypeInstr_SanityCheck(instruction ins, regNumber rs1, regNumber rs2); +static void emitOutput_JTypeInstr_SanityCheck(instruction ins, regNumber rd); +#endif // DEBUG + unsigned emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const; unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const; unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const; From eaae5bbb32aaf2f772d71d2c4770c597518e0893 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Tue, 9 Jan 2024 16:42:48 +0100 Subject: [PATCH 085/106] Fixed bug in noreloc --- src/coreclr/jit/emitriscv64.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index f4cfc304897880..6cd99c7e58a528 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2830,8 +2830,8 @@ static ssize_t LowerWordOfDoubleWord(ssize_t immediate) template static ssize_t DoubleWordSignExtend(ssize_t doubleWord) { - static constexpr size_t kLowerSignExtend = 1 << (31 - LowerMaskSize); - static constexpr size_t kUpperSignExtend = static_cast(1) << (31 - UpperMaskSize); + static constexpr size_t kLowerSignExtend = static_cast(1) << (63 - LowerMaskSize); + static constexpr size_t kUpperSignExtend = static_cast(1) << (63 - UpperMaskSize); return doubleWord + (kLowerSignExtend | kUpperSignExtend); } @@ -3018,7 +3018,7 @@ BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumbe assert((immediate >> (32 + 20)) == 0); regNumber rsvdReg = codeGen->rsGetRsvdReg(); - ssize_t upperSignExt = UpperWordOfDoubleWordSignExtend<20, 12>(immediate); + ssize_t upperSignExt = UpperWordOfDoubleWordSignExtend<32, 52>(immediate); dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(immediate)); From 79a5301acf7bb403dc8969bda01c7fd7388b3672 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 10 Jan 2024 09:20:12 +0100 Subject: [PATCH 086/106] Removed dead asserts --- src/coreclr/jit/emitriscv64.cpp | 673 -------------------------------- src/coreclr/jit/emitriscv64.h | 9 - 2 files changed, 682 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 6cd99c7e58a528..74aca2523735d9 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -3163,679 +3163,6 @@ BYTE* emitter::emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* i return dst; } -void emitter::assertOptsReloc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) -{ - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; - size_t clock_of_clocks = 0; - instruction ins; - - regNumber reg1 = id->idReg1(); - - *(code_t*)mock_ptr = 0x00000017 | (code_t)(reg1 << 7); - - mock_ptr += 4; - - if (id->idIsCnsReloc()) - { - ins = INS_addi; - *(code_t*)mock_ptr = 0x00000013 | (code_t)(reg1 << 7) | (code_t)(reg1 << 15); - } - else - { - assert(id->idIsDspReloc()); - ins = INS_ld; - *(code_t*)mock_ptr = 0x00003003 | (code_t)(reg1 << 7) | (code_t)(reg1 << 15); - } - - mock_ptr += 4; - clock_of_clocks += 8; - - assert(clock_of_clocks == buf_size); - assert(ins == cur_ins); - for (size_t i = 0; i < buf_size; ++i) - { - assert((dst + writeableOffset)[i] == mock_dst[i]); - } -} - -void emitter::assertOptsI(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) -{ - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; - instruction ins; - ssize_t imm = (ssize_t)(id->idAddr()->iiaAddr); - regNumber reg1 = id->idReg1(); - code_t code; - - switch (id->idCodeSize()) - { - case 8: - { - if (id->idReg2()) - { // special for INT64_MAX or UINT32_MAX; - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)REG_R0 << 15; - code |= 0xfff << 10; - - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - ssize_t ui6 = (imm == INT64_MAX) ? 1 : 32; - code = emitInsCode(INS_srli); - code |= ((code_t)(reg1 << 7) | ((code_t)(reg1 << 15)) | (ui6 << 20)); - *(code_t*)mock_ptr = code; - } - else - { - code = emitInsCode(INS_lui); - code |= (code_t)(reg1 << 7); - code |= ((code_t)((imm + 0x800) >> 12) & 0xfffff) << 12; - - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)(imm & 0xfff) << 20; - *(code_t*)mock_ptr = code; - } - break; - } - case 32: - { - ssize_t high = (imm >> 32) & 0xffffffff; - code = emitInsCode(INS_lui); - code |= (code_t)reg1 << 7; - code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; - - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)(high & 0xfff) << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - ssize_t low = imm & 0xffffffff; - - code = emitInsCode(INS_slli); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)11 << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)((low >> 21) & 0x7ff) << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)11 << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)((low >> 10) & 0x7ff) << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)10 << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)((low)&0x3ff) << 20; - *(code_t*)mock_ptr = code; - break; - } - default: - unreached(); - break; - } - - ins = INS_addi; - mock_ptr += 4; - - assert((mock_ptr - mock_dst) == buf_size); - assert(cur_ins == ins); - for (size_t i = 0; i < buf_size; ++i) - { - assert((dst + writeableOffset)[i] == mock_dst[i]); - } -} - -void emitter::assertOptsRc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) -{ - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; - instruction ins; - code_t code; - - assert(id->idAddr()->iiaIsJitDataOffset()); - assert(id->idGCref() == GCT_NONE); - - int doff = id->idAddr()->iiaGetJitDataOffset(); - assert(doff >= 0); - - ssize_t imm = emitGetInsSC(id); - assert((imm >= 0) && (imm < 0x4000)); // 0x4000 is arbitrary, currently 'imm' is always 0. - - unsigned dataOffs = (unsigned)(doff + imm); - - assert(dataOffs < emitDataSize()); - - ins = id->idIns(); - regNumber reg1 = id->idReg1(); - - if (id->idIsReloc()) - { - // get the addr-offset of the data. - imm = (ssize_t)emitConsBlock - (ssize_t)(dst) + dataOffs; - assert(imm > 0); - assert(!(imm & 3)); - - doff = (int)(imm & 0xfff); - assert(isValidSimm20((imm + 0x800) >> 12)); - -#ifdef DEBUG - code = emitInsCode(INS_auipc); - assert(code == 0x00000017); -#endif - code = 0x00000017 | (codeGen->rsGetRsvdReg() << 7); - *(code_t*)mock_ptr = code | ((code_t)((imm + 0x800) & 0xfffff000)); - mock_ptr += 4; - - if (ins == INS_jal) - { - assert(isGeneralRegister(reg1)); - ins = INS_addi; -#ifdef DEBUG - code = emitInsCode(INS_addi); - assert(code == 0x00000013); -#endif - code = 0x00000013 | (codeGen->rsGetRsvdReg() << 15); - *(code_t*)mock_ptr = code | ((code_t)reg1 << 7) | (((code_t)doff & 0xfff) << 20); - } - else - { - code = emitInsCode(ins); - code |= (code_t)(reg1 & 0x1f) << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)(doff & 0xfff) << 20; - *(code_t*)mock_ptr = code; - } - mock_ptr += 4; - } - else - { - // get the addr of the data. - imm = (ssize_t)emitConsBlock + dataOffs; - - code = emitInsCode(INS_lui); - if (ins == INS_jal) - { - assert((imm >> 40) == 0); - - doff = imm & 0x7ff; - - UINT32 high = imm >> 11; - - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)(((high + 0x800) >> 12) << 12); - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)(high & 0xFFF) << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)11 << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - ins = INS_addi; - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)doff << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - } - else - { - assert((imm >> 40) == 0); - - doff = imm & 0x7ff; - UINT32 high = imm >> 11; - - code |= (code_t)(codeGen->rsGetRsvdReg() << 7); - code |= (code_t)(((high + 0x800) >> 12) << 12); - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)(high & 0xFFF) << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)11 << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(ins); - code |= (code_t)(reg1 & 0x1f) << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)doff << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - } - } - - assert((mock_ptr - mock_dst) == buf_size); - assert(cur_ins == ins); - for (size_t i = 0; i < buf_size; ++i) - { - assert((dst + writeableOffset)[i] == mock_dst[i]); - } -} - -void emitter::assertOptsRl(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins) -{ - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; - instruction ins; - code_t code; - - insGroup* tgtIG = (insGroup*)id->idAddr()->iiaIGlabel; - - regNumber reg1 = id->idReg1(); - assert(isGeneralRegister(reg1)); - - if (id->idIsReloc()) - { - ssize_t imm = (ssize_t)tgtIG->igOffs; - imm = (ssize_t)emitCodeBlock + imm - (ssize_t)(dst); - assert((imm & 3) == 0); - - int doff = (int)(imm & 0xfff); - assert(isValidSimm20((imm + 0x800) >> 12)); - - code = 0x00000017; - *(code_t*)mock_ptr = code | (code_t)reg1 << 7 | ((imm + 0x800) & 0xfffff000); - mock_ptr += 4; -#ifdef DEBUG - code = emitInsCode(INS_auipc); - assert(code == 0x00000017); - code = emitInsCode(INS_addi); - assert(code == 0x00000013); -#endif - ins = INS_addi; - *(code_t*)mock_ptr = 0x00000013 | ((code_t)reg1 << 7) | ((code_t)reg1 << 15) | ((doff & 0xfff) << 20); - } - else - { - ssize_t imm = (ssize_t)tgtIG->igOffs + (ssize_t)emitCodeBlock; - assert((imm >> (32 + 20)) == 0); - - code = emitInsCode(INS_lui); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= ((code_t)((imm + 0x800) >> 12) & 0xfffff) << 12; - - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= (code_t)(imm & 0xfff) << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)reg1 << 7; - code |= (((imm + 0x80000800) >> 32) & 0xfff) << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)32 << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - ins = INS_add; - code = emitInsCode(INS_add); - code |= (code_t)reg1 << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)codeGen->rsGetRsvdReg() << 20; - *(code_t*)mock_ptr = code; - } - - mock_ptr += 4; - - assert((mock_ptr - mock_dst) == buf_size); - assert(cur_ins == ins); - - for (size_t i = 0; i < buf_size; ++i) - { - assert((dst + writeableOffset)[i] == mock_dst[i]); - } -} - -void emitter::assertOptsJarl( - BYTE* dst, size_t buf_size, instrDescJmp* jmp, const insGroup* ig, const instrDesc* id, instruction cur_ins) -{ - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; - instruction ins; - code_t code; - - regNumber reg1 = id->idReg1(); - { - ssize_t imm = emitOutputInstrJumpDistance(dst, ig, jmp); - imm -= 4; - - assert((imm & 0x3) == 0); - - ins = jmp->idIns(); - assert(jmp->idCodeSize() > 4); // The original INS_OPTS_JALR: not used by now!!! - switch (jmp->idCodeSize()) - { - case 8: - { - 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*)mock_ptr = code; - mock_ptr += 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*)mock_ptr = code; - mock_ptr += 4; - break; - } - 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; - code = emitInsCode(INS_lui); - code |= (code_t)tmpReg1 << 7; - code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; - - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)tmpReg1 << 7; - code |= (code_t)tmpReg1 << 15; - code |= (code_t)(high & 0xfff) << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)tmpReg1 << 7; - code |= (code_t)tmpReg1 << 15; - code |= (code_t)32 << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 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*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_add); - code |= (code_t)tmpReg2 << 7; - code |= (code_t)tmpReg1 << 15; - code |= (code_t)tmpReg2 << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 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*)mock_ptr = code; - mock_ptr += 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*)mock_ptr = code; - mock_ptr += 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; - code = emitInsCode(INS_lui); - code |= (code_t)tmpReg1 << 7; - code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; - - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_addi); - code |= (code_t)tmpReg1 << 7; - code |= (code_t)tmpReg1 << 15; - code |= (code_t)(high & 0xfff) << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_slli); - code |= (code_t)tmpReg1 << 7; - code |= (code_t)tmpReg1 << 15; - code |= (code_t)32 << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 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*)mock_ptr = code; - mock_ptr += 4; - - code = emitInsCode(INS_add); - code |= (code_t)tmpReg2 << 7; - code |= (code_t)tmpReg1 << 15; - code |= (code_t)tmpReg2 << 20; - *(code_t*)mock_ptr = code; - mock_ptr += 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*)mock_ptr = code; - mock_ptr += 4; - - break; - } - - default: - unreached(); - break; - } - } - - assert((mock_ptr - mock_dst) == buf_size); - assert(cur_ins == ins); - - for (size_t i = 0; i < buf_size; ++i) - { - assert((dst + writeableOffset)[i] == mock_dst[i]); - } -} - -void emitter::assertOptsJCond(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins) -{ - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; - instruction ins; - code_t code; - - ssize_t imm = emitOutputInstrJumpDistance(dst, ig, static_cast(id)); - assert(isValidSimm13(imm)); - assert(!(imm & 1)); - - ins = id->idIns(); - code = emitInsCode(ins); - code |= ((code_t)id->idReg1()) << 15; - code |= ((code_t)id->idReg2()) << 20; - code |= ((imm >> 11) & 0x1) << 7; - code |= ((imm >> 1) & 0xf) << 8; - code |= ((imm >> 5) & 0x3f) << 25; - code |= ((imm >> 12) & 0x1) << 31; - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - assert(cur_ins == ins); - - for (size_t i = 0; i < buf_size; ++i) - { - assert((dst + writeableOffset)[i] == mock_dst[i]); - } -} - -void emitter::assertOptsJ(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins) -{ - BYTE mock_dst[1024]; - BYTE* mock_ptr = mock_dst; - instruction ins; - code_t code; - - ssize_t imm = emitOutputInstrJumpDistance(dst, ig, static_cast(id)); - assert((imm & 3) == 0); - - ins = id->idIns(); - 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; - code |= ((imm >> 20) & 0x1) << 31; - code |= REG_RA << 7; - } - else if (ins == INS_j) - { - assert(isValidSimm21(imm)); - code |= ((imm >> 12) & 0xff) << 12; - code |= ((imm >> 11) & 0x1) << 20; - code |= ((imm >> 1) & 0x3ff) << 21; - code |= ((imm >> 20) & 0x1) << 31; - } - else if (ins == INS_jalr) - { - 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) - { - assert(isValidSimm13(imm)); - code |= (code_t)id->idReg1() << 15; - code |= ((imm >> 11) & 0x1) << 7; - code |= ((imm >> 1) & 0xf) << 8; - code |= ((imm >> 5) & 0x3f) << 25; - code |= ((imm >> 12) & 0x1) << 31; - } - 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; - code |= ((imm >> 1) & 0xf) << 8; - code |= ((imm >> 5) & 0x3f) << 25; - code |= ((imm >> 12) & 0x1) << 31; - } - else - { - unreached(); - } - - *(code_t*)mock_ptr = code; - mock_ptr += 4; - - assert(cur_ins == ins); - - for (size_t i = 0; i < buf_size; ++i) - { - assert((dst + writeableOffset)[i] == mock_dst[i]); - } -} - /***************************************************************************** * * Append the machine code corresponding to the given instruction descriptor diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 155d8b60fd304c..1772603fd5c4b1 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -139,15 +139,6 @@ BYTE* emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, in BYTE* emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins); BYTE* emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* ig, size_t* size); -void assertOptsReloc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); -void assertOptsI(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); -void assertOptsRc(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); -void assertOptsRl(BYTE* dst, size_t buf_size, const instrDesc* id, instruction cur_ins); -void assertOptsJarl( - BYTE* dst, size_t buf_size, instrDescJmp* jmp, const insGroup* ig, const instrDesc* id, instruction cur_ins); -void assertOptsJCond(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins); -void assertOptsJ(BYTE* dst, size_t buf_size, const insGroup* ig, instrDesc* id, instruction cur_ins); - /************************************************************************/ /* Public inline informational methods */ /************************************************************************/ From b776df56bc3ac161faf5f1bbf27df27457c7f534 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 10 Jan 2024 09:22:42 +0100 Subject: [PATCH 087/106] Removed now unused asserts --- src/coreclr/jit/emitriscv64.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 74aca2523735d9..61bcf6b65f1278 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -3187,40 +3187,33 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { case INS_OPTS_RELOC: dst = emitOutputInstr_OptsReloc(dst, id, &ins); - assertOptsReloc(*dp, dst - *dp, id, ins); sz = sizeof(instrDesc); break; case INS_OPTS_I: dst = emitOutputInstr_OptsI(dst, id); ins = INS_addi; sz = sizeof(instrDesc); - assertOptsI(*dp, dst - *dp, id, ins); break; case INS_OPTS_RC: dst = emitOutputInstr_OptsRc(dst, id, &ins); sz = sizeof(instrDesc); - assertOptsRc(*dp, dst - *dp, id, ins); break; case INS_OPTS_RL: dst = emitOutputInstr_OptsRl(dst, id, &ins); - assertOptsRl(*dp, dst - *dp, id, ins); sz = sizeof(instrDesc); break; case INS_OPTS_JALR: dst = emitOutputInstr_OptsJalr(dst, static_cast(id), ig, &ins); sz = sizeof(instrDescJmp); - assertOptsJarl(*dp, dst - *dp, static_cast(id), ig, id, ins); break; case INS_OPTS_J_cond: dst = emitOutputInstr_OptsJCond(dst, id, ig, &ins); sz = sizeof(instrDescJmp); - assertOptsJCond(*dp, dst - *dp, ig, id, ins); break; case INS_OPTS_J: // jal/j/jalr/bnez/beqz/beq/bne/blt/bge/bltu/bgeu dstRW-relative. dst = emitOutputInstr_OptsJ(dst, id, ig, &ins); sz = sizeof(instrDescJmp); - assertOptsJ(*dp, dst - *dp, ig, id, ins); break; case INS_OPTS_C: dst = emitOutputInstr_OptsC(dst, id, ig, &sz); From 44eb85d1a890738d525affcef397eb95b1debe7c Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 10 Jan 2024 10:36:14 +0100 Subject: [PATCH 088/106] Fixed format --- 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 61bcf6b65f1278..57fe7ac5c180f9 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -3187,7 +3187,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { case INS_OPTS_RELOC: dst = emitOutputInstr_OptsReloc(dst, id, &ins); - sz = sizeof(instrDesc); + sz = sizeof(instrDesc); break; case INS_OPTS_I: dst = emitOutputInstr_OptsI(dst, id); @@ -3200,7 +3200,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) break; case INS_OPTS_RL: dst = emitOutputInstr_OptsRl(dst, id, &ins); - sz = sizeof(instrDesc); + sz = sizeof(instrDesc); break; case INS_OPTS_JALR: dst = emitOutputInstr_OptsJalr(dst, static_cast(id), ig, &ins); From d1dfaf1fe6b1df76bac4f615cb661be03cb35e2b Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 10 Jan 2024 11:25:29 +0100 Subject: [PATCH 089/106] Fixed missing const --- src/coreclr/jit/emit.cpp | 4 ++-- src/coreclr/jit/emit.h | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index c9e36ae47a50da..ad070844c50e95 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -707,7 +707,7 @@ void emitLclVarAddr::initLclVarAddr(int varNum, unsigned offset) } // Returns the variable to access. Note that it returns a negative number for compiler spill temps. -int emitLclVarAddr::lvaVarNum() +int emitLclVarAddr::lvaVarNum() const { switch (_lvaTag) { @@ -721,7 +721,7 @@ int emitLclVarAddr::lvaVarNum() } } -unsigned emitLclVarAddr::lvaOffset() // returns the offset into the variable to access +unsigned emitLclVarAddr::lvaOffset() const // returns the offset into the variable to access { switch (_lvaTag) { diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 4427d4a1f7b7e0..77d06aa07edbce 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -418,8 +418,9 @@ struct emitLclVarAddr // Constructor void initLclVarAddr(int varNum, unsigned offset); - int lvaVarNum(); // Returns the variable to access. Note that it returns a negative number for compiler spill temps. - unsigned lvaOffset(); // returns the offset into the variable to access + int lvaVarNum() const; // Returns the variable to access. Note that it returns a negative number for compiler spill + // temps. + unsigned lvaOffset() const; // returns the offset into the variable to access // This struct should be 32 bits in size for the release build. // We have this constraint because this type is used in a union From 150eb421bd0a3635a8378aa885f5d124d8cc000b Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 10 Jan 2024 13:18:36 +0100 Subject: [PATCH 090/106] Removed useless ifdef --- src/coreclr/jit/emitriscv64.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 57fe7ac5c180f9..657a76974d4244 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2124,9 +2124,7 @@ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code) const static void assertCodeLength(unsigned code, uint8_t size) { -#ifdef DEBUG assert((code >> size) == 0); -#endif // DEBUG } /***************************************************************************** From d4c77ad88ad1e5700e86df8b5317a8fbdda4621b Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 10 Jan 2024 13:20:57 +0100 Subject: [PATCH 091/106] Fixed missing asserts --- src/coreclr/jit/emitriscv64.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 657a76974d4244..96a681c7811e5b 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2169,7 +2169,7 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(rd, 5); assertCodeLength(funct3, 3); assertCodeLength(rs1, 5); - isValidSimm12(imm12); + assert(isValidSimm12(imm12)); return opcode | (rd << 7) | (funct3 << 12) | (rs1 << 15) | (imm12 << 20); } @@ -2195,7 +2195,7 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(funct3, 3); assertCodeLength(rs1, 5); assertCodeLength(rs2, 5); - isValidSimm12(imm12); + assert(isValidSimm12(imm12)); unsigned imm12Lo = imm12 & kLoMask; unsigned imm12Hi = (imm12 >> 5) & kHiMask; @@ -2218,7 +2218,7 @@ static void assertCodeLength(unsigned code, uint8_t size) { assertCodeLength(opcode, 7); assertCodeLength(rd, 5); - isValidSimm20(imm20); + assert(isValidSimm20(imm20)); return opcode | (rd << 7) | (imm20 << 12); } @@ -2245,7 +2245,7 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(funct3, 3); assertCodeLength(rs1, 5); assertCodeLength(rs2, 5); - isValidSimm13(imm13); + assert(isValidSimm13(imm13)); unsigned imm12 = imm13 >> 1; unsigned imm12LoSection = imm12 & kLoSectionMask; @@ -2276,7 +2276,7 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(opcode, 7); assertCodeLength(rd, 5); - isValidSimm21(imm21); + assert(isValidSimm21(imm21)); unsigned imm20 = imm21 >> 1; unsigned imm20HiSection = imm20 & kHiSectionMask; @@ -2490,7 +2490,7 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; case INS_csrrsi: FALLTHROUGH; case INS_csrrci: - isGeneralRegisterOrR0(rd); + assert(isGeneralRegisterOrR0(rd)); assert(rs1 < 32); break; default: From ef18dea16e2c48bcc3672d1ccaa1921b21398441 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 10 Jan 2024 14:15:48 +0100 Subject: [PATCH 092/106] Added a new assert --- src/coreclr/jit/emitriscv64.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 96a681c7811e5b..4d3246f29183d4 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2492,6 +2492,7 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; case INS_csrrci: assert(isGeneralRegisterOrR0(rd)); assert(rs1 < 32); + assert((opcode & kInstructionFunct7Mask) == 0); break; default: NO_WAY("Illegal ins within emitOutput_ITypeInstr!"); From aae544b7e872d4ba27aadb77acbbc7b54c988ccf Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 10 Jan 2024 14:29:36 +0100 Subject: [PATCH 093/106] Added zero assert --- src/coreclr/jit/emitriscv64.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 4d3246f29183d4..68ab479bfb6a51 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2277,6 +2277,7 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(opcode, 7); assertCodeLength(rd, 5); assert(isValidSimm21(imm21)); + assert((imm21 & 0x01) == 0); unsigned imm20 = imm21 >> 1; unsigned imm20HiSection = imm20 & kHiSectionMask; From 8583d5212d2713f62b11eafc031954ad3e256e5f Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 10 Jan 2024 14:34:08 +0100 Subject: [PATCH 094/106] Removed useless FALLTHROUGH statements --- src/coreclr/jit/emitriscv64.cpp | 92 --------------------------------- 1 file changed, 92 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 68ab479bfb6a51..49c24c9f5e12fa 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2300,110 +2300,60 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; switch (ins) { case INS_add: - FALLTHROUGH; case INS_sub: - FALLTHROUGH; case INS_sll: - FALLTHROUGH; case INS_slt: - FALLTHROUGH; case INS_sltu: - FALLTHROUGH; case INS_xor: - FALLTHROUGH; case INS_srl: - FALLTHROUGH; case INS_sra: - FALLTHROUGH; case INS_or: - FALLTHROUGH; case INS_and: - FALLTHROUGH; case INS_addw: - FALLTHROUGH; case INS_subw: - FALLTHROUGH; case INS_sllw: - FALLTHROUGH; case INS_srlw: - FALLTHROUGH; case INS_sraw: - FALLTHROUGH; case INS_mul: - FALLTHROUGH; case INS_mulh: - FALLTHROUGH; case INS_mulhsu: - FALLTHROUGH; case INS_mulhu: - FALLTHROUGH; case INS_div: - FALLTHROUGH; case INS_divu: - FALLTHROUGH; case INS_rem: - FALLTHROUGH; case INS_remu: - FALLTHROUGH; case INS_mulw: - FALLTHROUGH; case INS_divw: - FALLTHROUGH; case INS_divuw: - FALLTHROUGH; case INS_remw: - FALLTHROUGH; case INS_remuw: assert(isGeneralRegisterOrR0(rd)); assert(isGeneralRegisterOrR0(rs1)); assert(isGeneralRegisterOrR0(rs2)); break; case INS_fadd_s: - FALLTHROUGH; case INS_fsub_s: - FALLTHROUGH; case INS_fmul_s: - FALLTHROUGH; case INS_fdiv_s: - FALLTHROUGH; case INS_fsgnj_s: - FALLTHROUGH; case INS_fsgnjn_s: - FALLTHROUGH; case INS_fsgnjx_s: - FALLTHROUGH; case INS_fmin_s: - FALLTHROUGH; case INS_fmax_s: - FALLTHROUGH; case INS_feq_s: - FALLTHROUGH; case INS_flt_s: - FALLTHROUGH; case INS_fle_s: - FALLTHROUGH; case INS_fadd_d: - FALLTHROUGH; case INS_fsub_d: - FALLTHROUGH; case INS_fmul_d: - FALLTHROUGH; case INS_fdiv_d: - FALLTHROUGH; case INS_fsgnj_d: - FALLTHROUGH; case INS_fsgnjn_d: - FALLTHROUGH; case INS_fsgnjx_d: - FALLTHROUGH; case INS_fmin_d: - FALLTHROUGH; case INS_fmax_d: - FALLTHROUGH; case INS_feq_d: - FALLTHROUGH; case INS_flt_d: - FALLTHROUGH; case INS_fle_d: assert(isFloatReg(rd)); assert(isFloatReg(rs1)); @@ -2421,75 +2371,50 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; switch (ins) { case INS_jalr: - FALLTHROUGH; case INS_lb: - FALLTHROUGH; case INS_lh: - FALLTHROUGH; case INS_lw: - FALLTHROUGH; case INS_lbu: - FALLTHROUGH; case INS_lhu: - FALLTHROUGH; case INS_addi: - FALLTHROUGH; case INS_slti: - FALLTHROUGH; case INS_sltiu: - FALLTHROUGH; case INS_xori: - FALLTHROUGH; case INS_ori: - FALLTHROUGH; case INS_andi: - FALLTHROUGH; case INS_lwu: - FALLTHROUGH; case INS_ld: - FALLTHROUGH; case INS_addiw: - FALLTHROUGH; case INS_fence_i: - FALLTHROUGH; case INS_csrrw: - FALLTHROUGH; case INS_csrrs: - FALLTHROUGH; case INS_csrrc: assert(isGeneralRegisterOrR0(rd)); assert(isGeneralRegisterOrR0(rs1)); assert((opcode & kInstructionFunct7Mask) == 0); break; case INS_flw: - FALLTHROUGH; case INS_fld: assert(isFloatReg(rd)); assert(isGeneralRegisterOrR0(rs1)); assert((opcode & kInstructionFunct7Mask) == 0); break; case INS_slli: - FALLTHROUGH; case INS_srli: - FALLTHROUGH; case INS_srai: assert(0 <= immediate < 64); assert(isGeneralRegisterOrR0(rd)); assert(isGeneralRegisterOrR0(rs1)); break; case INS_slliw: - FALLTHROUGH; case INS_srliw: - FALLTHROUGH; case INS_sraiw: assert(0 <= immediate < 32); assert(isGeneralRegisterOrR0(rd)); assert(isGeneralRegisterOrR0(rs1)); break; case INS_csrrwi: - FALLTHROUGH; case INS_csrrsi: - FALLTHROUGH; case INS_csrrci: assert(isGeneralRegisterOrR0(rd)); assert(rs1 < 32); @@ -2506,17 +2431,13 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; switch (ins) { case INS_sb: - FALLTHROUGH; case INS_sh: - FALLTHROUGH; case INS_sw: - FALLTHROUGH; case INS_sd: assert(isGeneralRegisterOrR0(rs1)); assert(isGeneralRegisterOrR0(rs2)); break; case INS_fsw: - FALLTHROUGH; case INS_fsd: assert(isFloatReg(rs1)); assert(isGeneralRegisterOrR0(rs2)); @@ -2532,7 +2453,6 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; switch (ins) { case INS_lui: - FALLTHROUGH; case INS_auipc: assert(isGeneralRegisterOrR0(rd)); break; @@ -2547,20 +2467,14 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; switch (ins) { case INS_beqz: - FALLTHROUGH; case INS_bnez: assert((rs1 == REG_ZERO) || (rs2 == REG_ZERO)); FALLTHROUGH; case INS_beq: - FALLTHROUGH; case INS_bne: - FALLTHROUGH; case INS_blt: - FALLTHROUGH; case INS_bge: - FALLTHROUGH; case INS_bltu: - FALLTHROUGH; case INS_bgeu: assert(isGeneralRegisterOrR0(rs1)); assert(isGeneralRegisterOrR0(rs2)); @@ -3124,20 +3038,14 @@ BYTE* emitter::emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* i dst += emitOutput_ITypeInstr(dst, INS_jalr, id->idReg1(), id->idReg2(), immediate); break; case INS_bnez: - FALLTHROUGH; case INS_beqz: dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), REG_ZERO, immediate); break; case INS_beq: - FALLTHROUGH; case INS_bne: - FALLTHROUGH; case INS_blt: - FALLTHROUGH; case INS_bge: - FALLTHROUGH; case INS_bltu: - FALLTHROUGH; case INS_bgeu: dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), id->idReg2(), immediate); break; From 9cd98ab266b3bbc06986384492b16a5f0ffff4bf Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Wed, 10 Jan 2024 15:23:41 +0100 Subject: [PATCH 095/106] Added trimmers --- src/coreclr/jit/emitriscv64.cpp | 28 ++++++++++++++++++++++++++++ src/coreclr/jit/emitriscv64.h | 5 +++++ 2 files changed, 33 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 49c24c9f5e12fa..761ca8bc94c83a 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2764,6 +2764,34 @@ static ssize_t UpperWordOfDoubleWordSignExtend(ssize_t doubleWord) return UpperWordOfDoubleWord(DoubleWordSignExtend(doubleWord)); } +/*static*/ unsigned emitter::TrimSignedToImm12(int imm12) +{ + assert(isValidSimm12(imm12)); + + return static_cast(LowerNBitsOfWord<12>(imm12)); +} + +/*static*/ unsigned emitter::TrimSignedToImm13(int imm13) +{ + assert(isValidSimm13(imm13)); + + return static_cast(LowerNBitsOfWord<13>(imm13)); +} + +/*static*/ unsigned emitter::TrimSignedToImm20(int imm20) +{ + assert(isValidSimm20(imm20)); + + return static_cast(LowerNBitsOfWord<20>(imm20)); +} + +/*static*/ unsigned emitter::TrimSignedToImm21(int imm21) +{ + assert(isValidSimm21(imm21)); + + return static_cast(LowerNBitsOfWord<21>(imm21)); +} + BYTE* emitter::emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins) { BYTE* const dstBase = dst; diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 1772603fd5c4b1..6f1febcf1f3980 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -139,6 +139,11 @@ BYTE* emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, in BYTE* emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins); BYTE* emitOutputInstr_OptsC(BYTE* dst, instrDesc* id, const insGroup* ig, size_t* size); +static unsigned TrimSignedToImm12(int imm12); +static unsigned TrimSignedToImm13(int imm13); +static unsigned TrimSignedToImm20(int imm20); +static unsigned TrimSignedToImm21(int imm21); + /************************************************************************/ /* Public inline informational methods */ /************************************************************************/ From 4c72aa12be528e6723cea4b7c69bade6c50902e2 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 12 Jan 2024 09:55:38 +0100 Subject: [PATCH 096/106] Added explicit signed integers trimming --- src/coreclr/jit/emitriscv64.cpp | 65 +++++++++++++++++---------------- src/coreclr/jit/emitriscv64.h | 14 +++---- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 761ca8bc94c83a..f637691f324358 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2163,13 +2163,14 @@ static void assertCodeLength(unsigned code, uint8_t size) */ /*static*/ emitter::code_t emitter::insEncodeITypeInstr( - unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, int imm12) + unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned imm12) { assertCodeLength(opcode, 7); assertCodeLength(rd, 5); assertCodeLength(funct3, 3); assertCodeLength(rs1, 5); - assert(isValidSimm12(imm12)); + // This assert may be triggered by the untrimmed signed integers. Please refer to the TrimSigned helpers + assertCodeLength(imm12, 12); return opcode | (rd << 7) | (funct3 << 12) | (rs1 << 15) | (imm12 << 20); } @@ -2186,7 +2187,7 @@ static void assertCodeLength(unsigned code, uint8_t size) */ /*static*/ emitter::code_t emitter::insEncodeSTypeInstr( - unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm12) + unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12) { static constexpr unsigned kLoMask = 0x1f; // 0b00011111 static constexpr unsigned kHiMask = 0x7f; // 0b01111111 @@ -2195,7 +2196,8 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(funct3, 3); assertCodeLength(rs1, 5); assertCodeLength(rs2, 5); - assert(isValidSimm12(imm12)); + // This assert may be triggered by the untrimmed signed integers. Please refer to the TrimSigned helpers + assertCodeLength(imm12, 12); unsigned imm12Lo = imm12 & kLoMask; unsigned imm12Hi = (imm12 >> 5) & kHiMask; @@ -2214,11 +2216,12 @@ static void assertCodeLength(unsigned code, uint8_t size) * ------------------------------------------------------------------- */ -/*static*/ emitter::code_t emitter::insEncodeUTypeInstr(unsigned opcode, unsigned rd, int imm20) +/*static*/ emitter::code_t emitter::insEncodeUTypeInstr(unsigned opcode, unsigned rd, unsigned imm20) { assertCodeLength(opcode, 7); assertCodeLength(rd, 5); - assert(isValidSimm20(imm20)); + // This assert may be triggered by the untrimmed signed integers. Please refer to the TrimSigned helpers + assertCodeLength(imm20, 20); return opcode | (rd << 7) | (imm20 << 12); } @@ -2235,7 +2238,7 @@ static void assertCodeLength(unsigned code, uint8_t size) */ /*static*/ emitter::code_t emitter::insEncodeBTypeInstr( - unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm13) + unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm13) { static constexpr unsigned kLoSectionMask = 0x0f; // 0b00001111 static constexpr unsigned kHiSectionMask = 0x3f; // 0b00111111 @@ -2245,7 +2248,9 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(funct3, 3); assertCodeLength(rs1, 5); assertCodeLength(rs2, 5); - assert(isValidSimm13(imm13)); + // This assert may be triggered by the untrimmed signed integers. Please refer to the TrimSigned helpers + assertCodeLength(imm13, 13); + assert((imm13 & 0x01) == 0); unsigned imm12 = imm13 >> 1; unsigned imm12LoSection = imm12 & kLoSectionMask; @@ -2268,7 +2273,7 @@ static void assertCodeLength(unsigned code, uint8_t size) * ------------------------------------------------------------------- */ -/*static*/ emitter::code_t emitter::insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21) +/*static*/ emitter::code_t emitter::insEncodeJTypeInstr(unsigned opcode, unsigned rd, unsigned imm21) { static constexpr unsigned kHiSectionMask = 0x3ff; // 0b1111111111 static constexpr unsigned kLoSectionMask = 0xff; // 0b11111111 @@ -2276,7 +2281,8 @@ static void assertCodeLength(unsigned code, uint8_t size) assertCodeLength(opcode, 7); assertCodeLength(rd, 5); - assert(isValidSimm21(imm21)); + // This assert may be triggered by the untrimmed signed integers. Please refer to the TrimSigned helpers + assertCodeLength(imm21, 21); assert((imm21 & 0x01) == 0); unsigned imm20 = imm21 >> 1; @@ -2366,7 +2372,7 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; } /*static*/ void emitter::emitOutput_ITypeInstr_SanityCheck( - instruction ins, regNumber rd, regNumber rs1, int immediate, unsigned opcode) + instruction ins, regNumber rd, regNumber rs1, unsigned immediate, unsigned opcode) { switch (ins) { @@ -2402,14 +2408,14 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; case INS_slli: case INS_srli: case INS_srai: - assert(0 <= immediate < 64); + assert(immediate < 64); assert(isGeneralRegisterOrR0(rd)); assert(isGeneralRegisterOrR0(rs1)); break; case INS_slliw: case INS_srliw: case INS_sraiw: - assert(0 <= immediate < 32); + assert(immediate < 32); assert(isGeneralRegisterOrR0(rd)); assert(isGeneralRegisterOrR0(rs1)); break; @@ -2529,7 +2535,7 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd * */ -unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const +unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, unsigned imm12) const { unsigned insCode = emitInsCode(ins); #ifdef DEBUG @@ -2548,7 +2554,7 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd * */ -unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const +unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, unsigned imm12) const { unsigned insCode = emitInsCode(ins); #ifdef DEBUG @@ -2566,7 +2572,7 @@ unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs * */ -unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm20) const +unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, unsigned imm20) const { unsigned insCode = emitInsCode(ins); #ifdef DEBUG @@ -2582,7 +2588,7 @@ unsigned emitter::emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd * */ -unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const +unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, unsigned imm13) const { unsigned insCode = emitInsCode(ins); #ifdef DEBUG @@ -2606,7 +2612,7 @@ unsigned emitter::emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs */ unsigned emitter::emitOutput_BTypeInstr_InvertComparation( - BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const + BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, unsigned imm13) const { unsigned insCode = emitInsCode(ins) ^ 0x1000; #ifdef DEBUG @@ -2624,7 +2630,7 @@ unsigned emitter::emitOutput_BTypeInstr_InvertComparation( * */ -unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm21) const +unsigned emitter::emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd, unsigned imm21) const { unsigned insCode = emitInsCode(ins); #ifdef DEBUG @@ -2840,7 +2846,7 @@ BYTE* emitter::emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t im { // special for INT64_MAX or UINT32_MAX dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, REG_R0, 0xfff); - ssize_t shiftValue = (immediate == INT64_MAX) ? 1 : 32; + const ssize_t shiftValue = (immediate == INT64_MAX) ? 1 : 32; dst += emitOutput_ITypeInstr(dst, INS_srli, reg1, reg1, shiftValue); } else @@ -3001,7 +3007,7 @@ BYTE* emitter::emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, ins regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? jmp->idReg2() : REG_R0; dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, jmp->idReg1(), reg2, 0x8); - dst += emitOutput_JTypeInstr(dst, INS_jal, REG_ZERO, immediate); + dst += emitOutput_JTypeInstr(dst, INS_jal, REG_ZERO, TrimSignedToImm21(immediate)); return dst; } @@ -3027,9 +3033,6 @@ BYTE* emitter::emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate) BYTE* emitter::emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate) { - assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || (INS_bnez == ins) || - (INS_beqz == ins)); - regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? jmp->idReg2() : REG_R0; dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, jmp->idReg1(), reg2, 0x1c); @@ -3039,11 +3042,10 @@ BYTE* emitter::emitOutputInstr_OptsJalr28(BYTE* dst, const instrDescJmp* jmp, in BYTE* emitter::emitOutputInstr_OptsJCond(BYTE* dst, instrDesc* id, const insGroup* ig, instruction* ins) { ssize_t immediate = emitOutputInstrJumpDistance(dst, ig, static_cast(id)); - assert((immediate & 0x01) == 0); *ins = id->idIns(); - dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), id->idReg2(), immediate); + dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), id->idReg2(), TrimSignedToImm13(immediate)); return dst; } @@ -3057,17 +3059,17 @@ BYTE* emitter::emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* i switch (*ins) { case INS_jal: - dst += emitOutput_JTypeInstr(dst, INS_jal, REG_RA, immediate); + dst += emitOutput_JTypeInstr(dst, INS_jal, REG_RA, TrimSignedToImm21(immediate)); break; case INS_j: - dst += emitOutput_JTypeInstr(dst, INS_j, REG_ZERO, immediate); + dst += emitOutput_JTypeInstr(dst, INS_j, REG_ZERO, TrimSignedToImm21(immediate)); break; case INS_jalr: - dst += emitOutput_ITypeInstr(dst, INS_jalr, id->idReg1(), id->idReg2(), immediate); + dst += emitOutput_ITypeInstr(dst, INS_jalr, id->idReg1(), id->idReg2(), TrimSignedToImm12(immediate)); break; case INS_bnez: case INS_beqz: - dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), REG_ZERO, immediate); + dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), REG_ZERO, TrimSignedToImm13(immediate)); break; case INS_beq: case INS_bne: @@ -3075,10 +3077,11 @@ BYTE* emitter::emitOutputInstr_OptsJ(BYTE* dst, instrDesc* id, const insGroup* i case INS_bge: case INS_bltu: case INS_bgeu: - dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), id->idReg2(), immediate); + dst += emitOutput_BTypeInstr(dst, *ins, id->idReg1(), id->idReg2(), TrimSignedToImm13(immediate)); break; default: unreached(); + break; } return dst; } diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 6f1febcf1f3980..a18b9fc96d8e5a 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -105,7 +105,7 @@ static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); #ifdef DEBUG static void emitOutput_RTypeInstr_SanityCheck(instruction ins, regNumber rd, regNumber rs1, regNumber rs2); static void emitOutput_ITypeInstr_SanityCheck( - instruction ins, regNumber rd, regNumber rs1, int immediate, unsigned opcode); + instruction ins, regNumber rd, regNumber rs1, unsigned immediate, unsigned opcode); static void emitOutput_STypeInstr_SanityCheck(instruction ins, regNumber rs1, regNumber rs2); static void emitOutput_UTypeInstr_SanityCheck(instruction ins, regNumber rd); static void emitOutput_BTypeInstr_SanityCheck(instruction ins, regNumber rs1, regNumber rs2); @@ -113,13 +113,13 @@ static void emitOutput_JTypeInstr_SanityCheck(instruction ins, regNumber rd); #endif // DEBUG unsigned emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const; -unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, int imm12) const; -unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm12) const; -unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm20) const; -unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const; +unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, unsigned imm12) const; +unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, unsigned imm12) const; +unsigned emitOutput_UTypeInstr(BYTE* dst, instruction ins, regNumber rd, unsigned imm20) const; +unsigned emitOutput_BTypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, unsigned imm13) const; unsigned emitOutput_BTypeInstr_InvertComparation( - BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, int imm13) const; -unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd, int imm21) const; + BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, unsigned imm13) const; +unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd, unsigned imm21) const; BYTE* emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id); From e09f03ae6c51b570fa9b6e4d85f614024feb3873 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 12 Jan 2024 09:57:12 +0100 Subject: [PATCH 097/106] Fixes to prev commit --- src/coreclr/jit/emitriscv64.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index a18b9fc96d8e5a..f10f53683e2953 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -96,11 +96,11 @@ bool IsRedundantLdStr( static code_t insEncodeRTypeInstr( unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned rs2, unsigned funct7); -static code_t insEncodeITypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, int imm12); -static code_t insEncodeSTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm12); -static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, int imm20); -static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, int imm13); -static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, int imm21); +static code_t insEncodeITypeInstr(unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned imm12); +static code_t insEncodeSTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm12); +static code_t insEncodeUTypeInstr(unsigned opcode, unsigned rd, unsigned imm20); +static code_t insEncodeBTypeInstr(unsigned opcode, unsigned funct3, unsigned rs1, unsigned rs2, unsigned imm13); +static code_t insEncodeJTypeInstr(unsigned opcode, unsigned rd, unsigned imm21); #ifdef DEBUG static void emitOutput_RTypeInstr_SanityCheck(instruction ins, regNumber rd, regNumber rs1, regNumber rs2); From 4b0f5ee2a89d16384583e23aedec84ba2f0f310b Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 12 Jan 2024 12:47:11 +0100 Subject: [PATCH 098/106] Added castFloatOrIntegralReg and fixed invalid asserts --- src/coreclr/jit/emitriscv64.cpp | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index f637691f324358..b5981b1c6911a1 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2440,13 +2440,13 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; case INS_sh: case INS_sw: case INS_sd: - assert(isGeneralRegisterOrR0(rs1)); + assert(isGeneralRegister(rs1)); assert(isGeneralRegisterOrR0(rs2)); break; case INS_fsw: case INS_fsd: - assert(isFloatReg(rs1)); - assert(isGeneralRegisterOrR0(rs2)); + assert(isGeneralRegister(rs1)); + assert(isFloatRegType(rs2)); break; default: NO_WAY("Illegal ins within emitOutput_STypeInstr!"); @@ -2509,6 +2509,26 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; #endif // DEBUG +/***************************************************************************** + * + * Casts an integral or float register from their identification number to + * theirs binary format. In case of the integral registers the encoded number + * is the register id. In case of the floating point registers the encoded + * number is shifted back by the floating point register base (32) (The + * instruction itself specifies whether the register contains floating + * point or integer, in their encoding they are indistinguishable) + * + */ + +static unsigned castFloatOrIntegralReg(regNumber reg) +{ + static constexpr unsigned kRegisterMask = 0x1f; + + assert(isGeneralRegisterOrR0(reg) || isFloatRegType(reg)); + + return reg & kRegisterMask; +} + /***************************************************************************** * * Emit a 32-bit RISCV64 R-Type instruction to the given buffer. Returns a @@ -2525,7 +2545,8 @@ unsigned emitter::emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 25; - return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, rd, funct3, rs1, rs2, funct7)); + return emitOutput_Instr(dst, insEncodeRTypeInstr(opcode, castFloatOrIntegralReg(rd), funct3, + castFloatOrIntegralReg(rs1), castFloatOrIntegralReg(rs2), funct7)); } /***************************************************************************** @@ -2544,7 +2565,7 @@ unsigned emitter::emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; unsigned funct7 = (insCode & kInstructionFunct7Mask) >> 20; // only used by some of the immediate shifts - return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, rd & 0x1f, funct3, rs1, imm12 | funct7)); + return emitOutput_Instr(dst, insEncodeITypeInstr(opcode, castFloatOrIntegralReg(rd), funct3, rs1, imm12 | funct7)); } /***************************************************************************** @@ -2562,7 +2583,7 @@ unsigned emitter::emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs #endif // DEBUG unsigned opcode = insCode & kInstructionOpcodeMask; unsigned funct3 = (insCode & kInstructionFunct3Mask) >> 12; - return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, rs2 & 0x1f, imm12)); + return emitOutput_Instr(dst, insEncodeSTypeInstr(opcode, funct3, rs1, castFloatOrIntegralReg(rs2), imm12)); } /***************************************************************************** From 03fcfa997e3b9ef497dd389587ead883460cd615 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 12 Jan 2024 12:49:24 +0100 Subject: [PATCH 099/106] Renamed upper word helpers --- src/coreclr/jit/emitriscv64.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index b5981b1c6911a1..03292c5b6286eb 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2778,7 +2778,7 @@ static ssize_t DoubleWordSignExtend(ssize_t doubleWord) } template -static ssize_t UpperWordDoubleWordSignExtend(ssize_t doubleWord) +static ssize_t UpperWordOfDoubleWordSingleSignExtend(ssize_t doubleWord) { static constexpr size_t kUpperSignExtend = static_cast(1) << (31 - UpperMaskSize); @@ -2786,7 +2786,7 @@ static ssize_t UpperWordDoubleWordSignExtend(ssize_t doubleWord) } template -static ssize_t UpperWordOfDoubleWordSignExtend(ssize_t doubleWord) +static ssize_t UpperWordOfDoubleWordDoubleSignExtend(ssize_t doubleWord) { return UpperWordOfDoubleWord(DoubleWordSignExtend(doubleWord)); } @@ -2987,7 +2987,7 @@ BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumbe assert((immediate >> (32 + 20)) == 0); regNumber rsvdReg = codeGen->rsGetRsvdReg(); - ssize_t upperSignExt = UpperWordOfDoubleWordSignExtend<32, 52>(immediate); + ssize_t upperSignExt = UpperWordOfDoubleWordDoubleSignExtend<32, 52>(immediate); dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(immediate)); @@ -3036,7 +3036,7 @@ BYTE* emitter::emitOutputInstr_OptsJalr24(BYTE* dst, ssize_t immediate) { // Make target address with offset, then jump (JALR) with the target address immediate -= 2 * 4; - ssize_t high = UpperWordDoubleWordSignExtend<0>(immediate); + ssize_t high = UpperWordOfDoubleWordSingleSignExtend<0>(immediate); dst += emitOutput_UTypeInstr(dst, INS_lui, REG_RA, UpperNBitsOfWordSignExtend<20>(high)); dst += emitOutput_ITypeInstr(dst, INS_addi, REG_RA, REG_RA, LowerNBitsOfWord<12>(high)); From a18bf4861778b1a3b47c4fbb7c5d4f87c784b194 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 12 Jan 2024 12:51:24 +0100 Subject: [PATCH 100/106] Spell fix --- 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 03292c5b6286eb..0d726bb45b0ec1 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2446,7 +2446,7 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; case INS_fsw: case INS_fsd: assert(isGeneralRegister(rs1)); - assert(isFloatRegType(rs2)); + assert(isFloatReg(rs2)); break; default: NO_WAY("Illegal ins within emitOutput_STypeInstr!"); @@ -2524,7 +2524,7 @@ static unsigned castFloatOrIntegralReg(regNumber reg) { static constexpr unsigned kRegisterMask = 0x1f; - assert(isGeneralRegisterOrR0(reg) || isFloatRegType(reg)); + assert(isGeneralRegisterOrR0(reg) || isFloatReg(reg)); return reg & kRegisterMask; } From 97b09514bddac1122414ec65d6a3447659117064 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 12 Jan 2024 12:58:38 +0100 Subject: [PATCH 101/106] Moved castFloat... to the emitter --- src/coreclr/jit/emitriscv64.cpp | 2 +- src/coreclr/jit/emitriscv64.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 0d726bb45b0ec1..19bb2c2de76ebd 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2520,7 +2520,7 @@ static constexpr unsigned kInstructionFunct7Mask = 0xfe000000; * */ -static unsigned castFloatOrIntegralReg(regNumber reg) +/*static*/ unsigned emitter::castFloatOrIntegralReg(regNumber reg) { static constexpr unsigned kRegisterMask = 0x1f; diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index f10f53683e2953..688f9d1f757a3f 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -112,6 +112,8 @@ static void emitOutput_BTypeInstr_SanityCheck(instruction ins, regNumber rs1, re static void emitOutput_JTypeInstr_SanityCheck(instruction ins, regNumber rd); #endif // DEBUG +static unsigned castFloatOrIntegralReg(regNumber reg); + unsigned emitOutput_RTypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, regNumber rs2) const; unsigned emitOutput_ITypeInstr(BYTE* dst, instruction ins, regNumber rd, regNumber rs1, unsigned imm12) const; unsigned emitOutput_STypeInstr(BYTE* dst, instruction ins, regNumber rs1, regNumber rs2, unsigned imm12) const; From 6c9fe76f066d9705fb8fa337d6c1a4f646555901 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Fri, 12 Jan 2024 16:03:34 +0100 Subject: [PATCH 102/106] Changes after code review --- 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 19bb2c2de76ebd..5ee4fb519faaec 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2122,7 +2122,7 @@ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code) const return sizeof(code_t); } -static void assertCodeLength(unsigned code, uint8_t size) +static inline void assertCodeLength(unsigned code, uint8_t size) { assert((code >> size) == 0); } @@ -2732,7 +2732,7 @@ static constexpr size_t NBitMask(uint8_t bits) template static ssize_t LowerNBitsOfWord(ssize_t word) { - static_assert(MaskSize < 32, "Given mask size is bigger tham the word itself"); + static_assert(MaskSize < 32, "Given mask size is bigger than the word itself"); static_assert(MaskSize > 0, "Given mask size cannot be zero"); static constexpr size_t kMask = NBitMask(MaskSize); From 7e13ad4ef3d45182b46c4e2730a70e488c6637be Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 15 Jan 2024 10:28:21 +0100 Subject: [PATCH 103/106] Removed bitcast --- src/coreclr/jit/emitriscv64.cpp | 10 +++++----- src/coreclr/jit/utils.h | 10 ---------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 5ee4fb519faaec..bceec14af19689 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2845,7 +2845,7 @@ BYTE* emitter::emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruc BYTE* emitter::emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id) { - ssize_t immediate = BitCast(id->idAddr()->iiaAddr); + ssize_t immediate = reinterpret_cast(id->idAddr()->iiaAddr); const regNumber reg1 = id->idReg1(); switch (id->idCodeSize()) @@ -2919,7 +2919,7 @@ BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instructio BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, instruction* ins, regNumber reg1) { - ssize_t immediate = BitCast(emitConsBlock) - BitCast(dst); + ssize_t immediate = reinterpret_cast(emitConsBlock) - reinterpret_cast(dst); assert(immediate > 0); assert((immediate & 0x03) == 0); @@ -2939,7 +2939,7 @@ BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, instruction* ins, regNumbe BYTE* emitter::emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsigned offset, regNumber reg1) { - ssize_t immediate = BitCast(emitConsBlock) + offset; + ssize_t immediate = reinterpret_cast(emitConsBlock) + offset; assert((immediate >> 40) == 0); regNumber rsvdReg = codeGen->rsGetRsvdReg(); @@ -2973,7 +2973,7 @@ BYTE* emitter::emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins BYTE* emitter::emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber reg1) { - ssize_t immediate = BitCast(emitCodeBlock) + igOffs - BitCast(dst); + ssize_t immediate = reinterpret_cast(emitCodeBlock) + igOffs - reinterpret_cast(dst); assert((immediate & 0x03) == 0); dst += emitOutput_UTypeInstr(dst, INS_auipc, reg1, UpperNBitsOfWordSignExtend<20>(immediate)); @@ -2983,7 +2983,7 @@ BYTE* emitter::emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumber reg1) { - ssize_t immediate = BitCast(emitCodeBlock) + igOffs; + ssize_t immediate = reinterpret_cast(emitCodeBlock) + igOffs; assert((immediate >> (32 + 20)) == 0); regNumber rsvdReg = codeGen->rsGetRsvdReg(); diff --git a/src/coreclr/jit/utils.h b/src/coreclr/jit/utils.h index 921be13daf0569..1eaa16d67ba81e 100644 --- a/src/coreclr/jit/utils.h +++ b/src/coreclr/jit/utils.h @@ -1086,14 +1086,4 @@ bool CastFromFloatOverflows(float fromValue, var_types toType); bool CastFromDoubleOverflows(double fromValue, var_types toType); } -template -T BitCast(const U& value) -{ - static_assert(sizeof(U) == sizeof(T), "T and U have to have the same size"); - - T result; - memcpy(&result, &value, sizeof(T)); - return result; -} - #endif // _UTILS_H_ From 6f61ec0d654fa9217fa2537b3db9a397b2c5e63b Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 15 Jan 2024 10:30:35 +0100 Subject: [PATCH 104/106] Added additional check --- src/coreclr/jit/emitriscv64.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index bceec14af19689..363abcb17eca0a 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2117,6 +2117,7 @@ void emitter::emitJumpDistBind() unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code) const { + assert(dst != nullptr); assert(sizeof(code_t) == 4); memcpy(dst + writeableOffset, &code, sizeof(code_t)); return sizeof(code_t); From 02462450b1d81ad2a63ac6aa5e786c66f397ca1a Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 15 Jan 2024 10:33:18 +0100 Subject: [PATCH 105/106] Removed unnecessary reinterpret casts --- 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 363abcb17eca0a..2e23d66e6dce73 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2920,7 +2920,7 @@ BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instructio BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, instruction* ins, regNumber reg1) { - ssize_t immediate = reinterpret_cast(emitConsBlock) - reinterpret_cast(dst); + ssize_t immediate = emitConsBlock - dst; assert(immediate > 0); assert((immediate & 0x03) == 0); @@ -2974,7 +2974,7 @@ BYTE* emitter::emitOutputInstr_OptsRl(BYTE* dst, instrDesc* id, instruction* ins BYTE* emitter::emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber reg1) { - ssize_t immediate = reinterpret_cast(emitCodeBlock) + igOffs - reinterpret_cast(dst); + ssize_t immediate = (emitCodeBlock - dst) + igOffs; assert((immediate & 0x03) == 0); dst += emitOutput_UTypeInstr(dst, INS_auipc, reg1, UpperNBitsOfWordSignExtend<20>(immediate)); From 1120364a3aa01fd04d6747d68c4faca449fc25d1 Mon Sep 17 00:00:00 2001 From: Grzegorz Czarnecki Date: Mon, 15 Jan 2024 10:39:29 +0100 Subject: [PATCH 106/106] Removed redundant asserts --- src/coreclr/jit/emitriscv64.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 2e23d66e6dce73..8f2a83b08799b6 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -3023,9 +3023,6 @@ BYTE* emitter::emitOutputInstr_OptsJalr(BYTE* dst, instrDescJmp* jmp, const insG BYTE* emitter::emitOutputInstr_OptsJalr8(BYTE* dst, const instrDescJmp* jmp, instruction ins, ssize_t immediate) { - assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || (INS_bnez == ins) || - (INS_beqz == ins)); - regNumber reg2 = ((ins != INS_beqz) && (ins != INS_bnez)) ? jmp->idReg2() : REG_R0; dst += emitOutput_BTypeInstr_InvertComparation(dst, ins, jmp->idReg1(), reg2, 0x8);