base-riscv-i.h (10258B)
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 #ifndef jit_riscv64_extension_Base_riscv_i_h_ 5 #define jit_riscv64_extension_Base_riscv_i_h_ 6 #include "mozilla/Assertions.h" 7 8 #include <stdint.h> 9 10 #include "jit/riscv64/constant/Constant-riscv64.h" 11 #include "jit/riscv64/extension/base-assembler-riscv.h" 12 namespace js { 13 namespace jit { 14 15 class AssemblerRISCVI : public AssemblerRiscvBase { 16 public: 17 void lui(Register rd, int32_t imm20); 18 void auipc(Register rd, int32_t imm20); 19 20 // Jumps 21 CodeOffset jal(Register rd, int32_t imm20); 22 BufferOffset jalr(Register rd, Register rs1, int16_t imm12); 23 24 // Branches 25 void beq(Register rs1, Register rs2, int16_t imm12); 26 void bne(Register rs1, Register rs2, int16_t imm12); 27 void blt(Register rs1, Register rs2, int16_t imm12); 28 void bge(Register rs1, Register rs2, int16_t imm12); 29 void bltu(Register rs1, Register rs2, int16_t imm12); 30 void bgeu(Register rs1, Register rs2, int16_t imm12); 31 // Loads 32 void lb(Register rd, Register rs1, int16_t imm12); 33 void lh(Register rd, Register rs1, int16_t imm12); 34 void lw(Register rd, Register rs1, int16_t imm12); 35 void lbu(Register rd, Register rs1, int16_t imm12); 36 void lhu(Register rd, Register rs1, int16_t imm12); 37 38 // Stores 39 void sb(Register source, Register base, int16_t imm12); 40 void sh(Register source, Register base, int16_t imm12); 41 void sw(Register source, Register base, int16_t imm12); 42 43 // Arithmetic with immediate 44 void addi(Register rd, Register rs1, int16_t imm12); 45 void slti(Register rd, Register rs1, int16_t imm12); 46 void sltiu(Register rd, Register rs1, int16_t imm12); 47 void xori(Register rd, Register rs1, int16_t imm12); 48 void ori(Register rd, Register rs1, int16_t imm12); 49 void andi(Register rd, Register rs1, int16_t imm12); 50 void slli(Register rd, Register rs1, uint8_t shamt); 51 void srli(Register rd, Register rs1, uint8_t shamt); 52 void srai(Register rd, Register rs1, uint8_t shamt); 53 54 // Arithmetic 55 void add(Register rd, Register rs1, Register rs2); 56 void sub(Register rd, Register rs1, Register rs2); 57 void sll(Register rd, Register rs1, Register rs2); 58 void slt(Register rd, Register rs1, Register rs2); 59 void sltu(Register rd, Register rs1, Register rs2); 60 void xor_(Register rd, Register rs1, Register rs2); 61 void srl(Register rd, Register rs1, Register rs2); 62 void sra(Register rd, Register rs1, Register rs2); 63 void or_(Register rd, Register rs1, Register rs2); 64 void and_(Register rd, Register rs1, Register rs2); 65 66 // Other pseudo instructions that are not part of RISCV pseudo assemly 67 void nor(Register rd, Register rs, Register rt) { 68 or_(rd, rs, rt); 69 not_(rd, rd); 70 } 71 72 // Memory fences 73 void fence(uint8_t pred, uint8_t succ); 74 void fence_tso(); 75 76 // Environment call / break 77 void ecall(); 78 void ebreak(); 79 80 void sync() { fence(0b1111, 0b1111); } 81 82 // This is a de facto standard (as set by GNU binutils) 32-bit unimplemented 83 // instruction (i.e., it should always trap, if your implementation has 84 // invalid instruction traps). 85 void unimp(); 86 87 static int JumpOffset(Instr instr); 88 static int AuipcOffset(Instr instr); 89 static int JalrOffset(Instr instr); 90 static int LoadOffset(Instr instr); 91 static int BranchOffset(Instr instr); 92 static int BrachlongOffset(Instr auipc, Instr instr_I); 93 static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos, 94 Instr instr) { 95 int32_t imm = target_pos - pos; 96 MOZ_ASSERT((imm & 1) == 0); 97 MOZ_ASSERT(is_intn(imm, kBranchOffsetBits)); 98 99 instr &= ~kBImm12Mask; 100 int32_t imm12 = ((imm & 0x800) >> 4) | // bit 11 101 ((imm & 0x1e) << 7) | // bits 4-1 102 ((imm & 0x7e0) << 20) | // bits 10-5 103 ((imm & 0x1000) << 19); // bit 12 104 105 return instr | (imm12 & kBImm12Mask); 106 } 107 108 static inline Instr SetJalOffset(int32_t pos, int32_t target_pos, 109 Instr instr) { 110 MOZ_ASSERT(IsJal(instr)); 111 int32_t imm = target_pos - pos; 112 MOZ_ASSERT((imm & 1) == 0); 113 MOZ_ASSERT(is_intn(imm, kJumpOffsetBits)); 114 115 instr &= ~kImm20Mask; 116 int32_t imm20 = (imm & 0xff000) | // bits 19-12 117 ((imm & 0x800) << 9) | // bit 11 118 ((imm & 0x7fe) << 20) | // bits 10-1 119 ((imm & 0x100000) << 11); // bit 20 120 121 return instr | (imm20 & kImm20Mask); 122 } 123 124 static inline Instr SetJalrOffset(int32_t offset, Instr instr) { 125 MOZ_ASSERT(IsJalr(instr)); 126 MOZ_ASSERT(is_int12(offset)); 127 instr &= ~kImm12Mask; 128 int32_t imm12 = offset << kImm12Shift; 129 MOZ_ASSERT(IsJalr(instr | (imm12 & kImm12Mask))); 130 MOZ_ASSERT(JalrOffset(instr | (imm12 & kImm12Mask)) == offset); 131 return instr | (imm12 & kImm12Mask); 132 } 133 134 static inline Instr SetLoadOffset(int32_t offset, Instr instr) { 135 #if JS_CODEGEN_RISCV64 136 MOZ_ASSERT(IsLd(instr)); 137 #elif JS_CODEGEN_RISCV32 138 MOZ_ASSERT(IsLw(instr)); 139 #endif 140 MOZ_ASSERT(is_int12(offset)); 141 instr &= ~kImm12Mask; 142 int32_t imm12 = offset << kImm12Shift; 143 return instr | (imm12 & kImm12Mask); 144 } 145 146 static inline Instr SetAuipcOffset(int32_t offset, Instr instr) { 147 MOZ_ASSERT(IsAuipc(instr)); 148 MOZ_ASSERT(is_int20(offset)); 149 instr = (instr & ~kImm31_12Mask) | ((offset & kImm19_0Mask) << 12); 150 return instr; 151 } 152 153 // Check if an instruction is a branch of some kind. 154 static bool IsBranch(Instr instr); 155 static bool IsNop(Instr instr); 156 static bool IsJump(Instr instr); 157 static bool IsJal(Instr instr); 158 static bool IsJalr(Instr instr); 159 static bool IsLui(Instr instr); 160 static bool IsAuipc(Instr instr); 161 static bool IsAddi(Instr instr); 162 static bool IsOri(Instr instr); 163 static bool IsSlli(Instr instr); 164 static bool IsLw(Instr instr); 165 166 inline int32_t branchOffset(Label* L) { 167 return branchOffsetHelper(L, OffsetSize::kOffset13); 168 } 169 inline int32_t jumpOffset(Label* L) { 170 return branchOffsetHelper(L, OffsetSize::kOffset21); 171 } 172 173 // Branches 174 void beq(Register rs1, Register rs2, Label* L) { 175 beq(rs1, rs2, branchOffset(L)); 176 } 177 void bne(Register rs1, Register rs2, Label* L) { 178 bne(rs1, rs2, branchOffset(L)); 179 } 180 void blt(Register rs1, Register rs2, Label* L) { 181 blt(rs1, rs2, branchOffset(L)); 182 } 183 void bge(Register rs1, Register rs2, Label* L) { 184 bge(rs1, rs2, branchOffset(L)); 185 } 186 void bltu(Register rs1, Register rs2, Label* L) { 187 bltu(rs1, rs2, branchOffset(L)); 188 } 189 void bgeu(Register rs1, Register rs2, Label* L) { 190 bgeu(rs1, rs2, branchOffset(L)); 191 } 192 193 void beqz(Register rs, int16_t imm13) { beq(rs, zero_reg, imm13); } 194 void beqz(Register rs1, Label* L) { beqz(rs1, branchOffset(L)); } 195 void bnez(Register rs, int16_t imm13) { bne(rs, zero_reg, imm13); } 196 void bnez(Register rs1, Label* L) { bnez(rs1, branchOffset(L)); } 197 void blez(Register rs, int16_t imm13) { bge(zero_reg, rs, imm13); } 198 void blez(Register rs1, Label* L) { blez(rs1, branchOffset(L)); } 199 void bgez(Register rs, int16_t imm13) { bge(rs, zero_reg, imm13); } 200 void bgez(Register rs1, Label* L) { bgez(rs1, branchOffset(L)); } 201 void bltz(Register rs, int16_t imm13) { blt(rs, zero_reg, imm13); } 202 void bltz(Register rs1, Label* L) { bltz(rs1, branchOffset(L)); } 203 void bgtz(Register rs, int16_t imm13) { blt(zero_reg, rs, imm13); } 204 205 void bgtz(Register rs1, Label* L) { bgtz(rs1, branchOffset(L)); } 206 void bgt(Register rs1, Register rs2, int16_t imm13) { blt(rs2, rs1, imm13); } 207 void bgt(Register rs1, Register rs2, Label* L) { 208 bgt(rs1, rs2, branchOffset(L)); 209 } 210 void ble(Register rs1, Register rs2, int16_t imm13) { bge(rs2, rs1, imm13); } 211 void ble(Register rs1, Register rs2, Label* L) { 212 ble(rs1, rs2, branchOffset(L)); 213 } 214 void bgtu(Register rs1, Register rs2, int16_t imm13) { 215 bltu(rs2, rs1, imm13); 216 } 217 void bgtu(Register rs1, Register rs2, Label* L) { 218 bgtu(rs1, rs2, branchOffset(L)); 219 } 220 void bleu(Register rs1, Register rs2, int16_t imm13) { 221 bgeu(rs2, rs1, imm13); 222 } 223 void bleu(Register rs1, Register rs2, Label* L) { 224 bleu(rs1, rs2, branchOffset(L)); 225 } 226 227 CodeOffset j(int32_t imm21) { return jal(zero_reg, imm21); } 228 CodeOffset j(Label* L) { return j(jumpOffset(L)); } 229 CodeOffset b(Label* L) { return j(L); } 230 CodeOffset jal(int32_t imm21) { return jal(ra, imm21); } 231 CodeOffset jal(Label* L) { return jal(jumpOffset(L)); } 232 void jr(Register rs) { jalr(zero_reg, rs, 0); } 233 void jr(Register rs, int32_t imm12) { jalr(zero_reg, rs, imm12); } 234 void jalr(Register rs, int32_t imm12) { jalr(ra, rs, imm12); } 235 void jalr(Register rs) { jalr(ra, rs, 0); } 236 void call(int32_t offset) { 237 auipc(ra, (offset >> 12) + ((offset & 0x800) >> 11)); 238 jalr(ra, ra, offset << 20 >> 20); 239 } 240 241 void mv(Register rd, Register rs) { addi(rd, rs, 0); } 242 void not_(Register rd, Register rs) { xori(rd, rs, -1); } 243 void neg(Register rd, Register rs) { sub(rd, zero_reg, rs); } 244 void seqz(Register rd, Register rs) { sltiu(rd, rs, 1); } 245 void snez(Register rd, Register rs) { sltu(rd, zero_reg, rs); } 246 void sltz(Register rd, Register rs) { slt(rd, rs, zero_reg); } 247 void sgtz(Register rd, Register rs) { slt(rd, zero_reg, rs); } 248 249 #if JS_CODEGEN_RISCV64 250 void lwu(Register rd, Register rs1, int16_t imm12); 251 void ld(Register rd, Register rs1, int16_t imm12); 252 void sd(Register source, Register base, int16_t imm12); 253 void addiw(Register rd, Register rs1, int16_t imm12); 254 void slliw(Register rd, Register rs1, uint8_t shamt); 255 void srliw(Register rd, Register rs1, uint8_t shamt); 256 void sraiw(Register rd, Register rs1, uint8_t shamt); 257 void addw(Register rd, Register rs1, Register rs2); 258 void subw(Register rd, Register rs1, Register rs2); 259 void sllw(Register rd, Register rs1, Register rs2); 260 void srlw(Register rd, Register rs1, Register rs2); 261 void sraw(Register rd, Register rs1, Register rs2); 262 void negw(Register rd, Register rs) { subw(rd, zero_reg, rs); } 263 void sext_w(Register rd, Register rs) { addiw(rd, rs, 0); } 264 265 static bool IsAddiw(Instr instr); 266 static bool IsLd(Instr instr); 267 #endif 268 }; 269 270 } // namespace jit 271 } // namespace js 272 273 #endif // jit_riscv64_extension_Base_riscv_I_h_