• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // - Redistribution in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 //
15 // - Neither the name of Sun Microsystems or the names of contributors may
16 // be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // The original source code covered by the above license above has been
32 // modified significantly by Google Inc.
33 // Copyright 2021 the V8 project authors. All rights reserved.
34 
35 #ifndef V8_CODEGEN_RISCV64_ASSEMBLER_RISCV64_H_
36 #define V8_CODEGEN_RISCV64_ASSEMBLER_RISCV64_H_
37 
38 #include <stdio.h>
39 
40 #include <memory>
41 #include <set>
42 
43 #include "src/codegen/assembler.h"
44 #include "src/codegen/constant-pool.h"
45 #include "src/codegen/external-reference.h"
46 #include "src/codegen/label.h"
47 #include "src/codegen/riscv64/constants-riscv64.h"
48 #include "src/codegen/riscv64/register-riscv64.h"
49 #include "src/objects/contexts.h"
50 #include "src/objects/smi.h"
51 
52 namespace v8 {
53 namespace internal {
54 
55 #define DEBUG_PRINTF(...) \
56   if (FLAG_riscv_debug) { \
57     printf(__VA_ARGS__);  \
58   }
59 
60 class SafepointTableBuilder;
61 
62 // -----------------------------------------------------------------------------
63 // Machine instruction Operands.
64 constexpr int kSmiShift = kSmiTagSize + kSmiShiftSize;
65 constexpr uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
66 // Class Operand represents a shifter operand in data processing instructions.
67 class Operand {
68  public:
69   // Immediate.
70   V8_INLINE explicit Operand(int64_t immediate,
71                              RelocInfo::Mode rmode = RelocInfo::NO_INFO)
rm_(no_reg)72       : rm_(no_reg), rmode_(rmode) {
73     value_.immediate = immediate;
74   }
Operand(const ExternalReference & f)75   V8_INLINE explicit Operand(const ExternalReference& f)
76       : rm_(no_reg), rmode_(RelocInfo::EXTERNAL_REFERENCE) {
77     value_.immediate = static_cast<int64_t>(f.address());
78   }
79   V8_INLINE explicit Operand(const char* s);
80   explicit Operand(Handle<HeapObject> handle);
Operand(Smi value)81   V8_INLINE explicit Operand(Smi value)
82       : rm_(no_reg), rmode_(RelocInfo::NO_INFO) {
83     value_.immediate = static_cast<intptr_t>(value.ptr());
84   }
85 
86   static Operand EmbeddedNumber(double number);  // Smi or HeapNumber.
87   static Operand EmbeddedStringConstant(const StringConstantBase* str);
88 
89   // Register.
Operand(Register rm)90   V8_INLINE explicit Operand(Register rm) : rm_(rm) {}
91 
92   // Return true if this is a register operand.
93   V8_INLINE bool is_reg() const;
94 
95   inline int64_t immediate() const;
96 
IsImmediate()97   bool IsImmediate() const { return !rm_.is_valid(); }
98 
heap_object_request()99   HeapObjectRequest heap_object_request() const {
100     DCHECK(IsHeapObjectRequest());
101     return value_.heap_object_request;
102   }
103 
IsHeapObjectRequest()104   bool IsHeapObjectRequest() const {
105     DCHECK_IMPLIES(is_heap_object_request_, IsImmediate());
106     DCHECK_IMPLIES(is_heap_object_request_,
107                    rmode_ == RelocInfo::FULL_EMBEDDED_OBJECT ||
108                        rmode_ == RelocInfo::CODE_TARGET);
109     return is_heap_object_request_;
110   }
111 
rm()112   Register rm() const { return rm_; }
113 
rmode()114   RelocInfo::Mode rmode() const { return rmode_; }
115 
116  private:
117   Register rm_;
118   union Value {
Value()119     Value() {}
120     HeapObjectRequest heap_object_request;  // if is_heap_object_request_
121     int64_t immediate;                      // otherwise
122   } value_;                                 // valid if rm_ == no_reg
123   bool is_heap_object_request_ = false;
124   RelocInfo::Mode rmode_;
125 
126   friend class Assembler;
127   friend class MacroAssembler;
128 };
129 
130 // On RISC-V we have only one addressing mode with base_reg + offset.
131 // Class MemOperand represents a memory operand in load and store instructions.
132 class V8_EXPORT_PRIVATE MemOperand : public Operand {
133  public:
134   // Immediate value attached to offset.
135   enum OffsetAddend { offset_minus_one = -1, offset_zero = 0 };
136 
137   explicit MemOperand(Register rn, int32_t offset = 0);
138   explicit MemOperand(Register rn, int32_t unit, int32_t multiplier,
139                       OffsetAddend offset_addend = offset_zero);
offset()140   int32_t offset() const { return offset_; }
141 
OffsetIsInt12Encodable()142   bool OffsetIsInt12Encodable() const { return is_int12(offset_); }
143 
144  private:
145   int32_t offset_;
146 
147   friend class Assembler;
148 };
149 
150 class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
151  public:
152   // Create an assembler. Instructions and relocation information are emitted
153   // into a buffer, with the instructions starting from the beginning and the
154   // relocation information starting from the end of the buffer. See CodeDesc
155   // for a detailed comment on the layout (globals.h).
156   //
157   // If the provided buffer is nullptr, the assembler allocates and grows its
158   // own buffer. Otherwise it takes ownership of the provided buffer.
159   explicit Assembler(const AssemblerOptions&,
160                      std::unique_ptr<AssemblerBuffer> = {});
161 
162   virtual ~Assembler();
163   void AbortedCodeGeneration();
164   // GetCode emits any pending (non-emitted) code and fills the descriptor desc.
165   static constexpr int kNoHandlerTable = 0;
166   static constexpr SafepointTableBuilder* kNoSafepointTable = nullptr;
167   void GetCode(Isolate* isolate, CodeDesc* desc,
168                SafepointTableBuilder* safepoint_table_builder,
169                int handler_table_offset);
170 
171   // Convenience wrapper for code without safepoint or handler tables.
GetCode(Isolate * isolate,CodeDesc * desc)172   void GetCode(Isolate* isolate, CodeDesc* desc) {
173     GetCode(isolate, desc, kNoSafepointTable, kNoHandlerTable);
174   }
175 
176   // Unused on this architecture.
MaybeEmitOutOfLineConstantPool()177   void MaybeEmitOutOfLineConstantPool() {}
178 
179   // Label operations & relative jumps (PPUM Appendix D).
180   //
181   // Takes a branch opcode (cc) and a label (L) and generates
182   // either a backward branch or a forward branch and links it
183   // to the label fixup chain. Usage:
184   //
185   // Label L;    // unbound label
186   // j(cc, &L);  // forward branch to unbound label
187   // bind(&L);   // bind label to the current pc
188   // j(cc, &L);  // backward branch to bound label
189   // bind(&L);   // illegal: a label may be bound only once
190   //
191   // Note: The same Label can be used for forward and backward branches
192   // but it may be bound only once.
193   void bind(Label* L);  // Binds an unbound label L to current code position.
194 
195   enum OffsetSize : int {
196     kOffset21 = 21,  // RISCV jal
197     kOffset12 = 12,  // RISCV imm12
198     kOffset20 = 20,  // RISCV imm20
199     kOffset13 = 13,  // RISCV branch
200     kOffset32 = 32,  // RISCV auipc + instr_I
201     kOffset11 = 11,  // RISCV C_J
202     kOffset8 = 8     // RISCV compressed branch
203   };
204 
205   // Determines if Label is bound and near enough so that branch instruction
206   // can be used to reach it, instead of jump instruction.
207   bool is_near(Label* L);
208   bool is_near(Label* L, OffsetSize bits);
209   bool is_near_branch(Label* L);
210 
211   // Get offset from instr.
212   int BranchOffset(Instr instr);
213   static int BrachlongOffset(Instr auipc, Instr jalr);
214   static int PatchBranchlongOffset(Address pc, Instr auipc, Instr instr_I,
215                                    int32_t offset);
216   int JumpOffset(Instr instr);
217   int CJumpOffset(Instr instr);
218   int CBranchOffset(Instr instr);
219   static int LdOffset(Instr instr);
220   static int AuipcOffset(Instr instr);
221   static int JalrOffset(Instr instr);
222 
223   // Returns the branch offset to the given label from the current code
224   // position. Links the label to the current position if it is still unbound.
225   // Manages the jump elimination optimization if the second parameter is true.
226   int32_t branch_offset_helper(Label* L, OffsetSize bits);
branch_offset(Label * L)227   inline int32_t branch_offset(Label* L) {
228     return branch_offset_helper(L, OffsetSize::kOffset13);
229   }
jump_offset(Label * L)230   inline int32_t jump_offset(Label* L) {
231     return branch_offset_helper(L, OffsetSize::kOffset21);
232   }
cjump_offset(Label * L)233   inline int16_t cjump_offset(Label* L) {
234     return (int16_t)branch_offset_helper(L, OffsetSize::kOffset11);
235   }
cbranch_offset(Label * L)236   inline int32_t cbranch_offset(Label* L) {
237     return branch_offset_helper(L, OffsetSize::kOffset8);
238   }
239 
240   uint64_t jump_address(Label* L);
241   uint64_t branch_long_offset(Label* L);
242 
243   // Puts a labels target address at the given position.
244   // The high 8 bits are set to zero.
245   void label_at_put(Label* L, int at_offset);
246 
247   // Read/Modify the code target address in the branch/call instruction at pc.
248   // The isolate argument is unused (and may be nullptr) when skipping flushing.
249   static Address target_address_at(Address pc);
250   V8_INLINE static void set_target_address_at(
251       Address pc, Address target,
252       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED) {
253     set_target_value_at(pc, target, icache_flush_mode);
254   }
255 
256   static Address target_address_at(Address pc, Address constant_pool);
257 
258   static void set_target_address_at(
259       Address pc, Address constant_pool, Address target,
260       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
261 
262   // Read/Modify the code target address in the branch/call instruction at pc.
263   inline static Tagged_t target_compressed_address_at(Address pc,
264                                                       Address constant_pool);
265   inline static void set_target_compressed_address_at(
266       Address pc, Address constant_pool, Tagged_t target,
267       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
268 
269   inline Handle<Object> code_target_object_handle_at(Address pc,
270                                                      Address constant_pool);
271   inline Handle<HeapObject> compressed_embedded_object_handle_at(
272       Address pc, Address constant_pool);
273 
274   static bool IsConstantPoolAt(Instruction* instr);
275   static int ConstantPoolSizeAt(Instruction* instr);
276   // See Assembler::CheckConstPool for more info.
277   void EmitPoolGuard();
278 
279   static void set_target_value_at(
280       Address pc, uint64_t target,
281       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
282 
283   static void JumpLabelToJumpRegister(Address pc);
284 
285   // This sets the branch destination (which gets loaded at the call address).
286   // This is for calls and branches within generated code.  The serializer
287   // has already deserialized the lui/ori instructions etc.
288   inline static void deserialization_set_special_target_at(
289       Address instruction_payload, Code code, Address target);
290 
291   // Get the size of the special target encoded at 'instruction_payload'.
292   inline static int deserialization_special_target_size(
293       Address instruction_payload);
294 
295   // This sets the internal reference at the pc.
296   inline static void deserialization_set_target_internal_reference_at(
297       Address pc, Address target,
298       RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
299 
300   // Difference between address of current opcode and target address offset.
301   static constexpr int kBranchPCOffset = kInstrSize;
302 
303   // Difference between address of current opcode and target address offset,
304   // when we are generatinga sequence of instructions for long relative PC
305   // branches
306   static constexpr int kLongBranchPCOffset = 3 * kInstrSize;
307 
308   // Adjust ra register in branch delay slot of bal instruction so to skip
309   // instructions not needed after optimization of PIC in
310   // TurboAssembler::BranchAndLink method.
311 
312   static constexpr int kOptimizedBranchAndLinkLongReturnOffset = 4 * kInstrSize;
313 
314   // Here we are patching the address in the LUI/ADDI instruction pair.
315   // These values are used in the serialization process and must be zero for
316   // RISC-V platform, as Code, Embedded Object or External-reference pointers
317   // are split across two consecutive instructions and don't exist separately
318   // in the code, so the serializer should not step forwards in memory after
319   // a target is resolved and written.
320   static constexpr int kSpecialTargetSize = 0;
321 
322   // Number of consecutive instructions used to store 32bit/64bit constant.
323   // This constant was used in RelocInfo::target_address_address() function
324   // to tell serializer address of the instruction that follows
325   // LUI/ADDI instruction pair.
326   static constexpr int kInstructionsFor32BitConstant = 2;
327   static constexpr int kInstructionsFor64BitConstant = 8;
328 
329   // Difference between address of current opcode and value read from pc
330   // register.
331   static constexpr int kPcLoadDelta = 4;
332 
333   // Bits available for offset field in branches
334   static constexpr int kBranchOffsetBits = 13;
335 
336   // Bits available for offset field in jump
337   static constexpr int kJumpOffsetBits = 21;
338 
339   // Bits available for offset field in compresed jump
340   static constexpr int kCJalOffsetBits = 12;
341 
342   // Bits available for offset field in compressed branch
343   static constexpr int kCBranchOffsetBits = 9;
344 
345   // Max offset for b instructions with 12-bit offset field (multiple of 2)
346   static constexpr int kMaxBranchOffset = (1 << (13 - 1)) - 1;
347 
348   // Max offset for jal instruction with 20-bit offset field (multiple of 2)
349   static constexpr int kMaxJumpOffset = (1 << (21 - 1)) - 1;
350 
351   static constexpr int kTrampolineSlotsSize = 2 * kInstrSize;
352 
GetScratchRegisterList()353   RegList* GetScratchRegisterList() { return &scratch_register_list_; }
354 
355   // ---------------------------------------------------------------------------
356   // Code generation.
357 
358   // Insert the smallest number of nop instructions
359   // possible to align the pc offset to a multiple
360   // of m. m must be a power of 2 (>= 4).
361   void Align(int m);
362   // Insert the smallest number of zero bytes possible to align the pc offset
363   // to a mulitple of m. m must be a power of 2 (>= 2).
364   void DataAlign(int m);
365   // Aligns code to something that's optimal for a jump target for the platform.
366   void CodeTargetAlign();
LoopHeaderAlign()367   void LoopHeaderAlign() { CodeTargetAlign(); }
368 
369   // Different nop operations are used by the code generator to detect certain
370   // states of the generated code.
371   enum NopMarkerTypes {
372     NON_MARKING_NOP = 0,
373     DEBUG_BREAK_NOP,
374     // IC markers.
375     PROPERTY_ACCESS_INLINED,
376     PROPERTY_ACCESS_INLINED_CONTEXT,
377     PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
378     // Helper values.
379     LAST_CODE_MARKER,
380     FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED,
381   };
382 
383   // RISC-V Instructions Emited to a buffer
384 
385   void lui(Register rd, int32_t imm20);
386   void auipc(Register rd, int32_t imm20);
387 
388   // Jumps
389   void jal(Register rd, int32_t imm20);
390   void jalr(Register rd, Register rs1, int16_t imm12);
391 
392   // Branches
393   void beq(Register rs1, Register rs2, int16_t imm12);
beq(Register rs1,Register rs2,Label * L)394   inline void beq(Register rs1, Register rs2, Label* L) {
395     beq(rs1, rs2, branch_offset(L));
396   }
397   void bne(Register rs1, Register rs2, int16_t imm12);
bne(Register rs1,Register rs2,Label * L)398   inline void bne(Register rs1, Register rs2, Label* L) {
399     bne(rs1, rs2, branch_offset(L));
400   }
401   void blt(Register rs1, Register rs2, int16_t imm12);
blt(Register rs1,Register rs2,Label * L)402   inline void blt(Register rs1, Register rs2, Label* L) {
403     blt(rs1, rs2, branch_offset(L));
404   }
405   void bge(Register rs1, Register rs2, int16_t imm12);
bge(Register rs1,Register rs2,Label * L)406   inline void bge(Register rs1, Register rs2, Label* L) {
407     bge(rs1, rs2, branch_offset(L));
408   }
409   void bltu(Register rs1, Register rs2, int16_t imm12);
bltu(Register rs1,Register rs2,Label * L)410   inline void bltu(Register rs1, Register rs2, Label* L) {
411     bltu(rs1, rs2, branch_offset(L));
412   }
413   void bgeu(Register rs1, Register rs2, int16_t imm12);
bgeu(Register rs1,Register rs2,Label * L)414   inline void bgeu(Register rs1, Register rs2, Label* L) {
415     bgeu(rs1, rs2, branch_offset(L));
416   }
417 
418   // Loads
419   void lb(Register rd, Register rs1, int16_t imm12);
420   void lh(Register rd, Register rs1, int16_t imm12);
421   void lw(Register rd, Register rs1, int16_t imm12);
422   void lbu(Register rd, Register rs1, int16_t imm12);
423   void lhu(Register rd, Register rs1, int16_t imm12);
424 
425   // Stores
426   void sb(Register source, Register base, int16_t imm12);
427   void sh(Register source, Register base, int16_t imm12);
428   void sw(Register source, Register base, int16_t imm12);
429 
430   // Arithmetic with immediate
431   void addi(Register rd, Register rs1, int16_t imm12);
432   void slti(Register rd, Register rs1, int16_t imm12);
433   void sltiu(Register rd, Register rs1, int16_t imm12);
434   void xori(Register rd, Register rs1, int16_t imm12);
435   void ori(Register rd, Register rs1, int16_t imm12);
436   void andi(Register rd, Register rs1, int16_t imm12);
437   void slli(Register rd, Register rs1, uint8_t shamt);
438   void srli(Register rd, Register rs1, uint8_t shamt);
439   void srai(Register rd, Register rs1, uint8_t shamt);
440 
441   // Arithmetic
442   void add(Register rd, Register rs1, Register rs2);
443   void sub(Register rd, Register rs1, Register rs2);
444   void sll(Register rd, Register rs1, Register rs2);
445   void slt(Register rd, Register rs1, Register rs2);
446   void sltu(Register rd, Register rs1, Register rs2);
447   void xor_(Register rd, Register rs1, Register rs2);
448   void srl(Register rd, Register rs1, Register rs2);
449   void sra(Register rd, Register rs1, Register rs2);
450   void or_(Register rd, Register rs1, Register rs2);
451   void and_(Register rd, Register rs1, Register rs2);
452 
453   // Memory fences
454   void fence(uint8_t pred, uint8_t succ);
455   void fence_tso();
456 
457   // Environment call / break
458   void ecall();
459   void ebreak();
460 
461   // This is a de facto standard (as set by GNU binutils) 32-bit unimplemented
462   // instruction (i.e., it should always trap, if your implementation has
463   // invalid instruction traps).
464   void unimp();
465 
466   // CSR
467   void csrrw(Register rd, ControlStatusReg csr, Register rs1);
468   void csrrs(Register rd, ControlStatusReg csr, Register rs1);
469   void csrrc(Register rd, ControlStatusReg csr, Register rs1);
470   void csrrwi(Register rd, ControlStatusReg csr, uint8_t imm5);
471   void csrrsi(Register rd, ControlStatusReg csr, uint8_t imm5);
472   void csrrci(Register rd, ControlStatusReg csr, uint8_t imm5);
473 
474   // RV64I
475   void lwu(Register rd, Register rs1, int16_t imm12);
476   void ld(Register rd, Register rs1, int16_t imm12);
477   void sd(Register source, Register base, int16_t imm12);
478   void addiw(Register rd, Register rs1, int16_t imm12);
479   void slliw(Register rd, Register rs1, uint8_t shamt);
480   void srliw(Register rd, Register rs1, uint8_t shamt);
481   void sraiw(Register rd, Register rs1, uint8_t shamt);
482   void addw(Register rd, Register rs1, Register rs2);
483   void subw(Register rd, Register rs1, Register rs2);
484   void sllw(Register rd, Register rs1, Register rs2);
485   void srlw(Register rd, Register rs1, Register rs2);
486   void sraw(Register rd, Register rs1, Register rs2);
487 
488   // RV32M Standard Extension
489   void mul(Register rd, Register rs1, Register rs2);
490   void mulh(Register rd, Register rs1, Register rs2);
491   void mulhsu(Register rd, Register rs1, Register rs2);
492   void mulhu(Register rd, Register rs1, Register rs2);
493   void div(Register rd, Register rs1, Register rs2);
494   void divu(Register rd, Register rs1, Register rs2);
495   void rem(Register rd, Register rs1, Register rs2);
496   void remu(Register rd, Register rs1, Register rs2);
497 
498   // RV64M Standard Extension (in addition to RV32M)
499   void mulw(Register rd, Register rs1, Register rs2);
500   void divw(Register rd, Register rs1, Register rs2);
501   void divuw(Register rd, Register rs1, Register rs2);
502   void remw(Register rd, Register rs1, Register rs2);
503   void remuw(Register rd, Register rs1, Register rs2);
504 
505   // RV32A Standard Extension
506   void lr_w(bool aq, bool rl, Register rd, Register rs1);
507   void sc_w(bool aq, bool rl, Register rd, Register rs1, Register rs2);
508   void amoswap_w(bool aq, bool rl, Register rd, Register rs1, Register rs2);
509   void amoadd_w(bool aq, bool rl, Register rd, Register rs1, Register rs2);
510   void amoxor_w(bool aq, bool rl, Register rd, Register rs1, Register rs2);
511   void amoand_w(bool aq, bool rl, Register rd, Register rs1, Register rs2);
512   void amoor_w(bool aq, bool rl, Register rd, Register rs1, Register rs2);
513   void amomin_w(bool aq, bool rl, Register rd, Register rs1, Register rs2);
514   void amomax_w(bool aq, bool rl, Register rd, Register rs1, Register rs2);
515   void amominu_w(bool aq, bool rl, Register rd, Register rs1, Register rs2);
516   void amomaxu_w(bool aq, bool rl, Register rd, Register rs1, Register rs2);
517 
518   // RV64A Standard Extension (in addition to RV32A)
519   void lr_d(bool aq, bool rl, Register rd, Register rs1);
520   void sc_d(bool aq, bool rl, Register rd, Register rs1, Register rs2);
521   void amoswap_d(bool aq, bool rl, Register rd, Register rs1, Register rs2);
522   void amoadd_d(bool aq, bool rl, Register rd, Register rs1, Register rs2);
523   void amoxor_d(bool aq, bool rl, Register rd, Register rs1, Register rs2);
524   void amoand_d(bool aq, bool rl, Register rd, Register rs1, Register rs2);
525   void amoor_d(bool aq, bool rl, Register rd, Register rs1, Register rs2);
526   void amomin_d(bool aq, bool rl, Register rd, Register rs1, Register rs2);
527   void amomax_d(bool aq, bool rl, Register rd, Register rs1, Register rs2);
528   void amominu_d(bool aq, bool rl, Register rd, Register rs1, Register rs2);
529   void amomaxu_d(bool aq, bool rl, Register rd, Register rs1, Register rs2);
530 
531   // RV32F Standard Extension
532   void flw(FPURegister rd, Register rs1, int16_t imm12);
533   void fsw(FPURegister source, Register base, int16_t imm12);
534   void fmadd_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
535                FPURegister rs3, RoundingMode frm = RNE);
536   void fmsub_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
537                FPURegister rs3, RoundingMode frm = RNE);
538   void fnmsub_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
539                 FPURegister rs3, RoundingMode frm = RNE);
540   void fnmadd_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
541                 FPURegister rs3, RoundingMode frm = RNE);
542   void fadd_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
543               RoundingMode frm = RNE);
544   void fsub_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
545               RoundingMode frm = RNE);
546   void fmul_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
547               RoundingMode frm = RNE);
548   void fdiv_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
549               RoundingMode frm = RNE);
550   void fsqrt_s(FPURegister rd, FPURegister rs1, RoundingMode frm = RNE);
551   void fsgnj_s(FPURegister rd, FPURegister rs1, FPURegister rs2);
552   void fsgnjn_s(FPURegister rd, FPURegister rs1, FPURegister rs2);
553   void fsgnjx_s(FPURegister rd, FPURegister rs1, FPURegister rs2);
554   void fmin_s(FPURegister rd, FPURegister rs1, FPURegister rs2);
555   void fmax_s(FPURegister rd, FPURegister rs1, FPURegister rs2);
556   void fcvt_w_s(Register rd, FPURegister rs1, RoundingMode frm = RNE);
557   void fcvt_wu_s(Register rd, FPURegister rs1, RoundingMode frm = RNE);
558   void fmv_x_w(Register rd, FPURegister rs1);
559   void feq_s(Register rd, FPURegister rs1, FPURegister rs2);
560   void flt_s(Register rd, FPURegister rs1, FPURegister rs2);
561   void fle_s(Register rd, FPURegister rs1, FPURegister rs2);
562   void fclass_s(Register rd, FPURegister rs1);
563   void fcvt_s_w(FPURegister rd, Register rs1, RoundingMode frm = RNE);
564   void fcvt_s_wu(FPURegister rd, Register rs1, RoundingMode frm = RNE);
565   void fmv_w_x(FPURegister rd, Register rs1);
566 
567   // RV64F Standard Extension (in addition to RV32F)
568   void fcvt_l_s(Register rd, FPURegister rs1, RoundingMode frm = RNE);
569   void fcvt_lu_s(Register rd, FPURegister rs1, RoundingMode frm = RNE);
570   void fcvt_s_l(FPURegister rd, Register rs1, RoundingMode frm = RNE);
571   void fcvt_s_lu(FPURegister rd, Register rs1, RoundingMode frm = RNE);
572 
573   // RV32D Standard Extension
574   void fld(FPURegister rd, Register rs1, int16_t imm12);
575   void fsd(FPURegister source, Register base, int16_t imm12);
576   void fmadd_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
577                FPURegister rs3, RoundingMode frm = RNE);
578   void fmsub_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
579                FPURegister rs3, RoundingMode frm = RNE);
580   void fnmsub_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
581                 FPURegister rs3, RoundingMode frm = RNE);
582   void fnmadd_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
583                 FPURegister rs3, RoundingMode frm = RNE);
584   void fadd_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
585               RoundingMode frm = RNE);
586   void fsub_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
587               RoundingMode frm = RNE);
588   void fmul_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
589               RoundingMode frm = RNE);
590   void fdiv_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
591               RoundingMode frm = RNE);
592   void fsqrt_d(FPURegister rd, FPURegister rs1, RoundingMode frm = RNE);
593   void fsgnj_d(FPURegister rd, FPURegister rs1, FPURegister rs2);
594   void fsgnjn_d(FPURegister rd, FPURegister rs1, FPURegister rs2);
595   void fsgnjx_d(FPURegister rd, FPURegister rs1, FPURegister rs2);
596   void fmin_d(FPURegister rd, FPURegister rs1, FPURegister rs2);
597   void fmax_d(FPURegister rd, FPURegister rs1, FPURegister rs2);
598   void fcvt_s_d(FPURegister rd, FPURegister rs1, RoundingMode frm = RNE);
599   void fcvt_d_s(FPURegister rd, FPURegister rs1, RoundingMode frm = RNE);
600   void feq_d(Register rd, FPURegister rs1, FPURegister rs2);
601   void flt_d(Register rd, FPURegister rs1, FPURegister rs2);
602   void fle_d(Register rd, FPURegister rs1, FPURegister rs2);
603   void fclass_d(Register rd, FPURegister rs1);
604   void fcvt_w_d(Register rd, FPURegister rs1, RoundingMode frm = RNE);
605   void fcvt_wu_d(Register rd, FPURegister rs1, RoundingMode frm = RNE);
606   void fcvt_d_w(FPURegister rd, Register rs1, RoundingMode frm = RNE);
607   void fcvt_d_wu(FPURegister rd, Register rs1, RoundingMode frm = RNE);
608 
609   // RV64D Standard Extension (in addition to RV32D)
610   void fcvt_l_d(Register rd, FPURegister rs1, RoundingMode frm = RNE);
611   void fcvt_lu_d(Register rd, FPURegister rs1, RoundingMode frm = RNE);
612   void fmv_x_d(Register rd, FPURegister rs1);
613   void fcvt_d_l(FPURegister rd, Register rs1, RoundingMode frm = RNE);
614   void fcvt_d_lu(FPURegister rd, Register rs1, RoundingMode frm = RNE);
615   void fmv_d_x(FPURegister rd, Register rs1);
616 
617   // RV64C Standard Extension
618   void c_nop();
619   void c_addi(Register rd, int8_t imm6);
620   void c_addiw(Register rd, int8_t imm6);
621   void c_addi16sp(int16_t imm10);
622   void c_addi4spn(Register rd, int16_t uimm10);
623   void c_li(Register rd, int8_t imm6);
624   void c_lui(Register rd, int8_t imm6);
625   void c_slli(Register rd, uint8_t shamt6);
626   void c_fldsp(FPURegister rd, uint16_t uimm9);
627   void c_lwsp(Register rd, uint16_t uimm8);
628   void c_ldsp(Register rd, uint16_t uimm9);
629   void c_jr(Register rs1);
630   void c_mv(Register rd, Register rs2);
631   void c_ebreak();
632   void c_jalr(Register rs1);
633   void c_j(int16_t imm12);
c_j(Label * L)634   inline void c_j(Label* L) { c_j(cjump_offset(L)); }
635   void c_add(Register rd, Register rs2);
636   void c_sub(Register rd, Register rs2);
637   void c_and(Register rd, Register rs2);
638   void c_xor(Register rd, Register rs2);
639   void c_or(Register rd, Register rs2);
640   void c_subw(Register rd, Register rs2);
641   void c_addw(Register rd, Register rs2);
642   void c_swsp(Register rs2, uint16_t uimm8);
643   void c_sdsp(Register rs2, uint16_t uimm9);
644   void c_fsdsp(FPURegister rs2, uint16_t uimm9);
645   void c_lw(Register rd, Register rs1, uint16_t uimm7);
646   void c_ld(Register rd, Register rs1, uint16_t uimm8);
647   void c_fld(FPURegister rd, Register rs1, uint16_t uimm8);
648   void c_sw(Register rs2, Register rs1, uint16_t uimm7);
649   void c_sd(Register rs2, Register rs1, uint16_t uimm8);
650   void c_fsd(FPURegister rs2, Register rs1, uint16_t uimm8);
651   void c_bnez(Register rs1, int16_t imm9);
c_bnez(Register rs1,Label * L)652   inline void c_bnez(Register rs1, Label* L) { c_bnez(rs1, branch_offset(L)); }
653   void c_beqz(Register rs1, int16_t imm9);
c_beqz(Register rs1,Label * L)654   inline void c_beqz(Register rs1, Label* L) { c_beqz(rs1, branch_offset(L)); }
655   void c_srli(Register rs1, int8_t shamt6);
656   void c_srai(Register rs1, int8_t shamt6);
657   void c_andi(Register rs1, int8_t imm6);
658   void NOP();
659   void EBREAK();
660 
661   // RVV
662   static int32_t GenZimm(VSew vsew, Vlmul vlmul, TailAgnosticType tail = tu,
663                          MaskAgnosticType mask = mu) {
664     return (mask << 7) | (tail << 6) | ((vsew & 0x7) << 3) | (vlmul & 0x7);
665   }
666 
667   void vl(VRegister vd, Register rs1, uint8_t lumop, VSew vsew,
668           MaskType mask = NoMask);
669   void vls(VRegister vd, Register rs1, Register rs2, VSew vsew,
670            MaskType mask = NoMask);
671   void vlx(VRegister vd, Register rs1, VRegister vs3, VSew vsew,
672            MaskType mask = NoMask);
673 
674   void vs(VRegister vd, Register rs1, uint8_t sumop, VSew vsew,
675           MaskType mask = NoMask);
676   void vss(VRegister vd, Register rs1, Register rs2, VSew vsew,
677            MaskType mask = NoMask);
678   void vsx(VRegister vd, Register rs1, VRegister vs3, VSew vsew,
679            MaskType mask = NoMask);
680 
681   void vsu(VRegister vd, Register rs1, VRegister vs3, VSew vsew,
682            MaskType mask = NoMask);
683 
684 #define SegInstr(OP)  \
685   void OP##seg2(ARG); \
686   void OP##seg3(ARG); \
687   void OP##seg4(ARG); \
688   void OP##seg5(ARG); \
689   void OP##seg6(ARG); \
690   void OP##seg7(ARG); \
691   void OP##seg8(ARG);
692 
693 #define ARG \
694   VRegister vd, Register rs1, uint8_t lumop, VSew vsew, MaskType mask = NoMask
695 
696   SegInstr(vl) SegInstr(vs)
697 #undef ARG
698 
699 #define ARG \
700   VRegister vd, Register rs1, Register rs2, VSew vsew, MaskType mask = NoMask
701 
702       SegInstr(vls) SegInstr(vss)
703 #undef ARG
704 
705 #define ARG \
706   VRegister vd, Register rs1, VRegister rs2, VSew vsew, MaskType mask = NoMask
707 
708           SegInstr(vsx) SegInstr(vlx)
709 #undef ARG
710 #undef SegInstr
711 
712   // RVV Vector Arithmetic Instruction
713 
714   void vmv_vv(VRegister vd, VRegister vs1);
715   void vmv_vx(VRegister vd, Register rs1);
716   void vmv_vi(VRegister vd, uint8_t simm5);
717   void vmv_xs(Register rd, VRegister vs2);
718   void vmv_sx(VRegister vd, Register rs1);
719   void vmerge_vv(VRegister vd, VRegister vs1, VRegister vs2);
720   void vmerge_vx(VRegister vd, Register rs1, VRegister vs2);
721   void vmerge_vi(VRegister vd, uint8_t imm5, VRegister vs2);
722 
723   void vredmaxu_vs(VRegister vd, VRegister vs2, VRegister vs1,
724                    MaskType mask = NoMask);
725   void vredmax_vs(VRegister vd, VRegister vs2, VRegister vs1,
726                   MaskType mask = NoMask);
727   void vredmin_vs(VRegister vd, VRegister vs2, VRegister vs1,
728                   MaskType mask = NoMask);
729   void vredminu_vs(VRegister vd, VRegister vs2, VRegister vs1,
730                    MaskType mask = NoMask);
731 
732   void vadc_vv(VRegister vd, VRegister vs1, VRegister vs2);
733   void vadc_vx(VRegister vd, Register rs1, VRegister vs2);
734   void vadc_vi(VRegister vd, uint8_t imm5, VRegister vs2);
735 
736   void vmadc_vv(VRegister vd, VRegister vs1, VRegister vs2);
737   void vmadc_vx(VRegister vd, Register rs1, VRegister vs2);
738   void vmadc_vi(VRegister vd, uint8_t imm5, VRegister vs2);
739 
740   void vfmv_vf(VRegister vd, FPURegister fs1, MaskType mask = NoMask);
741   void vfmv_fs(FPURegister fd, VRegister vs2);
742   void vfmv_sf(VRegister vd, FPURegister fs);
743 
744   void vwaddu_wx(VRegister vd, VRegister vs2, Register rs1,
745                  MaskType mask = NoMask);
746   void vid_v(VRegister vd, MaskType mask = Mask);
747 
748 #define DEFINE_OPIVV(name, funct6)                           \
749   void name##_vv(VRegister vd, VRegister vs2, VRegister vs1, \
750                  MaskType mask = NoMask);
751 
752 #define DEFINE_OPIVX(name, funct6)                          \
753   void name##_vx(VRegister vd, VRegister vs2, Register rs1, \
754                  MaskType mask = NoMask);
755 
756 #define DEFINE_OPIVI(name, funct6)                         \
757   void name##_vi(VRegister vd, VRegister vs2, int8_t imm5, \
758                  MaskType mask = NoMask);
759 
760 #define DEFINE_OPMVV(name, funct6)                           \
761   void name##_vv(VRegister vd, VRegister vs2, VRegister vs1, \
762                  MaskType mask = NoMask);
763 
764 #define DEFINE_OPMVX(name, funct6)                          \
765   void name##_vx(VRegister vd, VRegister vs2, Register rs1, \
766                  MaskType mask = NoMask);
767 
768 #define DEFINE_OPFVV(name, funct6)                           \
769   void name##_vv(VRegister vd, VRegister vs2, VRegister vs1, \
770                  MaskType mask = NoMask);
771 
772 #define DEFINE_OPFWV(name, funct6)                           \
773   void name##_wv(VRegister vd, VRegister vs2, VRegister vs1, \
774                  MaskType mask = NoMask);
775 
776 #define DEFINE_OPFRED(name, funct6)                          \
777   void name##_vs(VRegister vd, VRegister vs2, VRegister vs1, \
778                  MaskType mask = NoMask);
779 
780 #define DEFINE_OPFVF(name, funct6)                             \
781   void name##_vf(VRegister vd, VRegister vs2, FPURegister fs1, \
782                  MaskType mask = NoMask);
783 
784 #define DEFINE_OPFWF(name, funct6)                             \
785   void name##_wf(VRegister vd, VRegister vs2, FPURegister fs1, \
786                  MaskType mask = NoMask);
787 
788 #define DEFINE_OPFVV_FMA(name, funct6)                       \
789   void name##_vv(VRegister vd, VRegister vs1, VRegister vs2, \
790                  MaskType mask = NoMask);
791 
792 #define DEFINE_OPFVF_FMA(name, funct6)                         \
793   void name##_vf(VRegister vd, FPURegister fs1, VRegister vs2, \
794                  MaskType mask = NoMask);
795 
796 #define DEFINE_OPMVV_VIE(name) \
797   void name(VRegister vd, VRegister vs2, MaskType mask = NoMask);
798 
DEFINE_OPIVV(vadd,VADD_FUNCT6)799   DEFINE_OPIVV(vadd, VADD_FUNCT6)
800   DEFINE_OPIVX(vadd, VADD_FUNCT6)
801   DEFINE_OPIVI(vadd, VADD_FUNCT6)
802   DEFINE_OPIVV(vsub, VSUB_FUNCT6)
803   DEFINE_OPIVX(vsub, VSUB_FUNCT6)
804   DEFINE_OPMVX(vdiv, VDIV_FUNCT6)
805   DEFINE_OPMVX(vdivu, VDIVU_FUNCT6)
806   DEFINE_OPMVX(vmul, VMUL_FUNCT6)
807   DEFINE_OPMVX(vmulhu, VMULHU_FUNCT6)
808   DEFINE_OPMVX(vmulhsu, VMULHSU_FUNCT6)
809   DEFINE_OPMVX(vmulh, VMULH_FUNCT6)
810   DEFINE_OPMVV(vdiv, VDIV_FUNCT6)
811   DEFINE_OPMVV(vdivu, VDIVU_FUNCT6)
812   DEFINE_OPMVV(vmul, VMUL_FUNCT6)
813   DEFINE_OPMVV(vmulhu, VMULHU_FUNCT6)
814   DEFINE_OPMVV(vmulhsu, VMULHSU_FUNCT6)
815   DEFINE_OPMVV(vmulh, VMULH_FUNCT6)
816   DEFINE_OPMVV(vwmul, VWMUL_FUNCT6)
817   DEFINE_OPMVV(vwmulu, VWMULU_FUNCT6)
818   DEFINE_OPMVV(vwaddu, VWADDU_FUNCT6)
819   DEFINE_OPMVV(vwadd, VWADD_FUNCT6)
820   DEFINE_OPMVV(vcompress, VCOMPRESS_FUNCT6)
821   DEFINE_OPIVX(vsadd, VSADD_FUNCT6)
822   DEFINE_OPIVV(vsadd, VSADD_FUNCT6)
823   DEFINE_OPIVI(vsadd, VSADD_FUNCT6)
824   DEFINE_OPIVX(vsaddu, VSADD_FUNCT6)
825   DEFINE_OPIVV(vsaddu, VSADDU_FUNCT6)
826   DEFINE_OPIVI(vsaddu, VSADDU_FUNCT6)
827   DEFINE_OPIVX(vssub, VSSUB_FUNCT6)
828   DEFINE_OPIVV(vssub, VSSUB_FUNCT6)
829   DEFINE_OPIVX(vssubu, VSSUBU_FUNCT6)
830   DEFINE_OPIVV(vssubu, VSSUBU_FUNCT6)
831   DEFINE_OPIVX(vrsub, VRSUB_FUNCT6)
832   DEFINE_OPIVI(vrsub, VRSUB_FUNCT6)
833   DEFINE_OPIVV(vminu, VMINU_FUNCT6)
834   DEFINE_OPIVX(vminu, VMINU_FUNCT6)
835   DEFINE_OPIVV(vmin, VMIN_FUNCT6)
836   DEFINE_OPIVX(vmin, VMIN_FUNCT6)
837   DEFINE_OPIVV(vmaxu, VMAXU_FUNCT6)
838   DEFINE_OPIVX(vmaxu, VMAXU_FUNCT6)
839   DEFINE_OPIVV(vmax, VMAX_FUNCT6)
840   DEFINE_OPIVX(vmax, VMAX_FUNCT6)
841   DEFINE_OPIVV(vand, VAND_FUNCT6)
842   DEFINE_OPIVX(vand, VAND_FUNCT6)
843   DEFINE_OPIVI(vand, VAND_FUNCT6)
844   DEFINE_OPIVV(vor, VOR_FUNCT6)
845   DEFINE_OPIVX(vor, VOR_FUNCT6)
846   DEFINE_OPIVI(vor, VOR_FUNCT6)
847   DEFINE_OPIVV(vxor, VXOR_FUNCT6)
848   DEFINE_OPIVX(vxor, VXOR_FUNCT6)
849   DEFINE_OPIVI(vxor, VXOR_FUNCT6)
850   DEFINE_OPIVV(vrgather, VRGATHER_FUNCT6)
851   DEFINE_OPIVX(vrgather, VRGATHER_FUNCT6)
852   DEFINE_OPIVI(vrgather, VRGATHER_FUNCT6)
853 
854   DEFINE_OPIVX(vslidedown, VSLIDEDOWN_FUNCT6)
855   DEFINE_OPIVI(vslidedown, VSLIDEDOWN_FUNCT6)
856   DEFINE_OPIVX(vslideup, VSLIDEUP_FUNCT6)
857   DEFINE_OPIVI(vslideup, VSLIDEUP_FUNCT6)
858 
859   DEFINE_OPIVV(vmseq, VMSEQ_FUNCT6)
860   DEFINE_OPIVX(vmseq, VMSEQ_FUNCT6)
861   DEFINE_OPIVI(vmseq, VMSEQ_FUNCT6)
862 
863   DEFINE_OPIVV(vmsne, VMSNE_FUNCT6)
864   DEFINE_OPIVX(vmsne, VMSNE_FUNCT6)
865   DEFINE_OPIVI(vmsne, VMSNE_FUNCT6)
866 
867   DEFINE_OPIVV(vmsltu, VMSLTU_FUNCT6)
868   DEFINE_OPIVX(vmsltu, VMSLTU_FUNCT6)
869 
870   DEFINE_OPIVV(vmslt, VMSLT_FUNCT6)
871   DEFINE_OPIVX(vmslt, VMSLT_FUNCT6)
872 
873   DEFINE_OPIVV(vmsle, VMSLE_FUNCT6)
874   DEFINE_OPIVX(vmsle, VMSLE_FUNCT6)
875   DEFINE_OPIVI(vmsle, VMSLE_FUNCT6)
876 
877   DEFINE_OPIVV(vmsleu, VMSLEU_FUNCT6)
878   DEFINE_OPIVX(vmsleu, VMSLEU_FUNCT6)
879   DEFINE_OPIVI(vmsleu, VMSLEU_FUNCT6)
880 
881   DEFINE_OPIVI(vmsgt, VMSGT_FUNCT6)
882   DEFINE_OPIVX(vmsgt, VMSGT_FUNCT6)
883 
884   DEFINE_OPIVI(vmsgtu, VMSGTU_FUNCT6)
885   DEFINE_OPIVX(vmsgtu, VMSGTU_FUNCT6)
886 
887   DEFINE_OPIVV(vsrl, VSRL_FUNCT6)
888   DEFINE_OPIVX(vsrl, VSRL_FUNCT6)
889   DEFINE_OPIVI(vsrl, VSRL_FUNCT6)
890 
891   DEFINE_OPIVV(vsra, VSRA_FUNCT6)
892   DEFINE_OPIVX(vsra, VSRA_FUNCT6)
893   DEFINE_OPIVI(vsra, VSRA_FUNCT6)
894 
895   DEFINE_OPIVV(vsll, VSLL_FUNCT6)
896   DEFINE_OPIVX(vsll, VSLL_FUNCT6)
897   DEFINE_OPIVI(vsll, VSLL_FUNCT6)
898 
899   DEFINE_OPIVV(vsmul, VSMUL_FUNCT6)
900   DEFINE_OPIVX(vsmul, VSMUL_FUNCT6)
901 
902   DEFINE_OPFVV(vfadd, VFADD_FUNCT6)
903   DEFINE_OPFVF(vfadd, VFADD_FUNCT6)
904   DEFINE_OPFVV(vfsub, VFSUB_FUNCT6)
905   DEFINE_OPFVF(vfsub, VFSUB_FUNCT6)
906   DEFINE_OPFVV(vfdiv, VFDIV_FUNCT6)
907   DEFINE_OPFVF(vfdiv, VFDIV_FUNCT6)
908   DEFINE_OPFVV(vfmul, VFMUL_FUNCT6)
909   DEFINE_OPFVF(vfmul, VFMUL_FUNCT6)
910 
911   // Vector Widening Floating-Point Add/Subtract Instructions
912   DEFINE_OPFVV(vfwadd, VFWADD_FUNCT6)
913   DEFINE_OPFVF(vfwadd, VFWADD_FUNCT6)
914   DEFINE_OPFVV(vfwsub, VFWSUB_FUNCT6)
915   DEFINE_OPFVF(vfwsub, VFWSUB_FUNCT6)
916   DEFINE_OPFWV(vfwadd, VFWADD_W_FUNCT6)
917   DEFINE_OPFWF(vfwadd, VFWADD_W_FUNCT6)
918   DEFINE_OPFWV(vfwsub, VFWSUB_W_FUNCT6)
919   DEFINE_OPFWF(vfwsub, VFWSUB_W_FUNCT6)
920 
921   // Vector Widening Floating-Point Reduction Instructions
922   DEFINE_OPFVV(vfwredusum, VFWREDUSUM_FUNCT6)
923   DEFINE_OPFVV(vfwredosum, VFWREDOSUM_FUNCT6)
924 
925   // Vector Widening Floating-Point Multiply
926   DEFINE_OPFVV(vfwmul, VFWMUL_FUNCT6)
927   DEFINE_OPFVF(vfwmul, VFWMUL_FUNCT6)
928 
929   DEFINE_OPFVV(vmfeq, VMFEQ_FUNCT6)
930   DEFINE_OPFVV(vmfne, VMFNE_FUNCT6)
931   DEFINE_OPFVV(vmflt, VMFLT_FUNCT6)
932   DEFINE_OPFVV(vmfle, VMFLE_FUNCT6)
933   DEFINE_OPFVV(vfmax, VMFMAX_FUNCT6)
934   DEFINE_OPFVV(vfmin, VMFMIN_FUNCT6)
935   DEFINE_OPFRED(vfredmax, VFREDMAX_FUNCT6)
936 
937   DEFINE_OPFVV(vfsngj, VFSGNJ_FUNCT6)
938   DEFINE_OPFVF(vfsngj, VFSGNJ_FUNCT6)
939   DEFINE_OPFVV(vfsngjn, VFSGNJN_FUNCT6)
940   DEFINE_OPFVF(vfsngjn, VFSGNJN_FUNCT6)
941   DEFINE_OPFVV(vfsngjx, VFSGNJX_FUNCT6)
942   DEFINE_OPFVF(vfsngjx, VFSGNJX_FUNCT6)
943 
944   // Vector Single-Width Floating-Point Fused Multiply-Add Instructions
945   DEFINE_OPFVV_FMA(vfmadd, VFMADD_FUNCT6)
946   DEFINE_OPFVF_FMA(vfmadd, VFMADD_FUNCT6)
947   DEFINE_OPFVV_FMA(vfmsub, VFMSUB_FUNCT6)
948   DEFINE_OPFVF_FMA(vfmsub, VFMSUB_FUNCT6)
949   DEFINE_OPFVV_FMA(vfmacc, VFMACC_FUNCT6)
950   DEFINE_OPFVF_FMA(vfmacc, VFMACC_FUNCT6)
951   DEFINE_OPFVV_FMA(vfmsac, VFMSAC_FUNCT6)
952   DEFINE_OPFVF_FMA(vfmsac, VFMSAC_FUNCT6)
953   DEFINE_OPFVV_FMA(vfnmadd, VFNMADD_FUNCT6)
954   DEFINE_OPFVF_FMA(vfnmadd, VFNMADD_FUNCT6)
955   DEFINE_OPFVV_FMA(vfnmsub, VFNMSUB_FUNCT6)
956   DEFINE_OPFVF_FMA(vfnmsub, VFNMSUB_FUNCT6)
957   DEFINE_OPFVV_FMA(vfnmacc, VFNMACC_FUNCT6)
958   DEFINE_OPFVF_FMA(vfnmacc, VFNMACC_FUNCT6)
959   DEFINE_OPFVV_FMA(vfnmsac, VFNMSAC_FUNCT6)
960   DEFINE_OPFVF_FMA(vfnmsac, VFNMSAC_FUNCT6)
961 
962   // Vector Widening Floating-Point Fused Multiply-Add Instructions
963   DEFINE_OPFVV_FMA(vfwmacc, VFWMACC_FUNCT6)
964   DEFINE_OPFVF_FMA(vfwmacc, VFWMACC_FUNCT6)
965   DEFINE_OPFVV_FMA(vfwnmacc, VFWNMACC_FUNCT6)
966   DEFINE_OPFVF_FMA(vfwnmacc, VFWNMACC_FUNCT6)
967   DEFINE_OPFVV_FMA(vfwmsac, VFWMSAC_FUNCT6)
968   DEFINE_OPFVF_FMA(vfwmsac, VFWMSAC_FUNCT6)
969   DEFINE_OPFVV_FMA(vfwnmsac, VFWNMSAC_FUNCT6)
970   DEFINE_OPFVF_FMA(vfwnmsac, VFWNMSAC_FUNCT6)
971 
972   // Vector Narrowing Fixed-Point Clip Instructions
973   DEFINE_OPIVV(vnclip, VNCLIP_FUNCT6)
974   DEFINE_OPIVX(vnclip, VNCLIP_FUNCT6)
975   DEFINE_OPIVI(vnclip, VNCLIP_FUNCT6)
976   DEFINE_OPIVV(vnclipu, VNCLIPU_FUNCT6)
977   DEFINE_OPIVX(vnclipu, VNCLIPU_FUNCT6)
978   DEFINE_OPIVI(vnclipu, VNCLIPU_FUNCT6)
979 
980   // Vector Integer Extension
981   DEFINE_OPMVV_VIE(vzext_vf8)
982   DEFINE_OPMVV_VIE(vsext_vf8)
983   DEFINE_OPMVV_VIE(vzext_vf4)
984   DEFINE_OPMVV_VIE(vsext_vf4)
985   DEFINE_OPMVV_VIE(vzext_vf2)
986   DEFINE_OPMVV_VIE(vsext_vf2)
987 
988 #undef DEFINE_OPIVI
989 #undef DEFINE_OPIVV
990 #undef DEFINE_OPIVX
991 #undef DEFINE_OPMVV
992 #undef DEFINE_OPMVX
993 #undef DEFINE_OPFVV
994 #undef DEFINE_OPFWV
995 #undef DEFINE_OPFVF
996 #undef DEFINE_OPFWF
997 #undef DEFINE_OPFVV_FMA
998 #undef DEFINE_OPFVF_FMA
999 #undef DEFINE_OPMVV_VIE
1000 #undef DEFINE_OPFRED
1001 
1002 #define DEFINE_VFUNARY(name, funct6, vs1)                          \
1003   void name(VRegister vd, VRegister vs2, MaskType mask = NoMask) { \
1004     GenInstrV(funct6, OP_FVV, vd, vs1, vs2, mask);                 \
1005   }
1006 
1007   DEFINE_VFUNARY(vfcvt_xu_f_v, VFUNARY0_FUNCT6, VFCVT_XU_F_V)
1008   DEFINE_VFUNARY(vfcvt_x_f_v, VFUNARY0_FUNCT6, VFCVT_X_F_V)
1009   DEFINE_VFUNARY(vfcvt_f_x_v, VFUNARY0_FUNCT6, VFCVT_F_X_V)
1010   DEFINE_VFUNARY(vfcvt_f_xu_v, VFUNARY0_FUNCT6, VFCVT_F_XU_V)
1011   DEFINE_VFUNARY(vfwcvt_xu_f_v, VFUNARY0_FUNCT6, VFWCVT_XU_F_V)
1012   DEFINE_VFUNARY(vfwcvt_x_f_v, VFUNARY0_FUNCT6, VFWCVT_X_F_V)
1013   DEFINE_VFUNARY(vfwcvt_f_x_v, VFUNARY0_FUNCT6, VFWCVT_F_X_V)
1014   DEFINE_VFUNARY(vfwcvt_f_xu_v, VFUNARY0_FUNCT6, VFWCVT_F_XU_V)
1015   DEFINE_VFUNARY(vfwcvt_f_f_v, VFUNARY0_FUNCT6, VFWCVT_F_F_V)
1016 
1017   DEFINE_VFUNARY(vfncvt_f_f_w, VFUNARY0_FUNCT6, VFNCVT_F_F_W)
1018   DEFINE_VFUNARY(vfncvt_x_f_w, VFUNARY0_FUNCT6, VFNCVT_X_F_W)
1019   DEFINE_VFUNARY(vfncvt_xu_f_w, VFUNARY0_FUNCT6, VFNCVT_XU_F_W)
1020 
1021   DEFINE_VFUNARY(vfclass_v, VFUNARY1_FUNCT6, VFCLASS_V)
1022   DEFINE_VFUNARY(vfsqrt_v, VFUNARY1_FUNCT6, VFSQRT_V)
1023   DEFINE_VFUNARY(vfrsqrt7_v, VFUNARY1_FUNCT6, VFRSQRT7_V)
1024   DEFINE_VFUNARY(vfrec7_v, VFUNARY1_FUNCT6, VFREC7_V)
1025 #undef DEFINE_VFUNARY
1026 
1027   void vnot_vv(VRegister dst, VRegister src, MaskType mask = NoMask) {
1028     vxor_vi(dst, src, -1, mask);
1029   }
1030 
1031   void vneg_vv(VRegister dst, VRegister src, MaskType mask = NoMask) {
1032     vrsub_vx(dst, src, zero_reg, mask);
1033   }
1034 
1035   void vfneg_vv(VRegister dst, VRegister src, MaskType mask = NoMask) {
1036     vfsngjn_vv(dst, src, src, mask);
1037   }
1038   void vfabs_vv(VRegister dst, VRegister src, MaskType mask = NoMask) {
1039     vfsngjx_vv(dst, src, src, mask);
1040   }
1041   void vfirst_m(Register rd, VRegister vs2, MaskType mask = NoMask);
1042 
1043   void vcpop_m(Register rd, VRegister vs2, MaskType mask = NoMask);
1044 
1045   // Privileged
1046   void uret();
1047   void sret();
1048   void mret();
1049   void wfi();
1050   void sfence_vma(Register rs1, Register rs2);
1051 
1052   // Assembler Pseudo Instructions (Tables 25.2, 25.3, RISC-V Unprivileged ISA)
1053   void nop();
1054   void RV_li(Register rd, int64_t imm);
1055   // Returns the number of instructions required to load the immediate
1056   static int li_estimate(int64_t imm, bool is_get_temp_reg = false);
1057   // Loads an immediate, always using 8 instructions, regardless of the value,
1058   // so that it can be modified later.
1059   void li_constant(Register rd, int64_t imm);
1060   void li_ptr(Register rd, int64_t imm);
1061 
mv(Register rd,Register rs)1062   void mv(Register rd, Register rs) { addi(rd, rs, 0); }
not_(Register rd,Register rs)1063   void not_(Register rd, Register rs) { xori(rd, rs, -1); }
neg(Register rd,Register rs)1064   void neg(Register rd, Register rs) { sub(rd, zero_reg, rs); }
negw(Register rd,Register rs)1065   void negw(Register rd, Register rs) { subw(rd, zero_reg, rs); }
sext_w(Register rd,Register rs)1066   void sext_w(Register rd, Register rs) { addiw(rd, rs, 0); }
seqz(Register rd,Register rs)1067   void seqz(Register rd, Register rs) { sltiu(rd, rs, 1); }
snez(Register rd,Register rs)1068   void snez(Register rd, Register rs) { sltu(rd, zero_reg, rs); }
sltz(Register rd,Register rs)1069   void sltz(Register rd, Register rs) { slt(rd, rs, zero_reg); }
sgtz(Register rd,Register rs)1070   void sgtz(Register rd, Register rs) { slt(rd, zero_reg, rs); }
1071 
fmv_s(FPURegister rd,FPURegister rs)1072   void fmv_s(FPURegister rd, FPURegister rs) { fsgnj_s(rd, rs, rs); }
fabs_s(FPURegister rd,FPURegister rs)1073   void fabs_s(FPURegister rd, FPURegister rs) { fsgnjx_s(rd, rs, rs); }
fneg_s(FPURegister rd,FPURegister rs)1074   void fneg_s(FPURegister rd, FPURegister rs) { fsgnjn_s(rd, rs, rs); }
fmv_d(FPURegister rd,FPURegister rs)1075   void fmv_d(FPURegister rd, FPURegister rs) { fsgnj_d(rd, rs, rs); }
fabs_d(FPURegister rd,FPURegister rs)1076   void fabs_d(FPURegister rd, FPURegister rs) { fsgnjx_d(rd, rs, rs); }
fneg_d(FPURegister rd,FPURegister rs)1077   void fneg_d(FPURegister rd, FPURegister rs) { fsgnjn_d(rd, rs, rs); }
1078 
beqz(Register rs,int16_t imm13)1079   void beqz(Register rs, int16_t imm13) { beq(rs, zero_reg, imm13); }
beqz(Register rs1,Label * L)1080   inline void beqz(Register rs1, Label* L) { beqz(rs1, branch_offset(L)); }
bnez(Register rs,int16_t imm13)1081   void bnez(Register rs, int16_t imm13) { bne(rs, zero_reg, imm13); }
bnez(Register rs1,Label * L)1082   inline void bnez(Register rs1, Label* L) { bnez(rs1, branch_offset(L)); }
blez(Register rs,int16_t imm13)1083   void blez(Register rs, int16_t imm13) { bge(zero_reg, rs, imm13); }
blez(Register rs1,Label * L)1084   inline void blez(Register rs1, Label* L) { blez(rs1, branch_offset(L)); }
bgez(Register rs,int16_t imm13)1085   void bgez(Register rs, int16_t imm13) { bge(rs, zero_reg, imm13); }
bgez(Register rs1,Label * L)1086   inline void bgez(Register rs1, Label* L) { bgez(rs1, branch_offset(L)); }
bltz(Register rs,int16_t imm13)1087   void bltz(Register rs, int16_t imm13) { blt(rs, zero_reg, imm13); }
bltz(Register rs1,Label * L)1088   inline void bltz(Register rs1, Label* L) { bltz(rs1, branch_offset(L)); }
bgtz(Register rs,int16_t imm13)1089   void bgtz(Register rs, int16_t imm13) { blt(zero_reg, rs, imm13); }
1090 
bgtz(Register rs1,Label * L)1091   inline void bgtz(Register rs1, Label* L) { bgtz(rs1, branch_offset(L)); }
bgt(Register rs1,Register rs2,int16_t imm13)1092   void bgt(Register rs1, Register rs2, int16_t imm13) { blt(rs2, rs1, imm13); }
bgt(Register rs1,Register rs2,Label * L)1093   inline void bgt(Register rs1, Register rs2, Label* L) {
1094     bgt(rs1, rs2, branch_offset(L));
1095   }
ble(Register rs1,Register rs2,int16_t imm13)1096   void ble(Register rs1, Register rs2, int16_t imm13) { bge(rs2, rs1, imm13); }
ble(Register rs1,Register rs2,Label * L)1097   inline void ble(Register rs1, Register rs2, Label* L) {
1098     ble(rs1, rs2, branch_offset(L));
1099   }
bgtu(Register rs1,Register rs2,int16_t imm13)1100   void bgtu(Register rs1, Register rs2, int16_t imm13) {
1101     bltu(rs2, rs1, imm13);
1102   }
bgtu(Register rs1,Register rs2,Label * L)1103   inline void bgtu(Register rs1, Register rs2, Label* L) {
1104     bgtu(rs1, rs2, branch_offset(L));
1105   }
bleu(Register rs1,Register rs2,int16_t imm13)1106   void bleu(Register rs1, Register rs2, int16_t imm13) {
1107     bgeu(rs2, rs1, imm13);
1108   }
bleu(Register rs1,Register rs2,Label * L)1109   inline void bleu(Register rs1, Register rs2, Label* L) {
1110     bleu(rs1, rs2, branch_offset(L));
1111   }
1112 
j(int32_t imm21)1113   void j(int32_t imm21) { jal(zero_reg, imm21); }
j(Label * L)1114   inline void j(Label* L) { j(jump_offset(L)); }
b(Label * L)1115   inline void b(Label* L) { j(L); }
jal(int32_t imm21)1116   void jal(int32_t imm21) { jal(ra, imm21); }
jal(Label * L)1117   inline void jal(Label* L) { jal(jump_offset(L)); }
jr(Register rs)1118   void jr(Register rs) { jalr(zero_reg, rs, 0); }
jr(Register rs,int32_t imm12)1119   void jr(Register rs, int32_t imm12) { jalr(zero_reg, rs, imm12); }
jalr(Register rs,int32_t imm12)1120   void jalr(Register rs, int32_t imm12) { jalr(ra, rs, imm12); }
jalr(Register rs)1121   void jalr(Register rs) { jalr(ra, rs, 0); }
ret()1122   void ret() { jalr(zero_reg, ra, 0); }
call(int32_t offset)1123   void call(int32_t offset) {
1124     auipc(ra, (offset >> 12) + ((offset & 0x800) >> 11));
1125     jalr(ra, ra, offset << 20 >> 20);
1126   }
1127 
1128   // Read instructions-retired counter
rdinstret(Register rd)1129   void rdinstret(Register rd) { csrrs(rd, csr_instret, zero_reg); }
rdinstreth(Register rd)1130   void rdinstreth(Register rd) { csrrs(rd, csr_instreth, zero_reg); }
rdcycle(Register rd)1131   void rdcycle(Register rd) { csrrs(rd, csr_cycle, zero_reg); }
rdcycleh(Register rd)1132   void rdcycleh(Register rd) { csrrs(rd, csr_cycleh, zero_reg); }
rdtime(Register rd)1133   void rdtime(Register rd) { csrrs(rd, csr_time, zero_reg); }
rdtimeh(Register rd)1134   void rdtimeh(Register rd) { csrrs(rd, csr_timeh, zero_reg); }
1135 
csrr(Register rd,ControlStatusReg csr)1136   void csrr(Register rd, ControlStatusReg csr) { csrrs(rd, csr, zero_reg); }
csrw(ControlStatusReg csr,Register rs)1137   void csrw(ControlStatusReg csr, Register rs) { csrrw(zero_reg, csr, rs); }
csrs(ControlStatusReg csr,Register rs)1138   void csrs(ControlStatusReg csr, Register rs) { csrrs(zero_reg, csr, rs); }
csrc(ControlStatusReg csr,Register rs)1139   void csrc(ControlStatusReg csr, Register rs) { csrrc(zero_reg, csr, rs); }
1140 
csrwi(ControlStatusReg csr,uint8_t imm)1141   void csrwi(ControlStatusReg csr, uint8_t imm) { csrrwi(zero_reg, csr, imm); }
csrsi(ControlStatusReg csr,uint8_t imm)1142   void csrsi(ControlStatusReg csr, uint8_t imm) { csrrsi(zero_reg, csr, imm); }
csrci(ControlStatusReg csr,uint8_t imm)1143   void csrci(ControlStatusReg csr, uint8_t imm) { csrrci(zero_reg, csr, imm); }
1144 
frcsr(Register rd)1145   void frcsr(Register rd) { csrrs(rd, csr_fcsr, zero_reg); }
fscsr(Register rd,Register rs)1146   void fscsr(Register rd, Register rs) { csrrw(rd, csr_fcsr, rs); }
fscsr(Register rs)1147   void fscsr(Register rs) { csrrw(zero_reg, csr_fcsr, rs); }
1148 
frrm(Register rd)1149   void frrm(Register rd) { csrrs(rd, csr_frm, zero_reg); }
fsrm(Register rd,Register rs)1150   void fsrm(Register rd, Register rs) { csrrw(rd, csr_frm, rs); }
fsrm(Register rs)1151   void fsrm(Register rs) { csrrw(zero_reg, csr_frm, rs); }
1152 
frflags(Register rd)1153   void frflags(Register rd) { csrrs(rd, csr_fflags, zero_reg); }
fsflags(Register rd,Register rs)1154   void fsflags(Register rd, Register rs) { csrrw(rd, csr_fflags, rs); }
fsflags(Register rs)1155   void fsflags(Register rs) { csrrw(zero_reg, csr_fflags, rs); }
1156 
1157   // Other pseudo instructions that are not part of RISCV pseudo assemly
nor(Register rd,Register rs,Register rt)1158   void nor(Register rd, Register rs, Register rt) {
1159     or_(rd, rs, rt);
1160     not_(rd, rd);
1161   }
1162 
sync()1163   void sync() { fence(0b1111, 0b1111); }
1164   void break_(uint32_t code, bool break_as_stop = false);
1165   void stop(uint32_t code = kMaxStopCode);
1166 
1167   // Check the code size generated from label to here.
SizeOfCodeGeneratedSince(Label * label)1168   int SizeOfCodeGeneratedSince(Label* label) {
1169     return pc_offset() - label->pos();
1170   }
1171 
1172   // Check the number of instructions generated from label to here.
InstructionsGeneratedSince(Label * label)1173   int InstructionsGeneratedSince(Label* label) {
1174     return SizeOfCodeGeneratedSince(label) / kInstrSize;
1175   }
1176 
1177   using BlockConstPoolScope = ConstantPool::BlockScope;
1178   // Class for scoping postponing the trampoline pool generation.
1179   class BlockTrampolinePoolScope {
1180    public:
1181     explicit BlockTrampolinePoolScope(Assembler* assem, int margin = 0)
assem_(assem)1182         : assem_(assem) {
1183       assem_->StartBlockTrampolinePool();
1184     }
1185 
BlockTrampolinePoolScope(Assembler * assem,PoolEmissionCheck check)1186     explicit BlockTrampolinePoolScope(Assembler* assem, PoolEmissionCheck check)
1187         : assem_(assem) {
1188       assem_->StartBlockTrampolinePool();
1189     }
~BlockTrampolinePoolScope()1190     ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); }
1191 
1192    private:
1193     Assembler* assem_;
1194     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
1195   };
1196 
1197   // Class for postponing the assembly buffer growth. Typically used for
1198   // sequences of instructions that must be emitted as a unit, before
1199   // buffer growth (and relocation) can occur.
1200   // This blocking scope is not nestable.
1201   class BlockGrowBufferScope {
1202    public:
BlockGrowBufferScope(Assembler * assem)1203     explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) {
1204       assem_->StartBlockGrowBuffer();
1205     }
~BlockGrowBufferScope()1206     ~BlockGrowBufferScope() { assem_->EndBlockGrowBuffer(); }
1207 
1208    private:
1209     Assembler* assem_;
1210 
1211     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope);
1212   };
1213 
1214   // Record a deoptimization reason that can be used by a log or cpu profiler.
1215   // Use --trace-deopt to enable.
1216   void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
1217                          SourcePosition position, int id);
1218 
1219   static int RelocateInternalReference(RelocInfo::Mode rmode, Address pc,
1220                                        intptr_t pc_delta);
1221   static void RelocateRelativeReference(RelocInfo::Mode rmode, Address pc,
1222                                         intptr_t pc_delta);
1223 
1224   // Writes a single byte or word of data in the code stream.  Used for
1225   // inline tables, e.g., jump-tables.
1226   void db(uint8_t data);
1227   void dd(uint32_t data, RelocInfo::Mode rmode = RelocInfo::NO_INFO);
1228   void dq(uint64_t data, RelocInfo::Mode rmode = RelocInfo::NO_INFO);
1229   void dp(uintptr_t data, RelocInfo::Mode rmode = RelocInfo::NO_INFO) {
1230     dq(data, rmode);
1231   }
1232   void dd(Label* label);
1233 
pc()1234   Instruction* pc() const { return reinterpret_cast<Instruction*>(pc_); }
1235 
1236   // Postpone the generation of the trampoline pool for the specified number of
1237   // instructions.
1238   void BlockTrampolinePoolFor(int instructions);
1239 
1240   // Check if there is less than kGap bytes available in the buffer.
1241   // If this is the case, we need to grow the buffer before emitting
1242   // an instruction or relocation information.
overflow()1243   inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
1244 
1245   // Get the number of bytes available in the buffer.
available_space()1246   inline intptr_t available_space() const {
1247     return reloc_info_writer.pos() - pc_;
1248   }
1249 
1250   // Read/patch instructions.
instr_at(Address pc)1251   static Instr instr_at(Address pc) { return *reinterpret_cast<Instr*>(pc); }
instr_at_put(Address pc,Instr instr)1252   static void instr_at_put(Address pc, Instr instr) {
1253     *reinterpret_cast<Instr*>(pc) = instr;
1254   }
instr_at(int pos)1255   Instr instr_at(int pos) {
1256     return *reinterpret_cast<Instr*>(buffer_start_ + pos);
1257   }
instr_at_put(int pos,Instr instr)1258   void instr_at_put(int pos, Instr instr) {
1259     *reinterpret_cast<Instr*>(buffer_start_ + pos) = instr;
1260   }
1261 
instr_at_put(int pos,ShortInstr instr)1262   void instr_at_put(int pos, ShortInstr instr) {
1263     *reinterpret_cast<ShortInstr*>(buffer_start_ + pos) = instr;
1264   }
1265 
toAddress(int pos)1266   Address toAddress(int pos) {
1267     return reinterpret_cast<Address>(buffer_start_ + pos);
1268   }
1269 
1270   // Check if an instruction is a branch of some kind.
1271   static bool IsBranch(Instr instr);
1272   static bool IsCBranch(Instr instr);
1273   static bool IsNop(Instr instr);
1274   static bool IsJump(Instr instr);
1275   static bool IsJal(Instr instr);
1276   static bool IsCJal(Instr instr);
1277   static bool IsJalr(Instr instr);
1278   static bool IsLui(Instr instr);
1279   static bool IsAuipc(Instr instr);
1280   static bool IsAddiw(Instr instr);
1281   static bool IsAddi(Instr instr);
1282   static bool IsOri(Instr instr);
1283   static bool IsSlli(Instr instr);
1284   static bool IsLd(Instr instr);
1285   void CheckTrampolinePool();
1286 
1287   // Get the code target object for a pc-relative call or jump.
1288   V8_INLINE Handle<Code> relative_code_target_object_handle_at(
1289       Address pc_) const;
1290 
UnboundLabelsCount()1291   inline int UnboundLabelsCount() { return unbound_labels_count_; }
1292 
1293   using BlockPoolsScope = BlockTrampolinePoolScope;
1294 
1295   void RecordConstPool(int size);
1296 
ForceConstantPoolEmissionWithoutJump()1297   void ForceConstantPoolEmissionWithoutJump() {
1298     constpool_.Check(Emission::kForced, Jump::kOmitted);
1299   }
ForceConstantPoolEmissionWithJump()1300   void ForceConstantPoolEmissionWithJump() {
1301     constpool_.Check(Emission::kForced, Jump::kRequired);
1302   }
1303   // Check if the const pool needs to be emitted while pretending that {margin}
1304   // more bytes of instructions have already been emitted.
1305   void EmitConstPoolWithJumpIfNeeded(size_t margin = 0) {
1306     constpool_.Check(Emission::kIfNeeded, Jump::kRequired, margin);
1307   }
1308 
1309   void EmitConstPoolWithoutJumpIfNeeded(size_t margin = 0) {
1310     constpool_.Check(Emission::kIfNeeded, Jump::kOmitted, margin);
1311   }
1312 
RecordEntry(uint32_t data,RelocInfo::Mode rmode)1313   void RecordEntry(uint32_t data, RelocInfo::Mode rmode) {
1314     constpool_.RecordEntry(data, rmode);
1315   }
1316 
RecordEntry(uint64_t data,RelocInfo::Mode rmode)1317   void RecordEntry(uint64_t data, RelocInfo::Mode rmode) {
1318     constpool_.RecordEntry(data, rmode);
1319   }
1320 
1321   friend class VectorUnit;
1322   class VectorUnit {
1323    public:
sew()1324     inline int32_t sew() const { return 2 ^ (sew_ + 3); }
1325 
vlmax()1326     inline int32_t vlmax() const {
1327       if ((lmul_ & 0b100) != 0) {
1328         return (kRvvVLEN / sew()) >> (lmul_ & 0b11);
1329       } else {
1330         return ((kRvvVLEN << lmul_) / sew());
1331       }
1332     }
1333 
VectorUnit(Assembler * assm)1334     explicit VectorUnit(Assembler* assm) : assm_(assm) {}
1335 
set(Register rd,VSew sew,Vlmul lmul)1336     void set(Register rd, VSew sew, Vlmul lmul) {
1337       if (sew != sew_ || lmul != lmul_ || vl != vlmax()) {
1338         sew_ = sew;
1339         lmul_ = lmul;
1340         vl = vlmax();
1341         assm_->vsetvlmax(rd, sew_, lmul_);
1342       }
1343     }
1344 
set(Register rd,int8_t sew,int8_t lmul)1345     void set(Register rd, int8_t sew, int8_t lmul) {
1346       DCHECK_GE(sew, E8);
1347       DCHECK_LE(sew, E64);
1348       DCHECK_GE(lmul, m1);
1349       DCHECK_LE(lmul, mf2);
1350       set(rd, VSew(sew), Vlmul(lmul));
1351     }
1352 
set(RoundingMode mode)1353     void set(RoundingMode mode) {
1354       if (mode_ != mode) {
1355         assm_->addi(kScratchReg, zero_reg, mode << kFcsrFrmShift);
1356         assm_->fscsr(kScratchReg);
1357         mode_ = mode;
1358       }
1359     }
set(Register rd,Register rs1,VSew sew,Vlmul lmul)1360     void set(Register rd, Register rs1, VSew sew, Vlmul lmul) {
1361       if (sew != sew_ || lmul != lmul_) {
1362         sew_ = sew;
1363         lmul_ = lmul;
1364         vl = 0;
1365         assm_->vsetvli(rd, rs1, sew_, lmul_);
1366       }
1367     }
1368 
set(VSew sew,Vlmul lmul)1369     void set(VSew sew, Vlmul lmul) {
1370       if (sew != sew_ || lmul != lmul_) {
1371         sew_ = sew;
1372         lmul_ = lmul;
1373         assm_->vsetvl(sew_, lmul_);
1374       }
1375     }
1376 
1377    private:
1378     VSew sew_ = E8;
1379     Vlmul lmul_ = m1;
1380     int32_t vl = 0;
1381     Assembler* assm_;
1382     RoundingMode mode_ = RNE;
1383   };
1384 
1385   VectorUnit VU;
1386 
1387   void CheckTrampolinePoolQuick(int extra_instructions = 0) {
1388     DEBUG_PRINTF("\tpc_offset:%d %d\n", pc_offset(),
1389                  next_buffer_check_ - extra_instructions * kInstrSize);
1390     if (pc_offset() >= next_buffer_check_ - extra_instructions * kInstrSize) {
1391       CheckTrampolinePool();
1392     }
1393   }
1394 
1395  protected:
1396   // Readable constants for base and offset adjustment helper, these indicate if
1397   // aside from offset, another value like offset + 4 should fit into int16.
1398   enum class OffsetAccessType : bool {
1399     SINGLE_ACCESS = false,
1400     TWO_ACCESSES = true
1401   };
1402 
1403   // Determine whether need to adjust base and offset of memroy load/store
1404   bool NeedAdjustBaseAndOffset(
1405       const MemOperand& src, OffsetAccessType = OffsetAccessType::SINGLE_ACCESS,
1406       int second_Access_add_to_offset = 4);
1407 
1408   // Helper function for memory load/store using base register and offset.
1409   void AdjustBaseAndOffset(
1410       MemOperand* src, Register scratch,
1411       OffsetAccessType access_type = OffsetAccessType::SINGLE_ACCESS,
1412       int second_access_add_to_offset = 4);
1413 
1414   inline static void set_target_internal_reference_encoded_at(Address pc,
1415                                                               Address target);
1416 
buffer_space()1417   int64_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
1418 
1419   // Decode branch instruction at pos and return branch target pos.
1420   int target_at(int pos, bool is_internal);
1421 
1422   // Patch branch instruction at pos to branch to given branch target pos.
1423   void target_at_put(int pos, int target_pos, bool is_internal,
1424                      bool trampoline = false);
1425 
1426   // Say if we need to relocate with this mode.
1427   bool MustUseReg(RelocInfo::Mode rmode);
1428 
1429   // Record reloc info for current pc_.
1430   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1431 
1432   // Block the emission of the trampoline pool before pc_offset.
BlockTrampolinePoolBefore(int pc_offset)1433   void BlockTrampolinePoolBefore(int pc_offset) {
1434     if (no_trampoline_pool_before_ < pc_offset)
1435       no_trampoline_pool_before_ = pc_offset;
1436   }
1437 
StartBlockTrampolinePool()1438   void StartBlockTrampolinePool() {
1439     DEBUG_PRINTF("\tStartBlockTrampolinePool\n");
1440     trampoline_pool_blocked_nesting_++;
1441   }
1442 
EndBlockTrampolinePool()1443   void EndBlockTrampolinePool() {
1444     trampoline_pool_blocked_nesting_--;
1445     DEBUG_PRINTF("\ttrampoline_pool_blocked_nesting:%d\n",
1446                  trampoline_pool_blocked_nesting_);
1447     if (trampoline_pool_blocked_nesting_ == 0) {
1448       CheckTrampolinePoolQuick(1);
1449     }
1450   }
1451 
is_trampoline_pool_blocked()1452   bool is_trampoline_pool_blocked() const {
1453     return trampoline_pool_blocked_nesting_ > 0;
1454   }
1455 
has_exception()1456   bool has_exception() const { return internal_trampoline_exception_; }
1457 
is_trampoline_emitted()1458   bool is_trampoline_emitted() const { return trampoline_emitted_; }
1459 
1460   // Temporarily block automatic assembly buffer growth.
StartBlockGrowBuffer()1461   void StartBlockGrowBuffer() {
1462     DCHECK(!block_buffer_growth_);
1463     block_buffer_growth_ = true;
1464   }
1465 
EndBlockGrowBuffer()1466   void EndBlockGrowBuffer() {
1467     DCHECK(block_buffer_growth_);
1468     block_buffer_growth_ = false;
1469   }
1470 
is_buffer_growth_blocked()1471   bool is_buffer_growth_blocked() const { return block_buffer_growth_; }
1472 
1473  private:
1474   void vsetvli(Register rd, Register rs1, VSew vsew, Vlmul vlmul,
1475                TailAgnosticType tail = tu, MaskAgnosticType mask = mu);
1476 
1477   void vsetivli(Register rd, uint8_t uimm, VSew vsew, Vlmul vlmul,
1478                 TailAgnosticType tail = tu, MaskAgnosticType mask = mu);
1479 
1480   inline void vsetvlmax(Register rd, VSew vsew, Vlmul vlmul,
1481                         TailAgnosticType tail = tu,
1482                         MaskAgnosticType mask = mu) {
1483     vsetvli(rd, zero_reg, vsew, vlmul, tu, mu);
1484   }
1485 
1486   inline void vsetvl(VSew vsew, Vlmul vlmul, TailAgnosticType tail = tu,
1487                      MaskAgnosticType mask = mu) {
1488     vsetvli(zero_reg, zero_reg, vsew, vlmul, tu, mu);
1489   }
1490 
1491   void vsetvl(Register rd, Register rs1, Register rs2);
1492 
1493   // Avoid overflows for displacements etc.
1494   static const int kMaximalBufferSize = 512 * MB;
1495 
1496   // Buffer size and constant pool distance are checked together at regular
1497   // intervals of kBufferCheckInterval emitted bytes.
1498   static constexpr int kBufferCheckInterval = 1 * KB / 2;
1499 
1500   // Code generation.
1501   // The relocation writer's position is at least kGap bytes below the end of
1502   // the generated instructions. This is so that multi-instruction sequences do
1503   // not have to check for overflow. The same is true for writes of large
1504   // relocation info entries.
1505   static constexpr int kGap = 64;
1506   STATIC_ASSERT(AssemblerBase::kMinimalBufferSize >= 2 * kGap);
1507 
1508   // Repeated checking whether the trampoline pool should be emitted is rather
1509   // expensive. By default we only check again once a number of instructions
1510   // has been generated.
1511   static constexpr int kCheckConstIntervalInst = 32;
1512   static constexpr int kCheckConstInterval =
1513       kCheckConstIntervalInst * kInstrSize;
1514 
1515   int next_buffer_check_;  // pc offset of next buffer check.
1516 
1517   // Emission of the trampoline pool may be blocked in some code sequences.
1518   int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
1519   int no_trampoline_pool_before_;  // Block emission before this pc offset.
1520 
1521   // Keep track of the last emitted pool to guarantee a maximal distance.
1522   int last_trampoline_pool_end_;  // pc offset of the end of the last pool.
1523 
1524   // Automatic growth of the assembly buffer may be blocked for some sequences.
1525   bool block_buffer_growth_;  // Block growth when true.
1526 
1527   // Relocation information generation.
1528   // Each relocation is encoded as a variable size value.
1529   static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1530   RelocInfoWriter reloc_info_writer;
1531 
1532   // The bound position, before this we cannot do instruction elimination.
1533   int last_bound_pos_;
1534 
1535   // Code emission.
1536   inline void CheckBuffer();
1537   void GrowBuffer();
1538   inline void emit(Instr x);
1539   inline void emit(ShortInstr x);
1540   inline void emit(uint64_t x);
1541   template <typename T>
1542   inline void EmitHelper(T x);
1543 
1544   static void disassembleInstr(Instr instr);
1545 
1546   // Instruction generation.
1547 
1548   // ----- Top-level instruction formats match those in the ISA manual
1549   // (R, I, S, B, U, J). These match the formats defined in LLVM's
1550   // RISCVInstrFormats.td.
1551   void GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode, Register rd,
1552                  Register rs1, Register rs2);
1553   void GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode, FPURegister rd,
1554                  FPURegister rs1, FPURegister rs2);
1555   void GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode, Register rd,
1556                  FPURegister rs1, Register rs2);
1557   void GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode, FPURegister rd,
1558                  Register rs1, Register rs2);
1559   void GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode, FPURegister rd,
1560                  FPURegister rs1, Register rs2);
1561   void GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode, Register rd,
1562                  FPURegister rs1, FPURegister rs2);
1563   void GenInstrR4(uint8_t funct2, Opcode opcode, Register rd, Register rs1,
1564                   Register rs2, Register rs3, RoundingMode frm);
1565   void GenInstrR4(uint8_t funct2, Opcode opcode, FPURegister rd,
1566                   FPURegister rs1, FPURegister rs2, FPURegister rs3,
1567                   RoundingMode frm);
1568   void GenInstrRAtomic(uint8_t funct5, bool aq, bool rl, uint8_t funct3,
1569                        Register rd, Register rs1, Register rs2);
1570   void GenInstrRFrm(uint8_t funct7, Opcode opcode, Register rd, Register rs1,
1571                     Register rs2, RoundingMode frm);
1572   void GenInstrI(uint8_t funct3, Opcode opcode, Register rd, Register rs1,
1573                  int16_t imm12);
1574   void GenInstrI(uint8_t funct3, Opcode opcode, FPURegister rd, Register rs1,
1575                  int16_t imm12);
1576   void GenInstrIShift(bool arithshift, uint8_t funct3, Opcode opcode,
1577                       Register rd, Register rs1, uint8_t shamt);
1578   void GenInstrIShiftW(bool arithshift, uint8_t funct3, Opcode opcode,
1579                        Register rd, Register rs1, uint8_t shamt);
1580   void GenInstrS(uint8_t funct3, Opcode opcode, Register rs1, Register rs2,
1581                  int16_t imm12);
1582   void GenInstrS(uint8_t funct3, Opcode opcode, Register rs1, FPURegister rs2,
1583                  int16_t imm12);
1584   void GenInstrB(uint8_t funct3, Opcode opcode, Register rs1, Register rs2,
1585                  int16_t imm12);
1586   void GenInstrU(Opcode opcode, Register rd, int32_t imm20);
1587   void GenInstrJ(Opcode opcode, Register rd, int32_t imm20);
1588   void GenInstrCR(uint8_t funct4, Opcode opcode, Register rd, Register rs2);
1589   void GenInstrCA(uint8_t funct6, Opcode opcode, Register rd, uint8_t funct,
1590                   Register rs2);
1591   void GenInstrCI(uint8_t funct3, Opcode opcode, Register rd, int8_t imm6);
1592   void GenInstrCIU(uint8_t funct3, Opcode opcode, Register rd, uint8_t uimm6);
1593   void GenInstrCIU(uint8_t funct3, Opcode opcode, FPURegister rd,
1594                    uint8_t uimm6);
1595   void GenInstrCIW(uint8_t funct3, Opcode opcode, Register rd, uint8_t uimm8);
1596   void GenInstrCSS(uint8_t funct3, Opcode opcode, FPURegister rs2,
1597                    uint8_t uimm6);
1598   void GenInstrCSS(uint8_t funct3, Opcode opcode, Register rs2, uint8_t uimm6);
1599   void GenInstrCL(uint8_t funct3, Opcode opcode, Register rd, Register rs1,
1600                   uint8_t uimm5);
1601   void GenInstrCL(uint8_t funct3, Opcode opcode, FPURegister rd, Register rs1,
1602                   uint8_t uimm5);
1603   void GenInstrCS(uint8_t funct3, Opcode opcode, Register rs2, Register rs1,
1604                   uint8_t uimm5);
1605   void GenInstrCS(uint8_t funct3, Opcode opcode, FPURegister rs2, Register rs1,
1606                   uint8_t uimm5);
1607   void GenInstrCJ(uint8_t funct3, Opcode opcode, uint16_t uint11);
1608   void GenInstrCB(uint8_t funct3, Opcode opcode, Register rs1, uint8_t uimm8);
1609   void GenInstrCBA(uint8_t funct3, uint8_t funct2, Opcode opcode, Register rs1,
1610                    int8_t imm6);
1611 
1612   // ----- Instruction class templates match those in LLVM's RISCVInstrInfo.td
1613   void GenInstrBranchCC_rri(uint8_t funct3, Register rs1, Register rs2,
1614                             int16_t imm12);
1615   void GenInstrLoad_ri(uint8_t funct3, Register rd, Register rs1,
1616                        int16_t imm12);
1617   void GenInstrStore_rri(uint8_t funct3, Register rs1, Register rs2,
1618                          int16_t imm12);
1619   void GenInstrALU_ri(uint8_t funct3, Register rd, Register rs1, int16_t imm12);
1620   void GenInstrShift_ri(bool arithshift, uint8_t funct3, Register rd,
1621                         Register rs1, uint8_t shamt);
1622   void GenInstrALU_rr(uint8_t funct7, uint8_t funct3, Register rd, Register rs1,
1623                       Register rs2);
1624   void GenInstrCSR_ir(uint8_t funct3, Register rd, ControlStatusReg csr,
1625                       Register rs1);
1626   void GenInstrCSR_ii(uint8_t funct3, Register rd, ControlStatusReg csr,
1627                       uint8_t rs1);
1628   void GenInstrShiftW_ri(bool arithshift, uint8_t funct3, Register rd,
1629                          Register rs1, uint8_t shamt);
1630   void GenInstrALUW_rr(uint8_t funct7, uint8_t funct3, Register rd,
1631                        Register rs1, Register rs2);
1632   void GenInstrPriv(uint8_t funct7, Register rs1, Register rs2);
1633   void GenInstrLoadFP_ri(uint8_t funct3, FPURegister rd, Register rs1,
1634                          int16_t imm12);
1635   void GenInstrStoreFP_rri(uint8_t funct3, Register rs1, FPURegister rs2,
1636                            int16_t imm12);
1637   void GenInstrALUFP_rr(uint8_t funct7, uint8_t funct3, FPURegister rd,
1638                         FPURegister rs1, FPURegister rs2);
1639   void GenInstrALUFP_rr(uint8_t funct7, uint8_t funct3, FPURegister rd,
1640                         Register rs1, Register rs2);
1641   void GenInstrALUFP_rr(uint8_t funct7, uint8_t funct3, FPURegister rd,
1642                         FPURegister rs1, Register rs2);
1643   void GenInstrALUFP_rr(uint8_t funct7, uint8_t funct3, Register rd,
1644                         FPURegister rs1, Register rs2);
1645   void GenInstrALUFP_rr(uint8_t funct7, uint8_t funct3, Register rd,
1646                         FPURegister rs1, FPURegister rs2);
1647 
1648   // ----------------------------RVV------------------------------------------
1649   // vsetvl
1650   void GenInstrV(Register rd, Register rs1, Register rs2);
1651   // vsetvli
1652   void GenInstrV(Register rd, Register rs1, uint32_t zimm);
1653   // OPIVV OPFVV OPMVV
1654   void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, VRegister vs1,
1655                  VRegister vs2, MaskType mask = NoMask);
1656   void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, int8_t vs1,
1657                  VRegister vs2, MaskType mask = NoMask);
1658   void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, VRegister vs2,
1659                  MaskType mask = NoMask);
1660   // OPMVV OPFVV
1661   void GenInstrV(uint8_t funct6, Opcode opcode, Register rd, VRegister vs1,
1662                  VRegister vs2, MaskType mask = NoMask);
1663   // OPFVV
1664   void GenInstrV(uint8_t funct6, Opcode opcode, FPURegister fd, VRegister vs1,
1665                  VRegister vs2, MaskType mask = NoMask);
1666 
1667   // OPIVX OPMVX
1668   void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, Register rs1,
1669                  VRegister vs2, MaskType mask = NoMask);
1670   // OPFVF
1671   void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, FPURegister fs1,
1672                  VRegister vs2, MaskType mask = NoMask);
1673   // OPMVX
1674   void GenInstrV(uint8_t funct6, Register rd, Register rs1, VRegister vs2,
1675                  MaskType mask = NoMask);
1676   // OPIVI
1677   void GenInstrV(uint8_t funct6, VRegister vd, int8_t simm5, VRegister vs2,
1678                  MaskType mask = NoMask);
1679 
1680   // VL VS
1681   void GenInstrV(Opcode opcode, uint8_t width, VRegister vd, Register rs1,
1682                  uint8_t umop, MaskType mask, uint8_t IsMop, bool IsMew,
1683                  uint8_t Nf);
1684 
1685   void GenInstrV(Opcode opcode, uint8_t width, VRegister vd, Register rs1,
1686                  Register rs2, MaskType mask, uint8_t IsMop, bool IsMew,
1687                  uint8_t Nf);
1688   // VL VS AMO
1689   void GenInstrV(Opcode opcode, uint8_t width, VRegister vd, Register rs1,
1690                  VRegister vs2, MaskType mask, uint8_t IsMop, bool IsMew,
1691                  uint8_t Nf);
1692   // vmv_xs vcpop_m vfirst_m
1693   void GenInstrV(uint8_t funct6, Opcode opcode, Register rd, uint8_t vs1,
1694                  VRegister vs2, MaskType mask);
1695   // Labels.
1696   void print(const Label* L);
1697   void bind_to(Label* L, int pos);
1698   void next(Label* L, bool is_internal);
1699 
1700   // One trampoline consists of:
1701   // - space for trampoline slots,
1702   // - space for labels.
1703   //
1704   // Space for trampoline slots is equal to slot_count * 2 * kInstrSize.
1705   // Space for trampoline slots precedes space for labels. Each label is of one
1706   // instruction size, so total amount for labels is equal to
1707   // label_count *  kInstrSize.
1708   class Trampoline {
1709    public:
Trampoline()1710     Trampoline() {
1711       start_ = 0;
1712       next_slot_ = 0;
1713       free_slot_count_ = 0;
1714       end_ = 0;
1715     }
Trampoline(int start,int slot_count)1716     Trampoline(int start, int slot_count) {
1717       start_ = start;
1718       next_slot_ = start;
1719       free_slot_count_ = slot_count;
1720       end_ = start + slot_count * kTrampolineSlotsSize;
1721     }
start()1722     int start() { return start_; }
end()1723     int end() { return end_; }
take_slot()1724     int take_slot() {
1725       int trampoline_slot = kInvalidSlotPos;
1726       if (free_slot_count_ <= 0) {
1727         // We have run out of space on trampolines.
1728         // Make sure we fail in debug mode, so we become aware of each case
1729         // when this happens.
1730         DCHECK(0);
1731         // Internal exception will be caught.
1732       } else {
1733         trampoline_slot = next_slot_;
1734         free_slot_count_--;
1735         next_slot_ += kTrampolineSlotsSize;
1736       }
1737       return trampoline_slot;
1738     }
1739 
1740    private:
1741     int start_;
1742     int end_;
1743     int next_slot_;
1744     int free_slot_count_;
1745   };
1746 
1747   int32_t get_trampoline_entry(int32_t pos);
1748   int unbound_labels_count_;
1749   // After trampoline is emitted, long branches are used in generated code for
1750   // the forward branches whose target offsets could be beyond reach of branch
1751   // instruction. We use this information to trigger different mode of
1752   // branch instruction generation, where we use jump instructions rather
1753   // than regular branch instructions.
1754   bool trampoline_emitted_ = false;
1755   static constexpr int kInvalidSlotPos = -1;
1756 
1757   // Internal reference positions, required for unbounded internal reference
1758   // labels.
1759   std::set<int64_t> internal_reference_positions_;
is_internal_reference(Label * L)1760   bool is_internal_reference(Label* L) {
1761     return internal_reference_positions_.find(L->pos()) !=
1762            internal_reference_positions_.end();
1763   }
1764 
1765   Trampoline trampoline_;
1766   bool internal_trampoline_exception_;
1767 
1768   RegList scratch_register_list_;
1769 
1770  private:
1771   ConstantPool constpool_;
1772 
1773   void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
1774 
1775   int WriteCodeComments();
1776 
1777   friend class RegExpMacroAssemblerRISCV;
1778   friend class RelocInfo;
1779   friend class BlockTrampolinePoolScope;
1780   friend class EnsureSpace;
1781   friend class ConstantPool;
1782 };
1783 
1784 class EnsureSpace {
1785  public:
1786   explicit inline EnsureSpace(Assembler* assembler);
1787 };
1788 
1789 class V8_EXPORT_PRIVATE UseScratchRegisterScope {
1790  public:
1791   explicit UseScratchRegisterScope(Assembler* assembler);
1792   ~UseScratchRegisterScope();
1793 
1794   Register Acquire();
1795   bool hasAvailable() const;
Include(const RegList & list)1796   void Include(const RegList& list) { *available_ |= list; }
Exclude(const RegList & list)1797   void Exclude(const RegList& list) {
1798     *available_ &= RegList::FromBits(~list.bits());
1799   }
1800   void Include(const Register& reg1, const Register& reg2 = no_reg) {
1801     RegList list({reg1, reg2});
1802     Include(list);
1803   }
1804   void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
1805     RegList list({reg1, reg2});
1806     Exclude(list);
1807   }
1808 
1809  private:
1810   RegList* available_;
1811   RegList old_available_;
1812 };
1813 
1814 class LoadStoreLaneParams {
1815  public:
1816   int sz;
1817   uint8_t laneidx;
1818 
1819   LoadStoreLaneParams(MachineRepresentation rep, uint8_t laneidx);
1820 
1821  private:
LoadStoreLaneParams(uint8_t laneidx,int sz,int lanes)1822   LoadStoreLaneParams(uint8_t laneidx, int sz, int lanes)
1823       : sz(sz), laneidx(laneidx % lanes) {}
1824 };
1825 
1826 }  // namespace internal
1827 }  // namespace v8
1828 
1829 #endif  // V8_CODEGEN_RISCV64_ASSEMBLER_RISCV64_H_
1830