summaryrefslogtreecommitdiffstats
path: root/js/src/jit/riscv64/extension/base-riscv-i.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/riscv64/extension/base-riscv-i.h')
-rw-r--r--js/src/jit/riscv64/extension/base-riscv-i.h273
1 files changed, 273 insertions, 0 deletions
diff --git a/js/src/jit/riscv64/extension/base-riscv-i.h b/js/src/jit/riscv64/extension/base-riscv-i.h
new file mode 100644
index 0000000000..cca342c960
--- /dev/null
+++ b/js/src/jit/riscv64/extension/base-riscv-i.h
@@ -0,0 +1,273 @@
+// Copyright 2022 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef jit_riscv64_extension_Base_riscv_i_h_
+#define jit_riscv64_extension_Base_riscv_i_h_
+#include "mozilla/Assertions.h"
+
+#include <stdint.h>
+
+#include "jit/riscv64/constant/Constant-riscv64.h"
+#include "jit/riscv64/extension/base-assembler-riscv.h"
+namespace js {
+namespace jit {
+
+class AssemblerRISCVI : public AssemblerRiscvBase {
+ public:
+ void lui(Register rd, int32_t imm20);
+ void auipc(Register rd, int32_t imm20);
+
+ // Jumps
+ void jal(Register rd, int32_t imm20);
+ void jalr(Register rd, Register rs1, int16_t imm12);
+
+ // Branches
+ void beq(Register rs1, Register rs2, int16_t imm12);
+ void bne(Register rs1, Register rs2, int16_t imm12);
+ void blt(Register rs1, Register rs2, int16_t imm12);
+ void bge(Register rs1, Register rs2, int16_t imm12);
+ void bltu(Register rs1, Register rs2, int16_t imm12);
+ void bgeu(Register rs1, Register rs2, int16_t imm12);
+ // Loads
+ void lb(Register rd, Register rs1, int16_t imm12);
+ void lh(Register rd, Register rs1, int16_t imm12);
+ void lw(Register rd, Register rs1, int16_t imm12);
+ void lbu(Register rd, Register rs1, int16_t imm12);
+ void lhu(Register rd, Register rs1, int16_t imm12);
+
+ // Stores
+ void sb(Register source, Register base, int16_t imm12);
+ void sh(Register source, Register base, int16_t imm12);
+ void sw(Register source, Register base, int16_t imm12);
+
+ // Arithmetic with immediate
+ void addi(Register rd, Register rs1, int16_t imm12);
+ void slti(Register rd, Register rs1, int16_t imm12);
+ void sltiu(Register rd, Register rs1, int16_t imm12);
+ void xori(Register rd, Register rs1, int16_t imm12);
+ void ori(Register rd, Register rs1, int16_t imm12);
+ void andi(Register rd, Register rs1, int16_t imm12);
+ void slli(Register rd, Register rs1, uint8_t shamt);
+ void srli(Register rd, Register rs1, uint8_t shamt);
+ void srai(Register rd, Register rs1, uint8_t shamt);
+
+ // Arithmetic
+ void add(Register rd, Register rs1, Register rs2);
+ void sub(Register rd, Register rs1, Register rs2);
+ void sll(Register rd, Register rs1, Register rs2);
+ void slt(Register rd, Register rs1, Register rs2);
+ void sltu(Register rd, Register rs1, Register rs2);
+ void xor_(Register rd, Register rs1, Register rs2);
+ void srl(Register rd, Register rs1, Register rs2);
+ void sra(Register rd, Register rs1, Register rs2);
+ void or_(Register rd, Register rs1, Register rs2);
+ void and_(Register rd, Register rs1, Register rs2);
+
+ // Other pseudo instructions that are not part of RISCV pseudo assemly
+ void nor(Register rd, Register rs, Register rt) {
+ or_(rd, rs, rt);
+ not_(rd, rd);
+ }
+
+ // Memory fences
+ void fence(uint8_t pred, uint8_t succ);
+ void fence_tso();
+
+ // Environment call / break
+ void ecall();
+ void ebreak();
+
+ void sync() { fence(0b1111, 0b1111); }
+
+ // This is a de facto standard (as set by GNU binutils) 32-bit unimplemented
+ // instruction (i.e., it should always trap, if your implementation has
+ // invalid instruction traps).
+ void unimp();
+
+ static int JumpOffset(Instr instr);
+ static int AuipcOffset(Instr instr);
+ static int JalrOffset(Instr instr);
+ static int LoadOffset(Instr instr);
+ static int BranchOffset(Instr instr);
+ static int BrachlongOffset(Instr auipc, Instr instr_I);
+ static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos,
+ Instr instr) {
+ int32_t imm = target_pos - pos;
+ MOZ_ASSERT((imm & 1) == 0);
+ MOZ_ASSERT(is_intn(imm, kBranchOffsetBits));
+
+ instr &= ~kBImm12Mask;
+ int32_t imm12 = ((imm & 0x800) >> 4) | // bit 11
+ ((imm & 0x1e) << 7) | // bits 4-1
+ ((imm & 0x7e0) << 20) | // bits 10-5
+ ((imm & 0x1000) << 19); // bit 12
+
+ return instr | (imm12 & kBImm12Mask);
+ }
+
+ static inline Instr SetJalOffset(int32_t pos, int32_t target_pos,
+ Instr instr) {
+ MOZ_ASSERT(IsJal(instr));
+ int32_t imm = target_pos - pos;
+ MOZ_ASSERT((imm & 1) == 0);
+ MOZ_ASSERT(is_intn(imm, kJumpOffsetBits));
+
+ instr &= ~kImm20Mask;
+ int32_t imm20 = (imm & 0xff000) | // bits 19-12
+ ((imm & 0x800) << 9) | // bit 11
+ ((imm & 0x7fe) << 20) | // bits 10-1
+ ((imm & 0x100000) << 11); // bit 20
+
+ return instr | (imm20 & kImm20Mask);
+ }
+
+ static inline Instr SetJalrOffset(int32_t offset, Instr instr) {
+ MOZ_ASSERT(IsJalr(instr));
+ MOZ_ASSERT(is_int12(offset));
+ instr &= ~kImm12Mask;
+ int32_t imm12 = offset << kImm12Shift;
+ MOZ_ASSERT(IsJalr(instr | (imm12 & kImm12Mask)));
+ MOZ_ASSERT(JalrOffset(instr | (imm12 & kImm12Mask)) == offset);
+ return instr | (imm12 & kImm12Mask);
+ }
+
+ static inline Instr SetLoadOffset(int32_t offset, Instr instr) {
+#if JS_CODEGEN_RISCV64
+ MOZ_ASSERT(IsLd(instr));
+#elif JS_CODEGEN_RISCV32
+ MOZ_ASSERT(IsLw(instr));
+#endif
+ MOZ_ASSERT(is_int12(offset));
+ instr &= ~kImm12Mask;
+ int32_t imm12 = offset << kImm12Shift;
+ return instr | (imm12 & kImm12Mask);
+ }
+
+ static inline Instr SetAuipcOffset(int32_t offset, Instr instr) {
+ MOZ_ASSERT(IsAuipc(instr));
+ MOZ_ASSERT(is_int20(offset));
+ instr = (instr & ~kImm31_12Mask) | ((offset & kImm19_0Mask) << 12);
+ return instr;
+ }
+
+ // Check if an instruction is a branch of some kind.
+ static bool IsBranch(Instr instr);
+ static bool IsNop(Instr instr);
+ static bool IsJump(Instr instr);
+ static bool IsJal(Instr instr);
+ static bool IsJalr(Instr instr);
+ static bool IsLui(Instr instr);
+ static bool IsAuipc(Instr instr);
+ static bool IsAddi(Instr instr);
+ static bool IsOri(Instr instr);
+ static bool IsSlli(Instr instr);
+ static bool IsLw(Instr instr);
+
+ inline int32_t branch_offset(Label* L) {
+ return branch_offset_helper(L, OffsetSize::kOffset13);
+ }
+ inline int32_t jump_offset(Label* L) {
+ return branch_offset_helper(L, OffsetSize::kOffset21);
+ }
+
+ // Branches
+ void beq(Register rs1, Register rs2, Label* L) {
+ beq(rs1, rs2, branch_offset(L));
+ }
+ void bne(Register rs1, Register rs2, Label* L) {
+ bne(rs1, rs2, branch_offset(L));
+ }
+ void blt(Register rs1, Register rs2, Label* L) {
+ blt(rs1, rs2, branch_offset(L));
+ }
+ void bge(Register rs1, Register rs2, Label* L) {
+ bge(rs1, rs2, branch_offset(L));
+ }
+ void bltu(Register rs1, Register rs2, Label* L) {
+ bltu(rs1, rs2, branch_offset(L));
+ }
+ void bgeu(Register rs1, Register rs2, Label* L) {
+ bgeu(rs1, rs2, branch_offset(L));
+ }
+
+ void beqz(Register rs, int16_t imm13) { beq(rs, zero_reg, imm13); }
+ void beqz(Register rs1, Label* L) { beqz(rs1, branch_offset(L)); }
+ void bnez(Register rs, int16_t imm13) { bne(rs, zero_reg, imm13); }
+ void bnez(Register rs1, Label* L) { bnez(rs1, branch_offset(L)); }
+ void blez(Register rs, int16_t imm13) { bge(zero_reg, rs, imm13); }
+ void blez(Register rs1, Label* L) { blez(rs1, branch_offset(L)); }
+ void bgez(Register rs, int16_t imm13) { bge(rs, zero_reg, imm13); }
+ void bgez(Register rs1, Label* L) { bgez(rs1, branch_offset(L)); }
+ void bltz(Register rs, int16_t imm13) { blt(rs, zero_reg, imm13); }
+ void bltz(Register rs1, Label* L) { bltz(rs1, branch_offset(L)); }
+ void bgtz(Register rs, int16_t imm13) { blt(zero_reg, rs, imm13); }
+
+ void bgtz(Register rs1, Label* L) { bgtz(rs1, branch_offset(L)); }
+ void bgt(Register rs1, Register rs2, int16_t imm13) { blt(rs2, rs1, imm13); }
+ void bgt(Register rs1, Register rs2, Label* L) {
+ bgt(rs1, rs2, branch_offset(L));
+ }
+ void ble(Register rs1, Register rs2, int16_t imm13) { bge(rs2, rs1, imm13); }
+ void ble(Register rs1, Register rs2, Label* L) {
+ ble(rs1, rs2, branch_offset(L));
+ }
+ void bgtu(Register rs1, Register rs2, int16_t imm13) {
+ bltu(rs2, rs1, imm13);
+ }
+ void bgtu(Register rs1, Register rs2, Label* L) {
+ bgtu(rs1, rs2, branch_offset(L));
+ }
+ void bleu(Register rs1, Register rs2, int16_t imm13) {
+ bgeu(rs2, rs1, imm13);
+ }
+ void bleu(Register rs1, Register rs2, Label* L) {
+ bleu(rs1, rs2, branch_offset(L));
+ }
+
+ void j(int32_t imm21) { jal(zero_reg, imm21); }
+ void j(Label* L) { j(jump_offset(L)); }
+ void b(Label* L) { j(L); }
+ void jal(int32_t imm21) { jal(ra, imm21); }
+ void jal(Label* L) { jal(jump_offset(L)); }
+ void jr(Register rs) { jalr(zero_reg, rs, 0); }
+ void jr(Register rs, int32_t imm12) { jalr(zero_reg, rs, imm12); }
+ void jalr(Register rs, int32_t imm12) { jalr(ra, rs, imm12); }
+ void jalr(Register rs) { jalr(ra, rs, 0); }
+ void call(int32_t offset) {
+ auipc(ra, (offset >> 12) + ((offset & 0x800) >> 11));
+ jalr(ra, ra, offset << 20 >> 20);
+ }
+
+ void mv(Register rd, Register rs) { addi(rd, rs, 0); }
+ void not_(Register rd, Register rs) { xori(rd, rs, -1); }
+ void neg(Register rd, Register rs) { sub(rd, zero_reg, rs); }
+ void seqz(Register rd, Register rs) { sltiu(rd, rs, 1); }
+ void snez(Register rd, Register rs) { sltu(rd, zero_reg, rs); }
+ void sltz(Register rd, Register rs) { slt(rd, rs, zero_reg); }
+ void sgtz(Register rd, Register rs) { slt(rd, zero_reg, rs); }
+
+#if JS_CODEGEN_RISCV64
+ void lwu(Register rd, Register rs1, int16_t imm12);
+ void ld(Register rd, Register rs1, int16_t imm12);
+ void sd(Register source, Register base, int16_t imm12);
+ void addiw(Register rd, Register rs1, int16_t imm12);
+ void slliw(Register rd, Register rs1, uint8_t shamt);
+ void srliw(Register rd, Register rs1, uint8_t shamt);
+ void sraiw(Register rd, Register rs1, uint8_t shamt);
+ void addw(Register rd, Register rs1, Register rs2);
+ void subw(Register rd, Register rs1, Register rs2);
+ void sllw(Register rd, Register rs1, Register rs2);
+ void srlw(Register rd, Register rs1, Register rs2);
+ void sraw(Register rd, Register rs1, Register rs2);
+ void negw(Register rd, Register rs) { subw(rd, zero_reg, rs); }
+ void sext_w(Register rd, Register rs) { addiw(rd, rs, 0); }
+
+ static bool IsAddiw(Instr instr);
+ static bool IsLd(Instr instr);
+#endif
+};
+
+} // namespace jit
+} // namespace js
+
+#endif // jit_riscv64_extension_Base_riscv_I_h_