extension-riscv-c.cc (9491B)
1 // Copyright 2022 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 #include "jit/riscv64/extension/extension-riscv-c.h" 5 #include "jit/riscv64/Assembler-riscv64.h" 6 #include "jit/riscv64/constant/Constant-riscv64.h" 7 #include "jit/riscv64/Architecture-riscv64.h" 8 namespace js { 9 namespace jit { 10 // RV64C Standard Extension 11 void AssemblerRISCVC::c_nop() { GenInstrCI(0b000, C1, zero_reg, 0); } 12 13 void AssemblerRISCVC::c_addi(Register rd, int8_t imm6) { 14 MOZ_ASSERT(rd != zero_reg && imm6 != 0); 15 GenInstrCI(0b000, C1, rd, imm6); 16 } 17 18 #ifdef JS_CODEGEN_RISCV64 19 void AssemblerRISCVC::c_addiw(Register rd, int8_t imm6) { 20 MOZ_ASSERT(rd != zero_reg); 21 GenInstrCI(0b001, C1, rd, imm6); 22 } 23 #endif 24 25 void AssemblerRISCVC::c_addi16sp(int16_t imm10) { 26 MOZ_ASSERT(is_int10(imm10) && (imm10 & 0xf) == 0); 27 uint8_t uimm6 = ((imm10 & 0x200) >> 4) | (imm10 & 0x10) | 28 ((imm10 & 0x40) >> 3) | ((imm10 & 0x180) >> 6) | 29 ((imm10 & 0x20) >> 5); 30 GenInstrCIU(0b011, C1, sp, uimm6); 31 } 32 33 void AssemblerRISCVC::c_addi4spn(Register rd, int16_t uimm10) { 34 MOZ_ASSERT(is_uint10(uimm10) && (uimm10 != 0)); 35 uint8_t uimm8 = ((uimm10 & 0x4) >> 1) | ((uimm10 & 0x8) >> 3) | 36 ((uimm10 & 0x30) << 2) | ((uimm10 & 0x3c0) >> 4); 37 GenInstrCIW(0b000, C0, rd, uimm8); 38 } 39 40 void AssemblerRISCVC::c_li(Register rd, int8_t imm6) { 41 MOZ_ASSERT(rd != zero_reg); 42 GenInstrCI(0b010, C1, rd, imm6); 43 } 44 45 void AssemblerRISCVC::c_lui(Register rd, int8_t imm6) { 46 MOZ_ASSERT(rd != zero_reg && rd != sp && imm6 != 0); 47 GenInstrCI(0b011, C1, rd, imm6); 48 } 49 50 void AssemblerRISCVC::c_slli(Register rd, uint8_t shamt6) { 51 MOZ_ASSERT(rd != zero_reg && shamt6 != 0); 52 GenInstrCIU(0b000, C2, rd, shamt6); 53 } 54 55 void AssemblerRISCVC::c_fldsp(FPURegister rd, uint16_t uimm9) { 56 MOZ_ASSERT(is_uint9(uimm9) && (uimm9 & 0x7) == 0); 57 uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6); 58 GenInstrCIU(0b001, C2, rd, uimm6); 59 } 60 61 #ifdef JS_CODEGEN_RISCV64 62 void AssemblerRISCVC::c_ldsp(Register rd, uint16_t uimm9) { 63 MOZ_ASSERT(rd != zero_reg && is_uint9(uimm9) && (uimm9 & 0x7) == 0); 64 uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6); 65 GenInstrCIU(0b011, C2, rd, uimm6); 66 } 67 #endif 68 69 void AssemblerRISCVC::c_lwsp(Register rd, uint16_t uimm8) { 70 MOZ_ASSERT(rd != zero_reg && is_uint8(uimm8) && (uimm8 & 0x3) == 0); 71 uint8_t uimm6 = (uimm8 & 0x3c) | ((uimm8 & 0xc0) >> 6); 72 GenInstrCIU(0b010, C2, rd, uimm6); 73 } 74 75 void AssemblerRISCVC::c_jr(Register rs1) { 76 MOZ_ASSERT(rs1 != zero_reg); 77 GenInstrCR(0b1000, C2, rs1, zero_reg); 78 } 79 80 void AssemblerRISCVC::c_mv(Register rd, Register rs2) { 81 MOZ_ASSERT(rd != zero_reg && rs2 != zero_reg); 82 GenInstrCR(0b1000, C2, rd, rs2); 83 } 84 85 void AssemblerRISCVC::c_ebreak() { GenInstrCR(0b1001, C2, zero_reg, zero_reg); } 86 87 void AssemblerRISCVC::c_jalr(Register rs1) { 88 MOZ_ASSERT(rs1 != zero_reg); 89 GenInstrCR(0b1001, C2, rs1, zero_reg); 90 } 91 92 void AssemblerRISCVC::c_add(Register rd, Register rs2) { 93 MOZ_ASSERT(rd != zero_reg && rs2 != zero_reg); 94 GenInstrCR(0b1001, C2, rd, rs2); 95 } 96 97 // CA Instructions 98 void AssemblerRISCVC::c_sub(Register rd, Register rs2) { 99 MOZ_ASSERT(((rd.code() & 0b11000) == 0b01000) && 100 ((rs2.code() & 0b11000) == 0b01000)); 101 GenInstrCA(0b100011, C1, rd, 0b00, rs2); 102 } 103 104 void AssemblerRISCVC::c_xor(Register rd, Register rs2) { 105 MOZ_ASSERT(((rd.code() & 0b11000) == 0b01000) && 106 ((rs2.code() & 0b11000) == 0b01000)); 107 GenInstrCA(0b100011, C1, rd, 0b01, rs2); 108 } 109 110 void AssemblerRISCVC::c_or(Register rd, Register rs2) { 111 MOZ_ASSERT(((rd.code() & 0b11000) == 0b01000) && 112 ((rs2.code() & 0b11000) == 0b01000)); 113 GenInstrCA(0b100011, C1, rd, 0b10, rs2); 114 } 115 116 void AssemblerRISCVC::c_and(Register rd, Register rs2) { 117 MOZ_ASSERT(((rd.code() & 0b11000) == 0b01000) && 118 ((rs2.code() & 0b11000) == 0b01000)); 119 GenInstrCA(0b100011, C1, rd, 0b11, rs2); 120 } 121 122 #ifdef JS_CODEGEN_RISCV64 123 void AssemblerRISCVC::c_subw(Register rd, Register rs2) { 124 MOZ_ASSERT(((rd.code() & 0b11000) == 0b01000) && 125 ((rs2.code() & 0b11000) == 0b01000)); 126 GenInstrCA(0b100111, C1, rd, 0b00, rs2); 127 } 128 129 void AssemblerRISCVC::c_addw(Register rd, Register rs2) { 130 MOZ_ASSERT(((rd.code() & 0b11000) == 0b01000) && 131 ((rs2.code() & 0b11000) == 0b01000)); 132 GenInstrCA(0b100111, C1, rd, 0b01, rs2); 133 } 134 #endif 135 136 void AssemblerRISCVC::c_swsp(Register rs2, uint16_t uimm8) { 137 MOZ_ASSERT(is_uint8(uimm8) && (uimm8 & 0x3) == 0); 138 uint8_t uimm6 = (uimm8 & 0x3c) | ((uimm8 & 0xc0) >> 6); 139 GenInstrCSS(0b110, C2, rs2, uimm6); 140 } 141 142 #ifdef JS_CODEGEN_RISCV64 143 void AssemblerRISCVC::c_sdsp(Register rs2, uint16_t uimm9) { 144 MOZ_ASSERT(is_uint9(uimm9) && (uimm9 & 0x7) == 0); 145 uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6); 146 GenInstrCSS(0b111, C2, rs2, uimm6); 147 } 148 #endif 149 150 void AssemblerRISCVC::c_fsdsp(FPURegister rs2, uint16_t uimm9) { 151 MOZ_ASSERT(is_uint9(uimm9) && (uimm9 & 0x7) == 0); 152 uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6); 153 GenInstrCSS(0b101, C2, rs2, uimm6); 154 } 155 156 // CL Instructions 157 158 void AssemblerRISCVC::c_lw(Register rd, Register rs1, uint16_t uimm7) { 159 MOZ_ASSERT(((rd.code() & 0b11000) == 0b01000) && 160 ((rs1.code() & 0b11000) == 0b01000) && is_uint7(uimm7) && 161 ((uimm7 & 0x3) == 0)); 162 uint8_t uimm5 = 163 ((uimm7 & 0x4) >> 1) | ((uimm7 & 0x40) >> 6) | ((uimm7 & 0x38) >> 1); 164 GenInstrCL(0b010, C0, rd, rs1, uimm5); 165 } 166 167 #ifdef JS_CODEGEN_RISCV64 168 void AssemblerRISCVC::c_ld(Register rd, Register rs1, uint16_t uimm8) { 169 MOZ_ASSERT(((rd.code() & 0b11000) == 0b01000) && 170 ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) && 171 ((uimm8 & 0x7) == 0)); 172 uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6); 173 GenInstrCL(0b011, C0, rd, rs1, uimm5); 174 } 175 #endif 176 177 void AssemblerRISCVC::c_fld(FPURegister rd, Register rs1, uint16_t uimm8) { 178 MOZ_ASSERT(((rd.encoding() & 0b11000) == 0b01000) && 179 ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) && 180 ((uimm8 & 0x7) == 0)); 181 uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6); 182 GenInstrCL(0b001, C0, rd, rs1, uimm5); 183 } 184 185 // CS Instructions 186 187 void AssemblerRISCVC::c_sw(Register rs2, Register rs1, uint16_t uimm7) { 188 MOZ_ASSERT(((rs2.code() & 0b11000) == 0b01000) && 189 ((rs1.code() & 0b11000) == 0b01000) && is_uint7(uimm7) && 190 ((uimm7 & 0x3) == 0)); 191 uint8_t uimm5 = 192 ((uimm7 & 0x4) >> 1) | ((uimm7 & 0x40) >> 6) | ((uimm7 & 0x38) >> 1); 193 GenInstrCS(0b110, C0, rs2, rs1, uimm5); 194 } 195 196 #ifdef JS_CODEGEN_RISCV64 197 void AssemblerRISCVC::c_sd(Register rs2, Register rs1, uint16_t uimm8) { 198 MOZ_ASSERT(((rs2.code() & 0b11000) == 0b01000) && 199 ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) && 200 ((uimm8 & 0x7) == 0)); 201 uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6); 202 GenInstrCS(0b111, C0, rs2, rs1, uimm5); 203 } 204 #endif 205 206 void AssemblerRISCVC::c_fsd(FPURegister rs2, Register rs1, uint16_t uimm8) { 207 MOZ_ASSERT(((rs2.encoding() & 0b11000) == 0b01000) && 208 ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) && 209 ((uimm8 & 0x7) == 0)); 210 uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6); 211 GenInstrCS(0b101, C0, rs2, rs1, uimm5); 212 } 213 214 // CJ Instructions 215 216 void AssemblerRISCVC::c_j(int16_t imm12) { 217 MOZ_ASSERT(is_int12(imm12)); 218 int16_t uimm11 = ((imm12 & 0x800) >> 1) | ((imm12 & 0x400) >> 4) | 219 ((imm12 & 0x300) >> 1) | ((imm12 & 0x80) >> 3) | 220 ((imm12 & 0x40) >> 1) | ((imm12 & 0x20) >> 5) | 221 ((imm12 & 0x10) << 5) | (imm12 & 0xe); 222 GenInstrCJ(0b101, C1, uimm11); 223 } 224 225 // CB Instructions 226 227 void AssemblerRISCVC::c_bnez(Register rs1, int16_t imm9) { 228 MOZ_ASSERT(((rs1.code() & 0b11000) == 0b01000) && is_int9(imm9)); 229 uint8_t uimm8 = ((imm9 & 0x20) >> 5) | ((imm9 & 0x6)) | ((imm9 & 0xc0) >> 3) | 230 ((imm9 & 0x18) << 2) | ((imm9 & 0x100) >> 1); 231 GenInstrCB(0b111, C1, rs1, uimm8); 232 } 233 234 void AssemblerRISCVC::c_beqz(Register rs1, int16_t imm9) { 235 MOZ_ASSERT(((rs1.code() & 0b11000) == 0b01000) && is_int9(imm9)); 236 uint8_t uimm8 = ((imm9 & 0x20) >> 5) | ((imm9 & 0x6)) | ((imm9 & 0xc0) >> 3) | 237 ((imm9 & 0x18) << 2) | ((imm9 & 0x100) >> 1); 238 GenInstrCB(0b110, C1, rs1, uimm8); 239 } 240 241 void AssemblerRISCVC::c_srli(Register rs1, int8_t shamt6) { 242 MOZ_ASSERT(((rs1.code() & 0b11000) == 0b01000) && is_int6(shamt6)); 243 GenInstrCBA(0b100, 0b00, C1, rs1, shamt6); 244 } 245 246 void AssemblerRISCVC::c_srai(Register rs1, int8_t shamt6) { 247 MOZ_ASSERT(((rs1.code() & 0b11000) == 0b01000) && is_int6(shamt6)); 248 GenInstrCBA(0b100, 0b01, C1, rs1, shamt6); 249 } 250 251 void AssemblerRISCVC::c_andi(Register rs1, int8_t imm6) { 252 MOZ_ASSERT(((rs1.code() & 0b11000) == 0b01000) && is_int6(imm6)); 253 GenInstrCBA(0b100, 0b10, C1, rs1, imm6); 254 } 255 256 bool AssemblerRISCVC::IsCJal(Instr instr) { 257 return (instr & kRvcOpcodeMask) == RO_C_J; 258 } 259 260 bool AssemblerRISCVC::IsCBranch(Instr instr) { 261 int Op = instr & kRvcOpcodeMask; 262 return Op == RO_C_BNEZ || Op == RO_C_BEQZ; 263 } 264 265 int AssemblerRISCVC::CJumpOffset(Instr instr) { 266 int32_t imm12 = ((instr & 0x4) << 3) | ((instr & 0x38) >> 2) | 267 ((instr & 0x40) << 1) | ((instr & 0x80) >> 1) | 268 ((instr & 0x100) << 2) | ((instr & 0x600) >> 1) | 269 ((instr & 0x800) >> 7) | ((instr & 0x1000) >> 1); 270 imm12 = imm12 << 20 >> 20; 271 return imm12; 272 } 273 274 } // namespace jit 275 } // namespace js