• 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 #if V8_TARGET_ARCH_RISCV64
36 
37 #include "src/codegen/riscv64/assembler-riscv64.h"
38 
39 #include "src/base/cpu.h"
40 #include "src/codegen/riscv64/assembler-riscv64-inl.h"
41 #include "src/codegen/safepoint-table.h"
42 #include "src/codegen/string-constants.h"
43 #include "src/deoptimizer/deoptimizer.h"
44 #include "src/diagnostics/disasm.h"
45 #include "src/diagnostics/disassembler.h"
46 #include "src/objects/heap-number-inl.h"
47 
48 namespace v8 {
49 namespace internal {
50 // Get the CPU features enabled by the build. For cross compilation the
51 // preprocessor symbols CAN_USE_FPU_INSTRUCTIONS
52 // can be defined to enable FPU instructions when building the
53 // snapshot.
CpuFeaturesImpliedByCompiler()54 static unsigned CpuFeaturesImpliedByCompiler() {
55   unsigned answer = 0;
56 #ifdef CAN_USE_FPU_INSTRUCTIONS
57   answer |= 1u << FPU;
58 #endif  // def CAN_USE_FPU_INSTRUCTIONS
59 
60 #if (defined CAN_USE_RVV_INSTRUCTIONS)
61   answer |= 1u << RISCV_SIMD;
62 #endif  // def CAN_USE_RVV_INSTRUCTIONS || USE_SIMULATOR
63   return answer;
64 }
65 
SupportsWasmSimd128()66 bool CpuFeatures::SupportsWasmSimd128() { return IsSupported(RISCV_SIMD); }
67 
ProbeImpl(bool cross_compile)68 void CpuFeatures::ProbeImpl(bool cross_compile) {
69   supported_ |= CpuFeaturesImpliedByCompiler();
70   // Only use statically determined features for cross compile (snapshot).
71   if (cross_compile) return;
72   // Probe for additional features at runtime.
73   base::CPU cpu;
74   if (cpu.has_fpu()) supported_ |= 1u << FPU;
75   if (cpu.has_rvv()) supported_ |= 1u << RISCV_SIMD;
76   // Set a static value on whether SIMD is supported.
77   // This variable is only used for certain archs to query SupportWasmSimd128()
78   // at runtime in builtins using an extern ref. Other callers should use
79   // CpuFeatures::SupportWasmSimd128().
80   CpuFeatures::supports_wasm_simd_128_ = CpuFeatures::SupportsWasmSimd128();
81 }
82 
PrintTarget()83 void CpuFeatures::PrintTarget() {}
PrintFeatures()84 void CpuFeatures::PrintFeatures() {}
ToNumber(Register reg)85 int ToNumber(Register reg) {
86   DCHECK(reg.is_valid());
87   const int kNumbers[] = {
88       0,   // zero_reg
89       1,   // ra
90       2,   // sp
91       3,   // gp
92       4,   // tp
93       5,   // t0
94       6,   // t1
95       7,   // t2
96       8,   // s0/fp
97       9,   // s1
98       10,  // a0
99       11,  // a1
100       12,  // a2
101       13,  // a3
102       14,  // a4
103       15,  // a5
104       16,  // a6
105       17,  // a7
106       18,  // s2
107       19,  // s3
108       20,  // s4
109       21,  // s5
110       22,  // s6
111       23,  // s7
112       24,  // s8
113       25,  // s9
114       26,  // s10
115       27,  // s11
116       28,  // t3
117       29,  // t4
118       30,  // t5
119       31,  // t6
120   };
121   return kNumbers[reg.code()];
122 }
123 
ToRegister(int num)124 Register ToRegister(int num) {
125   DCHECK(num >= 0 && num < kNumRegisters);
126   const Register kRegisters[] = {
127       zero_reg, ra, sp, gp, tp, t0, t1, t2, fp, s1, a0,  a1,  a2, a3, a4, a5,
128       a6,       a7, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, t3, t4, t5, t6};
129   return kRegisters[num];
130 }
131 
132 // -----------------------------------------------------------------------------
133 // Implementation of RelocInfo.
134 
135 const int RelocInfo::kApplyMask =
136     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
137     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
138     RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET);
139 
IsCodedSpecially()140 bool RelocInfo::IsCodedSpecially() {
141   // The deserializer needs to know whether a pointer is specially coded.  Being
142   // specially coded on RISC-V means that it is a lui/addi instruction, and that
143   // is always the case inside code objects.
144   return true;
145 }
146 
IsInConstantPool()147 bool RelocInfo::IsInConstantPool() { return false; }
148 
wasm_call_tag() const149 uint32_t RelocInfo::wasm_call_tag() const {
150   DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL);
151   return static_cast<uint32_t>(
152       Assembler::target_address_at(pc_, constant_pool_));
153 }
154 
155 // -----------------------------------------------------------------------------
156 // Implementation of Operand and MemOperand.
157 // See assembler-riscv64-inl.h for inlined constructors.
158 
Operand(Handle<HeapObject> handle)159 Operand::Operand(Handle<HeapObject> handle)
160     : rm_(no_reg), rmode_(RelocInfo::FULL_EMBEDDED_OBJECT) {
161   value_.immediate = static_cast<intptr_t>(handle.address());
162 }
163 
EmbeddedNumber(double value)164 Operand Operand::EmbeddedNumber(double value) {
165   int32_t smi;
166   if (DoubleToSmiInteger(value, &smi)) return Operand(Smi::FromInt(smi));
167   Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
168   result.is_heap_object_request_ = true;
169   result.value_.heap_object_request = HeapObjectRequest(value);
170   return result;
171 }
172 
EmbeddedStringConstant(const StringConstantBase * str)173 Operand Operand::EmbeddedStringConstant(const StringConstantBase* str) {
174   Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
175   result.is_heap_object_request_ = true;
176   result.value_.heap_object_request = HeapObjectRequest(str);
177   return result;
178 }
179 
MemOperand(Register rm,int32_t offset)180 MemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) {
181   offset_ = offset;
182 }
183 
MemOperand(Register rm,int32_t unit,int32_t multiplier,OffsetAddend offset_addend)184 MemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier,
185                        OffsetAddend offset_addend)
186     : Operand(rm) {
187   offset_ = unit * multiplier + offset_addend;
188 }
189 
AllocateAndInstallRequestedHeapObjects(Isolate * isolate)190 void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
191   DCHECK_IMPLIES(isolate == nullptr, heap_object_requests_.empty());
192   for (auto& request : heap_object_requests_) {
193     Handle<HeapObject> object;
194     switch (request.kind()) {
195       case HeapObjectRequest::kHeapNumber:
196         object = isolate->factory()->NewHeapNumber<AllocationType::kOld>(
197             request.heap_number());
198         break;
199       case HeapObjectRequest::kStringConstant:
200         const StringConstantBase* str = request.string();
201         CHECK_NOT_NULL(str);
202         object = str->AllocateStringConstant(isolate);
203         break;
204     }
205     Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
206     set_target_value_at(pc, reinterpret_cast<uint64_t>(object.location()));
207   }
208 }
209 
210 // -----------------------------------------------------------------------------
211 // Specific instructions, constants, and masks.
212 
Assembler(const AssemblerOptions & options,std::unique_ptr<AssemblerBuffer> buffer)213 Assembler::Assembler(const AssemblerOptions& options,
214                      std::unique_ptr<AssemblerBuffer> buffer)
215     : AssemblerBase(options, std::move(buffer)),
216       VU(this),
217       scratch_register_list_({t3, t5}),
218       constpool_(this) {
219   reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
220 
221   last_trampoline_pool_end_ = 0;
222   no_trampoline_pool_before_ = 0;
223   trampoline_pool_blocked_nesting_ = 0;
224   // We leave space (16 * kTrampolineSlotsSize)
225   // for BlockTrampolinePoolScope buffer.
226   next_buffer_check_ = FLAG_force_long_branches
227                            ? kMaxInt
228                            : kMaxBranchOffset - kTrampolineSlotsSize * 16;
229   internal_trampoline_exception_ = false;
230   last_bound_pos_ = 0;
231 
232   trampoline_emitted_ = FLAG_force_long_branches;
233   unbound_labels_count_ = 0;
234   block_buffer_growth_ = false;
235 }
236 
AbortedCodeGeneration()237 void Assembler::AbortedCodeGeneration() { constpool_.Clear(); }
~Assembler()238 Assembler::~Assembler() { CHECK(constpool_.IsEmpty()); }
239 
GetCode(Isolate * isolate,CodeDesc * desc,SafepointTableBuilder * safepoint_table_builder,int handler_table_offset)240 void Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
241                         SafepointTableBuilder* safepoint_table_builder,
242                         int handler_table_offset) {
243   // As a crutch to avoid having to add manual Align calls wherever we use a
244   // raw workflow to create Code objects (mostly in tests), add another Align
245   // call here. It does no harm - the end of the Code object is aligned to the
246   // (larger) kCodeAlignment anyways.
247   // TODO(jgruber): Consider moving responsibility for proper alignment to
248   // metadata table builders (safepoint, handler, constant pool, code
249   // comments).
250   DataAlign(Code::kMetadataAlignment);
251 
252   ForceConstantPoolEmissionWithoutJump();
253 
254   int code_comments_size = WriteCodeComments();
255 
256   DCHECK(pc_ <= reloc_info_writer.pos());  // No overlap.
257 
258   AllocateAndInstallRequestedHeapObjects(isolate);
259 
260   // Set up code descriptor.
261   // TODO(jgruber): Reconsider how these offsets and sizes are maintained up to
262   // this point to make CodeDesc initialization less fiddly.
263 
264   static constexpr int kConstantPoolSize = 0;
265   const int instruction_size = pc_offset();
266   const int code_comments_offset = instruction_size - code_comments_size;
267   const int constant_pool_offset = code_comments_offset - kConstantPoolSize;
268   const int handler_table_offset2 = (handler_table_offset == kNoHandlerTable)
269                                         ? constant_pool_offset
270                                         : handler_table_offset;
271   const int safepoint_table_offset =
272       (safepoint_table_builder == kNoSafepointTable)
273           ? handler_table_offset2
274           : safepoint_table_builder->safepoint_table_offset();
275   const int reloc_info_offset =
276       static_cast<int>(reloc_info_writer.pos() - buffer_->start());
277   CodeDesc::Initialize(desc, this, safepoint_table_offset,
278                        handler_table_offset2, constant_pool_offset,
279                        code_comments_offset, reloc_info_offset);
280 }
281 
Align(int m)282 void Assembler::Align(int m) {
283   DCHECK(m >= 4 && base::bits::IsPowerOfTwo(m));
284   while ((pc_offset() & (m - 1)) != 0) {
285     NOP();
286   }
287 }
288 
CodeTargetAlign()289 void Assembler::CodeTargetAlign() {
290   // No advantage to aligning branch/call targets to more than
291   // single instruction, that I am aware of.
292   Align(4);
293 }
294 
295 // Labels refer to positions in the (to be) generated code.
296 // There are bound, linked, and unused labels.
297 //
298 // Bound labels refer to known positions in the already
299 // generated code. pos() is the position the label refers to.
300 //
301 // Linked labels refer to unknown positions in the code
302 // to be generated; pos() is the position of the last
303 // instruction using the label.
304 
305 // The link chain is terminated by a value in the instruction of 0,
306 // which is an otherwise illegal value (branch 0 is inf loop). When this case
307 // is detected, return an position of -1, an otherwise illegal position.
308 const int kEndOfChain = -1;
309 const int kEndOfJumpChain = 0;
310 
IsBranch(Instr instr)311 bool Assembler::IsBranch(Instr instr) {
312   return (instr & kBaseOpcodeMask) == BRANCH;
313 }
314 
IsCBranch(Instr instr)315 bool Assembler::IsCBranch(Instr instr) {
316   int Op = instr & kRvcOpcodeMask;
317   return Op == RO_C_BNEZ || Op == RO_C_BEQZ;
318 }
IsJump(Instr instr)319 bool Assembler::IsJump(Instr instr) {
320   int Op = instr & kBaseOpcodeMask;
321   return Op == JAL || Op == JALR;
322 }
323 
IsNop(Instr instr)324 bool Assembler::IsNop(Instr instr) { return instr == kNopByte; }
325 
IsJal(Instr instr)326 bool Assembler::IsJal(Instr instr) { return (instr & kBaseOpcodeMask) == JAL; }
327 
IsJalr(Instr instr)328 bool Assembler::IsJalr(Instr instr) {
329   return (instr & kBaseOpcodeMask) == JALR;
330 }
331 
IsCJal(Instr instr)332 bool Assembler::IsCJal(Instr instr) {
333   return (instr & kRvcOpcodeMask) == RO_C_J;
334 }
335 
IsLui(Instr instr)336 bool Assembler::IsLui(Instr instr) { return (instr & kBaseOpcodeMask) == LUI; }
IsAuipc(Instr instr)337 bool Assembler::IsAuipc(Instr instr) {
338   return (instr & kBaseOpcodeMask) == AUIPC;
339 }
IsAddiw(Instr instr)340 bool Assembler::IsAddiw(Instr instr) {
341   return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_ADDIW;
342 }
IsAddi(Instr instr)343 bool Assembler::IsAddi(Instr instr) {
344   return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_ADDI;
345 }
IsOri(Instr instr)346 bool Assembler::IsOri(Instr instr) {
347   return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_ORI;
348 }
IsSlli(Instr instr)349 bool Assembler::IsSlli(Instr instr) {
350   return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_SLLI;
351 }
352 
IsLd(Instr instr)353 bool Assembler::IsLd(Instr instr) {
354   return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_LD;
355 }
356 
target_at(int pos,bool is_internal)357 int Assembler::target_at(int pos, bool is_internal) {
358   if (is_internal) {
359     int64_t* p = reinterpret_cast<int64_t*>(buffer_start_ + pos);
360     int64_t address = *p;
361     if (address == kEndOfJumpChain) {
362       return kEndOfChain;
363     } else {
364       int64_t instr_address = reinterpret_cast<int64_t>(p);
365       DCHECK(instr_address - address < INT_MAX);
366       int delta = static_cast<int>(instr_address - address);
367       DCHECK(pos > delta);
368       return pos - delta;
369     }
370   }
371   Instruction* instruction = Instruction::At(buffer_start_ + pos);
372   DEBUG_PRINTF("target_at: %p (%d)\n\t",
373                reinterpret_cast<Instr*>(buffer_start_ + pos), pos);
374   Instr instr = instruction->InstructionBits();
375   disassembleInstr(instruction->InstructionBits());
376 
377   switch (instruction->InstructionOpcodeType()) {
378     case BRANCH: {
379       int32_t imm13 = BranchOffset(instr);
380       if (imm13 == kEndOfJumpChain) {
381         // EndOfChain sentinel is returned directly, not relative to pc or pos.
382         return kEndOfChain;
383       } else {
384         return pos + imm13;
385       }
386     }
387     case JAL: {
388       int32_t imm21 = JumpOffset(instr);
389       if (imm21 == kEndOfJumpChain) {
390         // EndOfChain sentinel is returned directly, not relative to pc or pos.
391         return kEndOfChain;
392       } else {
393         return pos + imm21;
394       }
395     }
396     case JALR: {
397       int32_t imm12 = instr >> 20;
398       if (imm12 == kEndOfJumpChain) {
399         // EndOfChain sentinel is returned directly, not relative to pc or pos.
400         return kEndOfChain;
401       } else {
402         return pos + imm12;
403       }
404     }
405     case LUI: {
406       Address pc = reinterpret_cast<Address>(buffer_start_ + pos);
407       pc = target_address_at(pc);
408       uint64_t instr_address = reinterpret_cast<uint64_t>(buffer_start_ + pos);
409       uint64_t imm = reinterpret_cast<uint64_t>(pc);
410       if (imm == kEndOfJumpChain) {
411         return kEndOfChain;
412       } else {
413         DCHECK(instr_address - imm < INT_MAX);
414         int32_t delta = static_cast<int32_t>(instr_address - imm);
415         DCHECK(pos > delta);
416         return pos - delta;
417       }
418     }
419     case AUIPC: {
420       Instr instr_auipc = instr;
421       Instr instr_I = instr_at(pos + 4);
422       DCHECK(IsJalr(instr_I) || IsAddi(instr_I));
423       int32_t offset = BrachlongOffset(instr_auipc, instr_I);
424       if (offset == kEndOfJumpChain) return kEndOfChain;
425       return offset + pos;
426     }
427     case RO_C_J: {
428       int32_t offset = instruction->RvcImm11CJValue();
429       if (offset == kEndOfJumpChain) return kEndOfChain;
430       return offset + pos;
431     }
432     case RO_C_BNEZ:
433     case RO_C_BEQZ: {
434       int32_t offset = instruction->RvcImm8BValue();
435       if (offset == kEndOfJumpChain) return kEndOfChain;
436       return pos + offset;
437     }
438     default: {
439       if (instr == kEndOfJumpChain) {
440         return kEndOfChain;
441       } else {
442         int32_t imm18 =
443             ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
444         return (imm18 + pos);
445       }
446     }
447   }
448 }
449 
SetBranchOffset(int32_t pos,int32_t target_pos,Instr instr)450 static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos,
451                                     Instr instr) {
452   int32_t imm = target_pos - pos;
453   DCHECK_EQ(imm & 1, 0);
454   DCHECK(is_intn(imm, Assembler::kBranchOffsetBits));
455 
456   instr &= ~kBImm12Mask;
457   int32_t imm12 = ((imm & 0x800) >> 4) |   // bit  11
458                   ((imm & 0x1e) << 7) |    // bits 4-1
459                   ((imm & 0x7e0) << 20) |  // bits 10-5
460                   ((imm & 0x1000) << 19);  // bit 12
461 
462   return instr | (imm12 & kBImm12Mask);
463 }
464 
SetLdOffset(int32_t offset,Instr instr)465 static inline Instr SetLdOffset(int32_t offset, Instr instr) {
466   DCHECK(Assembler::IsLd(instr));
467   DCHECK(is_int12(offset));
468   instr &= ~kImm12Mask;
469   int32_t imm12 = offset << kImm12Shift;
470   return instr | (imm12 & kImm12Mask);
471 }
472 
SetAuipcOffset(int32_t offset,Instr instr)473 static inline Instr SetAuipcOffset(int32_t offset, Instr instr) {
474   DCHECK(Assembler::IsAuipc(instr));
475   DCHECK(is_int20(offset));
476   instr = (instr & ~kImm31_12Mask) | ((offset & kImm19_0Mask) << 12);
477   return instr;
478 }
479 
SetJalrOffset(int32_t offset,Instr instr)480 static inline Instr SetJalrOffset(int32_t offset, Instr instr) {
481   DCHECK(Assembler::IsJalr(instr));
482   DCHECK(is_int12(offset));
483   instr &= ~kImm12Mask;
484   int32_t imm12 = offset << kImm12Shift;
485   DCHECK(Assembler::IsJalr(instr | (imm12 & kImm12Mask)));
486   DCHECK_EQ(Assembler::JalrOffset(instr | (imm12 & kImm12Mask)), offset);
487   return instr | (imm12 & kImm12Mask);
488 }
489 
SetJalOffset(int32_t pos,int32_t target_pos,Instr instr)490 static inline Instr SetJalOffset(int32_t pos, int32_t target_pos, Instr instr) {
491   DCHECK(Assembler::IsJal(instr));
492   int32_t imm = target_pos - pos;
493   DCHECK_EQ(imm & 1, 0);
494   DCHECK(is_intn(imm, Assembler::kJumpOffsetBits));
495 
496   instr &= ~kImm20Mask;
497   int32_t imm20 = (imm & 0xff000) |          // bits 19-12
498                   ((imm & 0x800) << 9) |     // bit  11
499                   ((imm & 0x7fe) << 20) |    // bits 10-1
500                   ((imm & 0x100000) << 11);  // bit  20
501 
502   return instr | (imm20 & kImm20Mask);
503 }
504 
SetCJalOffset(int32_t pos,int32_t target_pos,Instr instr)505 static inline ShortInstr SetCJalOffset(int32_t pos, int32_t target_pos,
506                                        Instr instr) {
507   DCHECK(Assembler::IsCJal(instr));
508   int32_t imm = target_pos - pos;
509   DCHECK_EQ(imm & 1, 0);
510   DCHECK(is_intn(imm, Assembler::kCJalOffsetBits));
511   instr &= ~kImm11Mask;
512   int16_t imm11 = ((imm & 0x800) >> 1) | ((imm & 0x400) >> 4) |
513                   ((imm & 0x300) >> 1) | ((imm & 0x80) >> 3) |
514                   ((imm & 0x40) >> 1) | ((imm & 0x20) >> 5) |
515                   ((imm & 0x10) << 5) | (imm & 0xe);
516   imm11 = imm11 << kImm11Shift;
517   DCHECK(Assembler::IsCJal(instr | (imm11 & kImm11Mask)));
518   return instr | (imm11 & kImm11Mask);
519 }
SetCBranchOffset(int32_t pos,int32_t target_pos,Instr instr)520 static inline Instr SetCBranchOffset(int32_t pos, int32_t target_pos,
521                                      Instr instr) {
522   DCHECK(Assembler::IsCBranch(instr));
523   int32_t imm = target_pos - pos;
524   DCHECK_EQ(imm & 1, 0);
525   DCHECK(is_intn(imm, Assembler::kCBranchOffsetBits));
526 
527   instr &= ~kRvcBImm8Mask;
528   int32_t imm8 = ((imm & 0x20) >> 5) | ((imm & 0x6)) | ((imm & 0xc0) >> 3) |
529                  ((imm & 0x18) << 2) | ((imm & 0x100) >> 1);
530   imm8 = ((imm8 & 0x1f) << 2) | ((imm8 & 0xe0) << 5);
531   DCHECK(Assembler::IsCBranch(instr | imm8 & kRvcBImm8Mask));
532 
533   return instr | (imm8 & kRvcBImm8Mask);
534 }
535 
target_at_put(int pos,int target_pos,bool is_internal,bool trampoline)536 void Assembler::target_at_put(int pos, int target_pos, bool is_internal,
537                               bool trampoline) {
538   if (is_internal) {
539     uint64_t imm = reinterpret_cast<uint64_t>(buffer_start_) + target_pos;
540     *reinterpret_cast<uint64_t*>(buffer_start_ + pos) = imm;
541     return;
542   }
543   DEBUG_PRINTF("target_at_put: %p (%d) to %p (%d)\n",
544                reinterpret_cast<Instr*>(buffer_start_ + pos), pos,
545                reinterpret_cast<Instr*>(buffer_start_ + target_pos),
546                target_pos);
547   Instruction* instruction = Instruction::At(buffer_start_ + pos);
548   Instr instr = instruction->InstructionBits();
549 
550   switch (instruction->InstructionOpcodeType()) {
551     case BRANCH: {
552       instr = SetBranchOffset(pos, target_pos, instr);
553       instr_at_put(pos, instr);
554     } break;
555     case JAL: {
556       DCHECK(IsJal(instr));
557       instr = SetJalOffset(pos, target_pos, instr);
558       instr_at_put(pos, instr);
559     } break;
560     case LUI: {
561       Address pc = reinterpret_cast<Address>(buffer_start_ + pos);
562       set_target_value_at(
563           pc, reinterpret_cast<uint64_t>(buffer_start_ + target_pos));
564     } break;
565     case AUIPC: {
566       Instr instr_auipc = instr;
567       Instr instr_I = instr_at(pos + 4);
568       DCHECK(IsJalr(instr_I) || IsAddi(instr_I));
569 
570       int64_t offset = target_pos - pos;
571       if (is_int21(offset) && IsJalr(instr_I) && trampoline) {
572         DCHECK(is_int21(offset) && ((offset & 1) == 0));
573         Instr instr = JAL;
574         instr = SetJalOffset(pos, target_pos, instr);
575         DCHECK(IsJal(instr));
576         DCHECK(JumpOffset(instr) == offset);
577         instr_at_put(pos, instr);
578         instr_at_put(pos + 4, kNopByte);
579       } else {
580         CHECK(is_int32(offset + 0x800));
581 
582         int32_t Hi20 = (((int32_t)offset + 0x800) >> 12);
583         int32_t Lo12 = (int32_t)offset << 20 >> 20;
584 
585         instr_auipc =
586             (instr_auipc & ~kImm31_12Mask) | ((Hi20 & kImm19_0Mask) << 12);
587         instr_at_put(pos, instr_auipc);
588 
589         const int kImm31_20Mask = ((1 << 12) - 1) << 20;
590         const int kImm11_0Mask = ((1 << 12) - 1);
591         instr_I = (instr_I & ~kImm31_20Mask) | ((Lo12 & kImm11_0Mask) << 20);
592         instr_at_put(pos + 4, instr_I);
593       }
594     } break;
595     case RO_C_J: {
596       ShortInstr short_instr = SetCJalOffset(pos, target_pos, instr);
597       instr_at_put(pos, short_instr);
598     } break;
599     case RO_C_BNEZ:
600     case RO_C_BEQZ: {
601       instr = SetCBranchOffset(pos, target_pos, instr);
602       instr_at_put(pos, instr);
603     } break;
604     default: {
605       // Emitted label constant, not part of a branch.
606       // Make label relative to Code pointer of generated Code object.
607       instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
608     } break;
609   }
610   disassembleInstr(instr);
611 }
612 
print(const Label * L)613 void Assembler::print(const Label* L) {
614   if (L->is_unused()) {
615     PrintF("unused label\n");
616   } else if (L->is_bound()) {
617     PrintF("bound label to %d\n", L->pos());
618   } else if (L->is_linked()) {
619     Label l;
620     l.link_to(L->pos());
621     PrintF("unbound label");
622     while (l.is_linked()) {
623       PrintF("@ %d ", l.pos());
624       Instr instr = instr_at(l.pos());
625       if ((instr & ~kImm16Mask) == 0) {
626         PrintF("value\n");
627       } else {
628         PrintF("%d\n", instr);
629       }
630       next(&l, is_internal_reference(&l));
631     }
632   } else {
633     PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
634   }
635 }
636 
bind_to(Label * L,int pos)637 void Assembler::bind_to(Label* L, int pos) {
638   DCHECK(0 <= pos && pos <= pc_offset());  // Must have valid binding position.
639   DEBUG_PRINTF("binding %d to label %p\n", pos, L);
640   int trampoline_pos = kInvalidSlotPos;
641   bool is_internal = false;
642   if (L->is_linked() && !trampoline_emitted_) {
643     unbound_labels_count_--;
644     if (!is_internal_reference(L)) {
645       next_buffer_check_ += kTrampolineSlotsSize;
646     }
647   }
648 
649   while (L->is_linked()) {
650     int fixup_pos = L->pos();
651     int dist = pos - fixup_pos;
652     is_internal = is_internal_reference(L);
653     next(L, is_internal);  // Call next before overwriting link with target
654                            // at fixup_pos.
655     Instr instr = instr_at(fixup_pos);
656     DEBUG_PRINTF("\tfixup: %d to %d\n", fixup_pos, dist);
657     if (is_internal) {
658       target_at_put(fixup_pos, pos, is_internal);
659     } else {
660       if (IsBranch(instr)) {
661         if (dist > kMaxBranchOffset) {
662           if (trampoline_pos == kInvalidSlotPos) {
663             trampoline_pos = get_trampoline_entry(fixup_pos);
664             CHECK_NE(trampoline_pos, kInvalidSlotPos);
665           }
666           CHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
667           DEBUG_PRINTF("\t\ttrampolining: %d\n", trampoline_pos);
668           target_at_put(fixup_pos, trampoline_pos, false, true);
669           fixup_pos = trampoline_pos;
670         }
671         target_at_put(fixup_pos, pos, false);
672       } else if (IsJal(instr)) {
673         if (dist > kMaxJumpOffset) {
674           if (trampoline_pos == kInvalidSlotPos) {
675             trampoline_pos = get_trampoline_entry(fixup_pos);
676             CHECK_NE(trampoline_pos, kInvalidSlotPos);
677           }
678           CHECK((trampoline_pos - fixup_pos) <= kMaxJumpOffset);
679           DEBUG_PRINTF("\t\ttrampolining: %d\n", trampoline_pos);
680           target_at_put(fixup_pos, trampoline_pos, false, true);
681           fixup_pos = trampoline_pos;
682         }
683         target_at_put(fixup_pos, pos, false);
684       } else {
685         target_at_put(fixup_pos, pos, false);
686       }
687     }
688   }
689   L->bind_to(pos);
690 
691   // Keep track of the last bound label so we don't eliminate any instructions
692   // before a bound label.
693   if (pos > last_bound_pos_) last_bound_pos_ = pos;
694 }
695 
bind(Label * L)696 void Assembler::bind(Label* L) {
697   DCHECK(!L->is_bound());  // Label can only be bound once.
698   bind_to(L, pc_offset());
699 }
700 
next(Label * L,bool is_internal)701 void Assembler::next(Label* L, bool is_internal) {
702   DCHECK(L->is_linked());
703   int link = target_at(L->pos(), is_internal);
704   if (link == kEndOfChain) {
705     L->Unuse();
706   } else {
707     DCHECK_GE(link, 0);
708     DEBUG_PRINTF("next: %p to %p (%d)\n", L,
709                  reinterpret_cast<Instr*>(buffer_start_ + link), link);
710     L->link_to(link);
711   }
712 }
713 
is_near(Label * L)714 bool Assembler::is_near(Label* L) {
715   DCHECK(L->is_bound());
716   return is_intn((pc_offset() - L->pos()), kJumpOffsetBits);
717 }
718 
is_near(Label * L,OffsetSize bits)719 bool Assembler::is_near(Label* L, OffsetSize bits) {
720   if (L == nullptr || !L->is_bound()) return true;
721   return is_intn((pc_offset() - L->pos()), bits);
722 }
723 
is_near_branch(Label * L)724 bool Assembler::is_near_branch(Label* L) {
725   DCHECK(L->is_bound());
726   return is_intn((pc_offset() - L->pos()), kBranchOffsetBits);
727 }
728 
BranchOffset(Instr instr)729 int Assembler::BranchOffset(Instr instr) {
730   // | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1|11] | opcode |
731   //  31          25                      11          7
732   int32_t imm13 = ((instr & 0xf00) >> 7) | ((instr & 0x7e000000) >> 20) |
733                   ((instr & 0x80) << 4) | ((instr & 0x80000000) >> 19);
734   imm13 = imm13 << 19 >> 19;
735   return imm13;
736 }
737 
JumpOffset(Instr instr)738 int Assembler::JumpOffset(Instr instr) {
739   int32_t imm21 = ((instr & 0x7fe00000) >> 20) | ((instr & 0x100000) >> 9) |
740                   (instr & 0xff000) | ((instr & 0x80000000) >> 11);
741   imm21 = imm21 << 11 >> 11;
742   return imm21;
743 }
744 
CJumpOffset(Instr instr)745 int Assembler::CJumpOffset(Instr instr) {
746   int32_t imm12 = ((instr & 0x4) << 3) | ((instr & 0x38) >> 2) |
747                   ((instr & 0x40) << 1) | ((instr & 0x80) >> 1) |
748                   ((instr & 0x100) << 2) | ((instr & 0x600) >> 1) |
749                   ((instr & 0x800) >> 7) | ((instr & 0x1000) >> 1);
750   imm12 = imm12 << 20 >> 20;
751   return imm12;
752 }
753 
BrachlongOffset(Instr auipc,Instr instr_I)754 int Assembler::BrachlongOffset(Instr auipc, Instr instr_I) {
755   DCHECK(reinterpret_cast<Instruction*>(&instr_I)->InstructionType() ==
756          InstructionBase::kIType);
757   DCHECK(IsAuipc(auipc));
758   DCHECK_EQ((auipc & kRdFieldMask) >> kRdShift,
759             (instr_I & kRs1FieldMask) >> kRs1Shift);
760   int32_t imm_auipc = AuipcOffset(auipc);
761   int32_t imm12 = static_cast<int32_t>(instr_I & kImm12Mask) >> 20;
762   int32_t offset = imm12 + imm_auipc;
763   return offset;
764 }
765 
PatchBranchlongOffset(Address pc,Instr instr_auipc,Instr instr_jalr,int32_t offset)766 int Assembler::PatchBranchlongOffset(Address pc, Instr instr_auipc,
767                                      Instr instr_jalr, int32_t offset) {
768   DCHECK(IsAuipc(instr_auipc));
769   DCHECK(IsJalr(instr_jalr));
770   CHECK(is_int32(offset + 0x800));
771   int32_t Hi20 = (((int32_t)offset + 0x800) >> 12);
772   int32_t Lo12 = (int32_t)offset << 20 >> 20;
773   instr_at_put(pc, SetAuipcOffset(Hi20, instr_auipc));
774   instr_at_put(pc + 4, SetJalrOffset(Lo12, instr_jalr));
775   DCHECK(offset ==
776          BrachlongOffset(Assembler::instr_at(pc), Assembler::instr_at(pc + 4)));
777   return 2;
778 }
779 
LdOffset(Instr instr)780 int Assembler::LdOffset(Instr instr) {
781   DCHECK(IsLd(instr));
782   int32_t imm12 = static_cast<int32_t>(instr & kImm12Mask) >> 20;
783   return imm12;
784 }
785 
JalrOffset(Instr instr)786 int Assembler::JalrOffset(Instr instr) {
787   DCHECK(IsJalr(instr));
788   int32_t imm12 = static_cast<int32_t>(instr & kImm12Mask) >> 20;
789   return imm12;
790 }
791 
AuipcOffset(Instr instr)792 int Assembler::AuipcOffset(Instr instr) {
793   DCHECK(IsAuipc(instr));
794   int32_t imm20 = static_cast<int32_t>(instr & kImm20Mask);
795   return imm20;
796 }
797 // We have to use a temporary register for things that can be relocated even
798 // if they can be encoded in RISC-V's 12 bits of immediate-offset instruction
799 // space.  There is no guarantee that the relocated location can be similarly
800 // encoded.
MustUseReg(RelocInfo::Mode rmode)801 bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
802   return !RelocInfo::IsNoInfo(rmode);
803 }
804 
disassembleInstr(Instr instr)805 void Assembler::disassembleInstr(Instr instr) {
806   if (!FLAG_riscv_debug) return;
807   disasm::NameConverter converter;
808   disasm::Disassembler disasm(converter);
809   base::EmbeddedVector<char, 128> disasm_buffer;
810 
811   disasm.InstructionDecode(disasm_buffer, reinterpret_cast<byte*>(&instr));
812   DEBUG_PRINTF("%s\n", disasm_buffer.begin());
813 }
814 
815 // ----- Top-level instruction formats match those in the ISA manual
816 // (R, I, S, B, U, J). These match the formats defined in the compiler
GenInstrR(uint8_t funct7,uint8_t funct3,Opcode opcode,Register rd,Register rs1,Register rs2)817 void Assembler::GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode,
818                           Register rd, Register rs1, Register rs2) {
819   DCHECK(is_uint7(funct7) && is_uint3(funct3) && rd.is_valid() &&
820          rs1.is_valid() && rs2.is_valid());
821   Instr instr = opcode | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
822                 (rs1.code() << kRs1Shift) | (rs2.code() << kRs2Shift) |
823                 (funct7 << kFunct7Shift);
824   emit(instr);
825 }
826 
GenInstrR(uint8_t funct7,uint8_t funct3,Opcode opcode,FPURegister rd,FPURegister rs1,FPURegister rs2)827 void Assembler::GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode,
828                           FPURegister rd, FPURegister rs1, FPURegister rs2) {
829   DCHECK(is_uint7(funct7) && is_uint3(funct3) && rd.is_valid() &&
830          rs1.is_valid() && rs2.is_valid());
831   Instr instr = opcode | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
832                 (rs1.code() << kRs1Shift) | (rs2.code() << kRs2Shift) |
833                 (funct7 << kFunct7Shift);
834   emit(instr);
835 }
836 
GenInstrR(uint8_t funct7,uint8_t funct3,Opcode opcode,Register rd,FPURegister rs1,Register rs2)837 void Assembler::GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode,
838                           Register rd, FPURegister rs1, Register rs2) {
839   DCHECK(is_uint7(funct7) && is_uint3(funct3) && rd.is_valid() &&
840          rs1.is_valid() && rs2.is_valid());
841   Instr instr = opcode | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
842                 (rs1.code() << kRs1Shift) | (rs2.code() << kRs2Shift) |
843                 (funct7 << kFunct7Shift);
844   emit(instr);
845 }
846 
GenInstrR(uint8_t funct7,uint8_t funct3,Opcode opcode,FPURegister rd,Register rs1,Register rs2)847 void Assembler::GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode,
848                           FPURegister rd, Register rs1, Register rs2) {
849   DCHECK(is_uint7(funct7) && is_uint3(funct3) && rd.is_valid() &&
850          rs1.is_valid() && rs2.is_valid());
851   Instr instr = opcode | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
852                 (rs1.code() << kRs1Shift) | (rs2.code() << kRs2Shift) |
853                 (funct7 << kFunct7Shift);
854   emit(instr);
855 }
856 
GenInstrR(uint8_t funct7,uint8_t funct3,Opcode opcode,FPURegister rd,FPURegister rs1,Register rs2)857 void Assembler::GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode,
858                           FPURegister rd, FPURegister rs1, Register rs2) {
859   DCHECK(is_uint7(funct7) && is_uint3(funct3) && rd.is_valid() &&
860          rs1.is_valid() && rs2.is_valid());
861   Instr instr = opcode | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
862                 (rs1.code() << kRs1Shift) | (rs2.code() << kRs2Shift) |
863                 (funct7 << kFunct7Shift);
864   emit(instr);
865 }
866 
GenInstrR(uint8_t funct7,uint8_t funct3,Opcode opcode,Register rd,FPURegister rs1,FPURegister rs2)867 void Assembler::GenInstrR(uint8_t funct7, uint8_t funct3, Opcode opcode,
868                           Register rd, FPURegister rs1, FPURegister rs2) {
869   DCHECK(is_uint7(funct7) && is_uint3(funct3) && rd.is_valid() &&
870          rs1.is_valid() && rs2.is_valid());
871   Instr instr = opcode | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
872                 (rs1.code() << kRs1Shift) | (rs2.code() << kRs2Shift) |
873                 (funct7 << kFunct7Shift);
874   emit(instr);
875 }
876 
GenInstrR4(uint8_t funct2,Opcode opcode,Register rd,Register rs1,Register rs2,Register rs3,RoundingMode frm)877 void Assembler::GenInstrR4(uint8_t funct2, Opcode opcode, Register rd,
878                            Register rs1, Register rs2, Register rs3,
879                            RoundingMode frm) {
880   DCHECK(is_uint2(funct2) && rd.is_valid() && rs1.is_valid() &&
881          rs2.is_valid() && rs3.is_valid() && is_uint3(frm));
882   Instr instr = opcode | (rd.code() << kRdShift) | (frm << kFunct3Shift) |
883                 (rs1.code() << kRs1Shift) | (rs2.code() << kRs2Shift) |
884                 (funct2 << kFunct2Shift) | (rs3.code() << kRs3Shift);
885   emit(instr);
886 }
887 
GenInstrR4(uint8_t funct2,Opcode opcode,FPURegister rd,FPURegister rs1,FPURegister rs2,FPURegister rs3,RoundingMode frm)888 void Assembler::GenInstrR4(uint8_t funct2, Opcode opcode, FPURegister rd,
889                            FPURegister rs1, FPURegister rs2, FPURegister rs3,
890                            RoundingMode frm) {
891   DCHECK(is_uint2(funct2) && rd.is_valid() && rs1.is_valid() &&
892          rs2.is_valid() && rs3.is_valid() && is_uint3(frm));
893   Instr instr = opcode | (rd.code() << kRdShift) | (frm << kFunct3Shift) |
894                 (rs1.code() << kRs1Shift) | (rs2.code() << kRs2Shift) |
895                 (funct2 << kFunct2Shift) | (rs3.code() << kRs3Shift);
896   emit(instr);
897 }
898 
GenInstrRAtomic(uint8_t funct5,bool aq,bool rl,uint8_t funct3,Register rd,Register rs1,Register rs2)899 void Assembler::GenInstrRAtomic(uint8_t funct5, bool aq, bool rl,
900                                 uint8_t funct3, Register rd, Register rs1,
901                                 Register rs2) {
902   DCHECK(is_uint5(funct5) && is_uint3(funct3) && rd.is_valid() &&
903          rs1.is_valid() && rs2.is_valid());
904   Instr instr = AMO | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
905                 (rs1.code() << kRs1Shift) | (rs2.code() << kRs2Shift) |
906                 (rl << kRlShift) | (aq << kAqShift) | (funct5 << kFunct5Shift);
907   emit(instr);
908 }
909 
GenInstrRFrm(uint8_t funct7,Opcode opcode,Register rd,Register rs1,Register rs2,RoundingMode frm)910 void Assembler::GenInstrRFrm(uint8_t funct7, Opcode opcode, Register rd,
911                              Register rs1, Register rs2, RoundingMode frm) {
912   DCHECK(rd.is_valid() && rs1.is_valid() && rs2.is_valid() && is_uint3(frm));
913   Instr instr = opcode | (rd.code() << kRdShift) | (frm << kFunct3Shift) |
914                 (rs1.code() << kRs1Shift) | (rs2.code() << kRs2Shift) |
915                 (funct7 << kFunct7Shift);
916   emit(instr);
917 }
918 
GenInstrI(uint8_t funct3,Opcode opcode,Register rd,Register rs1,int16_t imm12)919 void Assembler::GenInstrI(uint8_t funct3, Opcode opcode, Register rd,
920                           Register rs1, int16_t imm12) {
921   DCHECK(is_uint3(funct3) && rd.is_valid() && rs1.is_valid() &&
922          (is_uint12(imm12) || is_int12(imm12)));
923   Instr instr = opcode | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
924                 (rs1.code() << kRs1Shift) | (imm12 << kImm12Shift);
925   emit(instr);
926 }
927 
GenInstrI(uint8_t funct3,Opcode opcode,FPURegister rd,Register rs1,int16_t imm12)928 void Assembler::GenInstrI(uint8_t funct3, Opcode opcode, FPURegister rd,
929                           Register rs1, int16_t imm12) {
930   DCHECK(is_uint3(funct3) && rd.is_valid() && rs1.is_valid() &&
931          (is_uint12(imm12) || is_int12(imm12)));
932   Instr instr = opcode | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
933                 (rs1.code() << kRs1Shift) | (imm12 << kImm12Shift);
934   emit(instr);
935 }
936 
GenInstrIShift(bool arithshift,uint8_t funct3,Opcode opcode,Register rd,Register rs1,uint8_t shamt)937 void Assembler::GenInstrIShift(bool arithshift, uint8_t funct3, Opcode opcode,
938                                Register rd, Register rs1, uint8_t shamt) {
939   DCHECK(is_uint3(funct3) && rd.is_valid() && rs1.is_valid() &&
940          is_uint6(shamt));
941   Instr instr = opcode | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
942                 (rs1.code() << kRs1Shift) | (shamt << kShamtShift) |
943                 (arithshift << kArithShiftShift);
944   emit(instr);
945 }
946 
GenInstrIShiftW(bool arithshift,uint8_t funct3,Opcode opcode,Register rd,Register rs1,uint8_t shamt)947 void Assembler::GenInstrIShiftW(bool arithshift, uint8_t funct3, Opcode opcode,
948                                 Register rd, Register rs1, uint8_t shamt) {
949   DCHECK(is_uint3(funct3) && rd.is_valid() && rs1.is_valid() &&
950          is_uint5(shamt));
951   Instr instr = opcode | (rd.code() << kRdShift) | (funct3 << kFunct3Shift) |
952                 (rs1.code() << kRs1Shift) | (shamt << kShamtWShift) |
953                 (arithshift << kArithShiftShift);
954   emit(instr);
955 }
956 
GenInstrS(uint8_t funct3,Opcode opcode,Register rs1,Register rs2,int16_t imm12)957 void Assembler::GenInstrS(uint8_t funct3, Opcode opcode, Register rs1,
958                           Register rs2, int16_t imm12) {
959   DCHECK(is_uint3(funct3) && rs1.is_valid() && rs2.is_valid() &&
960          is_int12(imm12));
961   Instr instr = opcode | ((imm12 & 0x1f) << 7) |  // bits  4-0
962                 (funct3 << kFunct3Shift) | (rs1.code() << kRs1Shift) |
963                 (rs2.code() << kRs2Shift) |
964                 ((imm12 & 0xfe0) << 20);  // bits 11-5
965   emit(instr);
966 }
967 
GenInstrS(uint8_t funct3,Opcode opcode,Register rs1,FPURegister rs2,int16_t imm12)968 void Assembler::GenInstrS(uint8_t funct3, Opcode opcode, Register rs1,
969                           FPURegister rs2, int16_t imm12) {
970   DCHECK(is_uint3(funct3) && rs1.is_valid() && rs2.is_valid() &&
971          is_int12(imm12));
972   Instr instr = opcode | ((imm12 & 0x1f) << 7) |  // bits  4-0
973                 (funct3 << kFunct3Shift) | (rs1.code() << kRs1Shift) |
974                 (rs2.code() << kRs2Shift) |
975                 ((imm12 & 0xfe0) << 20);  // bits 11-5
976   emit(instr);
977 }
978 
GenInstrB(uint8_t funct3,Opcode opcode,Register rs1,Register rs2,int16_t imm13)979 void Assembler::GenInstrB(uint8_t funct3, Opcode opcode, Register rs1,
980                           Register rs2, int16_t imm13) {
981   DCHECK(is_uint3(funct3) && rs1.is_valid() && rs2.is_valid() &&
982          is_int13(imm13) && ((imm13 & 1) == 0));
983   Instr instr = opcode | ((imm13 & 0x800) >> 4) |  // bit  11
984                 ((imm13 & 0x1e) << 7) |            // bits 4-1
985                 (funct3 << kFunct3Shift) | (rs1.code() << kRs1Shift) |
986                 (rs2.code() << kRs2Shift) |
987                 ((imm13 & 0x7e0) << 20) |  // bits 10-5
988                 ((imm13 & 0x1000) << 19);  // bit 12
989   emit(instr);
990 }
991 
GenInstrU(Opcode opcode,Register rd,int32_t imm20)992 void Assembler::GenInstrU(Opcode opcode, Register rd, int32_t imm20) {
993   DCHECK(rd.is_valid() && (is_int20(imm20) || is_uint20(imm20)));
994   Instr instr = opcode | (rd.code() << kRdShift) | (imm20 << kImm20Shift);
995   emit(instr);
996 }
997 
GenInstrJ(Opcode opcode,Register rd,int32_t imm21)998 void Assembler::GenInstrJ(Opcode opcode, Register rd, int32_t imm21) {
999   DCHECK(rd.is_valid() && is_int21(imm21) && ((imm21 & 1) == 0));
1000   Instr instr = opcode | (rd.code() << kRdShift) |
1001                 (imm21 & 0xff000) |          // bits 19-12
1002                 ((imm21 & 0x800) << 9) |     // bit  11
1003                 ((imm21 & 0x7fe) << 20) |    // bits 10-1
1004                 ((imm21 & 0x100000) << 11);  // bit  20
1005   emit(instr);
1006 }
1007 
GenInstrCR(uint8_t funct4,Opcode opcode,Register rd,Register rs2)1008 void Assembler::GenInstrCR(uint8_t funct4, Opcode opcode, Register rd,
1009                            Register rs2) {
1010   DCHECK(is_uint4(funct4) && rd.is_valid() && rs2.is_valid());
1011   ShortInstr instr = opcode | (rs2.code() << kRvcRs2Shift) |
1012                      (rd.code() << kRvcRdShift) | (funct4 << kRvcFunct4Shift);
1013   emit(instr);
1014 }
1015 
GenInstrCA(uint8_t funct6,Opcode opcode,Register rd,uint8_t funct,Register rs2)1016 void Assembler::GenInstrCA(uint8_t funct6, Opcode opcode, Register rd,
1017                            uint8_t funct, Register rs2) {
1018   DCHECK(is_uint6(funct6) && rd.is_valid() && rs2.is_valid() &&
1019          is_uint2(funct));
1020   ShortInstr instr = opcode | ((rs2.code() & 0x7) << kRvcRs2sShift) |
1021                      ((rd.code() & 0x7) << kRvcRs1sShift) |
1022                      (funct6 << kRvcFunct6Shift) | (funct << kRvcFunct2Shift);
1023   emit(instr);
1024 }
1025 
GenInstrCI(uint8_t funct3,Opcode opcode,Register rd,int8_t imm6)1026 void Assembler::GenInstrCI(uint8_t funct3, Opcode opcode, Register rd,
1027                            int8_t imm6) {
1028   DCHECK(is_uint3(funct3) && rd.is_valid() && is_int6(imm6));
1029   ShortInstr instr = opcode | ((imm6 & 0x1f) << 2) |
1030                      (rd.code() << kRvcRdShift) | ((imm6 & 0x20) << 7) |
1031                      (funct3 << kRvcFunct3Shift);
1032   emit(instr);
1033 }
1034 
GenInstrCIU(uint8_t funct3,Opcode opcode,Register rd,uint8_t uimm6)1035 void Assembler::GenInstrCIU(uint8_t funct3, Opcode opcode, Register rd,
1036                             uint8_t uimm6) {
1037   DCHECK(is_uint3(funct3) && rd.is_valid() && is_uint6(uimm6));
1038   ShortInstr instr = opcode | ((uimm6 & 0x1f) << 2) |
1039                      (rd.code() << kRvcRdShift) | ((uimm6 & 0x20) << 7) |
1040                      (funct3 << kRvcFunct3Shift);
1041   emit(instr);
1042 }
1043 
GenInstrCIU(uint8_t funct3,Opcode opcode,FPURegister rd,uint8_t uimm6)1044 void Assembler::GenInstrCIU(uint8_t funct3, Opcode opcode, FPURegister rd,
1045                             uint8_t uimm6) {
1046   DCHECK(is_uint3(funct3) && rd.is_valid() && is_uint6(uimm6));
1047   ShortInstr instr = opcode | ((uimm6 & 0x1f) << 2) |
1048                      (rd.code() << kRvcRdShift) | ((uimm6 & 0x20) << 7) |
1049                      (funct3 << kRvcFunct3Shift);
1050   emit(instr);
1051 }
1052 
GenInstrCIW(uint8_t funct3,Opcode opcode,Register rd,uint8_t uimm8)1053 void Assembler::GenInstrCIW(uint8_t funct3, Opcode opcode, Register rd,
1054                             uint8_t uimm8) {
1055   DCHECK(is_uint3(funct3) && rd.is_valid() && is_uint8(uimm8));
1056   ShortInstr instr = opcode | ((uimm8) << 5) |
1057                      ((rd.code() & 0x7) << kRvcRs2sShift) |
1058                      (funct3 << kRvcFunct3Shift);
1059   emit(instr);
1060 }
1061 
GenInstrCSS(uint8_t funct3,Opcode opcode,Register rs2,uint8_t uimm6)1062 void Assembler::GenInstrCSS(uint8_t funct3, Opcode opcode, Register rs2,
1063                             uint8_t uimm6) {
1064   DCHECK(is_uint3(funct3) && rs2.is_valid() && is_uint6(uimm6));
1065   ShortInstr instr = opcode | (uimm6 << 7) | (rs2.code() << kRvcRs2Shift) |
1066                      (funct3 << kRvcFunct3Shift);
1067   emit(instr);
1068 }
1069 
GenInstrCSS(uint8_t funct3,Opcode opcode,FPURegister rs2,uint8_t uimm6)1070 void Assembler::GenInstrCSS(uint8_t funct3, Opcode opcode, FPURegister rs2,
1071                             uint8_t uimm6) {
1072   DCHECK(is_uint3(funct3) && rs2.is_valid() && is_uint6(uimm6));
1073   ShortInstr instr = opcode | (uimm6 << 7) | (rs2.code() << kRvcRs2Shift) |
1074                      (funct3 << kRvcFunct3Shift);
1075   emit(instr);
1076 }
1077 
GenInstrCL(uint8_t funct3,Opcode opcode,Register rd,Register rs1,uint8_t uimm5)1078 void Assembler::GenInstrCL(uint8_t funct3, Opcode opcode, Register rd,
1079                            Register rs1, uint8_t uimm5) {
1080   DCHECK(is_uint3(funct3) && rd.is_valid() && rs1.is_valid() &&
1081          is_uint5(uimm5));
1082   ShortInstr instr = opcode | ((uimm5 & 0x3) << 5) |
1083                      ((rd.code() & 0x7) << kRvcRs2sShift) |
1084                      ((uimm5 & 0x1c) << 8) | (funct3 << kRvcFunct3Shift) |
1085                      ((rs1.code() & 0x7) << kRvcRs1sShift);
1086   emit(instr);
1087 }
1088 
GenInstrCL(uint8_t funct3,Opcode opcode,FPURegister rd,Register rs1,uint8_t uimm5)1089 void Assembler::GenInstrCL(uint8_t funct3, Opcode opcode, FPURegister rd,
1090                            Register rs1, uint8_t uimm5) {
1091   DCHECK(is_uint3(funct3) && rd.is_valid() && rs1.is_valid() &&
1092          is_uint5(uimm5));
1093   ShortInstr instr = opcode | ((uimm5 & 0x3) << 5) |
1094                      ((rd.code() & 0x7) << kRvcRs2sShift) |
1095                      ((uimm5 & 0x1c) << 8) | (funct3 << kRvcFunct3Shift) |
1096                      ((rs1.code() & 0x7) << kRvcRs1sShift);
1097   emit(instr);
1098 }
GenInstrCJ(uint8_t funct3,Opcode opcode,uint16_t uint11)1099 void Assembler::GenInstrCJ(uint8_t funct3, Opcode opcode, uint16_t uint11) {
1100   DCHECK(is_uint11(uint11));
1101   ShortInstr instr = opcode | (funct3 << kRvcFunct3Shift) | (uint11 << 2);
1102   emit(instr);
1103 }
1104 
GenInstrCS(uint8_t funct3,Opcode opcode,Register rs2,Register rs1,uint8_t uimm5)1105 void Assembler::GenInstrCS(uint8_t funct3, Opcode opcode, Register rs2,
1106                            Register rs1, uint8_t uimm5) {
1107   DCHECK(is_uint3(funct3) && rs2.is_valid() && rs1.is_valid() &&
1108          is_uint5(uimm5));
1109   ShortInstr instr = opcode | ((uimm5 & 0x3) << 5) |
1110                      ((rs2.code() & 0x7) << kRvcRs2sShift) |
1111                      ((uimm5 & 0x1c) << 8) | (funct3 << kRvcFunct3Shift) |
1112                      ((rs1.code() & 0x7) << kRvcRs1sShift);
1113   emit(instr);
1114 }
1115 
GenInstrCS(uint8_t funct3,Opcode opcode,FPURegister rs2,Register rs1,uint8_t uimm5)1116 void Assembler::GenInstrCS(uint8_t funct3, Opcode opcode, FPURegister rs2,
1117                            Register rs1, uint8_t uimm5) {
1118   DCHECK(is_uint3(funct3) && rs2.is_valid() && rs1.is_valid() &&
1119          is_uint5(uimm5));
1120   ShortInstr instr = opcode | ((uimm5 & 0x3) << 5) |
1121                      ((rs2.code() & 0x7) << kRvcRs2sShift) |
1122                      ((uimm5 & 0x1c) << 8) | (funct3 << kRvcFunct3Shift) |
1123                      ((rs1.code() & 0x7) << kRvcRs1sShift);
1124   emit(instr);
1125 }
1126 
GenInstrCB(uint8_t funct3,Opcode opcode,Register rs1,uint8_t uimm8)1127 void Assembler::GenInstrCB(uint8_t funct3, Opcode opcode, Register rs1,
1128                            uint8_t uimm8) {
1129   DCHECK(is_uint3(funct3) && is_uint8(uimm8));
1130   ShortInstr instr = opcode | ((uimm8 & 0x1f) << 2) | ((uimm8 & 0xe0) << 5) |
1131                      ((rs1.code() & 0x7) << kRvcRs1sShift) |
1132                      (funct3 << kRvcFunct3Shift);
1133   emit(instr);
1134 }
1135 
GenInstrCBA(uint8_t funct3,uint8_t funct2,Opcode opcode,Register rs1,int8_t imm6)1136 void Assembler::GenInstrCBA(uint8_t funct3, uint8_t funct2, Opcode opcode,
1137                             Register rs1, int8_t imm6) {
1138   DCHECK(is_uint3(funct3) && is_uint2(funct2) && is_int6(imm6));
1139   ShortInstr instr = opcode | ((imm6 & 0x1f) << 2) | ((imm6 & 0x20) << 7) |
1140                      ((rs1.code() & 0x7) << kRvcRs1sShift) |
1141                      (funct3 << kRvcFunct3Shift) | (funct2 << 10);
1142   emit(instr);
1143 }
1144 
1145 // OPIVV OPFVV OPMVV
GenInstrV(uint8_t funct6,Opcode opcode,VRegister vd,VRegister vs1,VRegister vs2,MaskType mask)1146 void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd,
1147                           VRegister vs1, VRegister vs2, MaskType mask) {
1148   DCHECK(opcode == OP_MVV || opcode == OP_FVV || opcode == OP_IVV);
1149   Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) |
1150                 ((vd.code() & 0x1F) << kRvvVdShift) |
1151                 ((vs1.code() & 0x1F) << kRvvVs1Shift) |
1152                 ((vs2.code() & 0x1F) << kRvvVs2Shift);
1153   emit(instr);
1154 }
1155 
GenInstrV(uint8_t funct6,Opcode opcode,VRegister vd,int8_t vs1,VRegister vs2,MaskType mask)1156 void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd,
1157                           int8_t vs1, VRegister vs2, MaskType mask) {
1158   DCHECK(opcode == OP_MVV || opcode == OP_FVV || opcode == OP_IVV);
1159   Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) |
1160                 ((vd.code() & 0x1F) << kRvvVdShift) |
1161                 ((vs1 & 0x1F) << kRvvVs1Shift) |
1162                 ((vs2.code() & 0x1F) << kRvvVs2Shift);
1163   emit(instr);
1164 }
1165 // OPMVV OPFVV
GenInstrV(uint8_t funct6,Opcode opcode,Register rd,VRegister vs1,VRegister vs2,MaskType mask)1166 void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, Register rd,
1167                           VRegister vs1, VRegister vs2, MaskType mask) {
1168   DCHECK(opcode == OP_MVV || opcode == OP_FVV);
1169   Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) |
1170                 ((rd.code() & 0x1F) << kRvvVdShift) |
1171                 ((vs1.code() & 0x1F) << kRvvVs1Shift) |
1172                 ((vs2.code() & 0x1F) << kRvvVs2Shift);
1173   emit(instr);
1174 }
1175 
1176 // OPFVV
GenInstrV(uint8_t funct6,Opcode opcode,FPURegister fd,VRegister vs1,VRegister vs2,MaskType mask)1177 void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, FPURegister fd,
1178                           VRegister vs1, VRegister vs2, MaskType mask) {
1179   DCHECK(opcode == OP_FVV);
1180   Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) |
1181                 ((fd.code() & 0x1F) << kRvvVdShift) |
1182                 ((vs1.code() & 0x1F) << kRvvVs1Shift) |
1183                 ((vs2.code() & 0x1F) << kRvvVs2Shift);
1184   emit(instr);
1185 }
1186 
1187 // OPIVX OPMVX
GenInstrV(uint8_t funct6,Opcode opcode,VRegister vd,Register rs1,VRegister vs2,MaskType mask)1188 void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd,
1189                           Register rs1, VRegister vs2, MaskType mask) {
1190   DCHECK(opcode == OP_IVX || opcode == OP_MVX);
1191   Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) |
1192                 ((vd.code() & 0x1F) << kRvvVdShift) |
1193                 ((rs1.code() & 0x1F) << kRvvRs1Shift) |
1194                 ((vs2.code() & 0x1F) << kRvvVs2Shift);
1195   emit(instr);
1196 }
1197 
1198 // OPFVF
GenInstrV(uint8_t funct6,Opcode opcode,VRegister vd,FPURegister fs1,VRegister vs2,MaskType mask)1199 void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd,
1200                           FPURegister fs1, VRegister vs2, MaskType mask) {
1201   DCHECK(opcode == OP_FVF);
1202   Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) |
1203                 ((vd.code() & 0x1F) << kRvvVdShift) |
1204                 ((fs1.code() & 0x1F) << kRvvRs1Shift) |
1205                 ((vs2.code() & 0x1F) << kRvvVs2Shift);
1206   emit(instr);
1207 }
1208 
1209 // OPMVX
GenInstrV(uint8_t funct6,Register rd,Register rs1,VRegister vs2,MaskType mask)1210 void Assembler::GenInstrV(uint8_t funct6, Register rd, Register rs1,
1211                           VRegister vs2, MaskType mask) {
1212   Instr instr = (funct6 << kRvvFunct6Shift) | OP_MVX | (mask << kRvvVmShift) |
1213                 ((rd.code() & 0x1F) << kRvvVdShift) |
1214                 ((rs1.code() & 0x1F) << kRvvRs1Shift) |
1215                 ((vs2.code() & 0x1F) << kRvvVs2Shift);
1216   emit(instr);
1217 }
1218 // OPIVI
GenInstrV(uint8_t funct6,VRegister vd,int8_t imm5,VRegister vs2,MaskType mask)1219 void Assembler::GenInstrV(uint8_t funct6, VRegister vd, int8_t imm5,
1220                           VRegister vs2, MaskType mask) {
1221   DCHECK(is_uint5(imm5) || is_int5(imm5));
1222   Instr instr = (funct6 << kRvvFunct6Shift) | OP_IVI | (mask << kRvvVmShift) |
1223                 ((vd.code() & 0x1F) << kRvvVdShift) |
1224                 (((uint32_t)imm5 << kRvvImm5Shift) & kRvvImm5Mask) |
1225                 ((vs2.code() & 0x1F) << kRvvVs2Shift);
1226   emit(instr);
1227 }
1228 
1229 // VL VS
GenInstrV(Opcode opcode,uint8_t width,VRegister vd,Register rs1,uint8_t umop,MaskType mask,uint8_t IsMop,bool IsMew,uint8_t Nf)1230 void Assembler::GenInstrV(Opcode opcode, uint8_t width, VRegister vd,
1231                           Register rs1, uint8_t umop, MaskType mask,
1232                           uint8_t IsMop, bool IsMew, uint8_t Nf) {
1233   DCHECK(opcode == LOAD_FP || opcode == STORE_FP);
1234   Instr instr = opcode | ((vd.code() << kRvvVdShift) & kRvvVdMask) |
1235                 ((width << kRvvWidthShift) & kRvvWidthMask) |
1236                 ((rs1.code() << kRvvRs1Shift) & kRvvRs1Mask) |
1237                 ((umop << kRvvRs2Shift) & kRvvRs2Mask) |
1238                 ((mask << kRvvVmShift) & kRvvVmMask) |
1239                 ((IsMop << kRvvMopShift) & kRvvMopMask) |
1240                 ((IsMew << kRvvMewShift) & kRvvMewMask) |
1241                 ((Nf << kRvvNfShift) & kRvvNfMask);
1242   emit(instr);
1243 }
GenInstrV(Opcode opcode,uint8_t width,VRegister vd,Register rs1,Register rs2,MaskType mask,uint8_t IsMop,bool IsMew,uint8_t Nf)1244 void Assembler::GenInstrV(Opcode opcode, uint8_t width, VRegister vd,
1245                           Register rs1, Register rs2, MaskType mask,
1246                           uint8_t IsMop, bool IsMew, uint8_t Nf) {
1247   DCHECK(opcode == LOAD_FP || opcode == STORE_FP);
1248   Instr instr = opcode | ((vd.code() << kRvvVdShift) & kRvvVdMask) |
1249                 ((width << kRvvWidthShift) & kRvvWidthMask) |
1250                 ((rs1.code() << kRvvRs1Shift) & kRvvRs1Mask) |
1251                 ((rs2.code() << kRvvRs2Shift) & kRvvRs2Mask) |
1252                 ((mask << kRvvVmShift) & kRvvVmMask) |
1253                 ((IsMop << kRvvMopShift) & kRvvMopMask) |
1254                 ((IsMew << kRvvMewShift) & kRvvMewMask) |
1255                 ((Nf << kRvvNfShift) & kRvvNfMask);
1256   emit(instr);
1257 }
1258 // VL VS AMO
GenInstrV(Opcode opcode,uint8_t width,VRegister vd,Register rs1,VRegister vs2,MaskType mask,uint8_t IsMop,bool IsMew,uint8_t Nf)1259 void Assembler::GenInstrV(Opcode opcode, uint8_t width, VRegister vd,
1260                           Register rs1, VRegister vs2, MaskType mask,
1261                           uint8_t IsMop, bool IsMew, uint8_t Nf) {
1262   DCHECK(opcode == LOAD_FP || opcode == STORE_FP || opcode == AMO);
1263   Instr instr = opcode | ((vd.code() << kRvvVdShift) & kRvvVdMask) |
1264                 ((width << kRvvWidthShift) & kRvvWidthMask) |
1265                 ((rs1.code() << kRvvRs1Shift) & kRvvRs1Mask) |
1266                 ((vs2.code() << kRvvRs2Shift) & kRvvRs2Mask) |
1267                 ((mask << kRvvVmShift) & kRvvVmMask) |
1268                 ((IsMop << kRvvMopShift) & kRvvMopMask) |
1269                 ((IsMew << kRvvMewShift) & kRvvMewMask) |
1270                 ((Nf << kRvvNfShift) & kRvvNfMask);
1271   emit(instr);
1272 }
1273 // vmv_xs vcpop_m vfirst_m
GenInstrV(uint8_t funct6,Opcode opcode,Register rd,uint8_t vs1,VRegister vs2,MaskType mask)1274 void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, Register rd,
1275                           uint8_t vs1, VRegister vs2, MaskType mask) {
1276   DCHECK(opcode == OP_MVV);
1277   Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) |
1278                 ((rd.code() & 0x1F) << kRvvVdShift) |
1279                 ((vs1 & 0x1F) << kRvvVs1Shift) |
1280                 ((vs2.code() & 0x1F) << kRvvVs2Shift);
1281   emit(instr);
1282 }
1283 // ----- Instruction class templates match those in the compiler
1284 
GenInstrBranchCC_rri(uint8_t funct3,Register rs1,Register rs2,int16_t imm13)1285 void Assembler::GenInstrBranchCC_rri(uint8_t funct3, Register rs1, Register rs2,
1286                                      int16_t imm13) {
1287   GenInstrB(funct3, BRANCH, rs1, rs2, imm13);
1288 }
1289 
GenInstrLoad_ri(uint8_t funct3,Register rd,Register rs1,int16_t imm12)1290 void Assembler::GenInstrLoad_ri(uint8_t funct3, Register rd, Register rs1,
1291                                 int16_t imm12) {
1292   GenInstrI(funct3, LOAD, rd, rs1, imm12);
1293 }
1294 
GenInstrStore_rri(uint8_t funct3,Register rs1,Register rs2,int16_t imm12)1295 void Assembler::GenInstrStore_rri(uint8_t funct3, Register rs1, Register rs2,
1296                                   int16_t imm12) {
1297   GenInstrS(funct3, STORE, rs1, rs2, imm12);
1298 }
1299 
GenInstrALU_ri(uint8_t funct3,Register rd,Register rs1,int16_t imm12)1300 void Assembler::GenInstrALU_ri(uint8_t funct3, Register rd, Register rs1,
1301                                int16_t imm12) {
1302   GenInstrI(funct3, OP_IMM, rd, rs1, imm12);
1303 }
1304 
GenInstrShift_ri(bool arithshift,uint8_t funct3,Register rd,Register rs1,uint8_t shamt)1305 void Assembler::GenInstrShift_ri(bool arithshift, uint8_t funct3, Register rd,
1306                                  Register rs1, uint8_t shamt) {
1307   DCHECK(is_uint6(shamt));
1308   GenInstrI(funct3, OP_IMM, rd, rs1, (arithshift << 10) | shamt);
1309 }
1310 
GenInstrALU_rr(uint8_t funct7,uint8_t funct3,Register rd,Register rs1,Register rs2)1311 void Assembler::GenInstrALU_rr(uint8_t funct7, uint8_t funct3, Register rd,
1312                                Register rs1, Register rs2) {
1313   GenInstrR(funct7, funct3, OP, rd, rs1, rs2);
1314 }
1315 
GenInstrCSR_ir(uint8_t funct3,Register rd,ControlStatusReg csr,Register rs1)1316 void Assembler::GenInstrCSR_ir(uint8_t funct3, Register rd,
1317                                ControlStatusReg csr, Register rs1) {
1318   GenInstrI(funct3, SYSTEM, rd, rs1, csr);
1319 }
1320 
GenInstrCSR_ii(uint8_t funct3,Register rd,ControlStatusReg csr,uint8_t imm5)1321 void Assembler::GenInstrCSR_ii(uint8_t funct3, Register rd,
1322                                ControlStatusReg csr, uint8_t imm5) {
1323   GenInstrI(funct3, SYSTEM, rd, ToRegister(imm5), csr);
1324 }
1325 
GenInstrShiftW_ri(bool arithshift,uint8_t funct3,Register rd,Register rs1,uint8_t shamt)1326 void Assembler::GenInstrShiftW_ri(bool arithshift, uint8_t funct3, Register rd,
1327                                   Register rs1, uint8_t shamt) {
1328   GenInstrIShiftW(arithshift, funct3, OP_IMM_32, rd, rs1, shamt);
1329 }
1330 
GenInstrALUW_rr(uint8_t funct7,uint8_t funct3,Register rd,Register rs1,Register rs2)1331 void Assembler::GenInstrALUW_rr(uint8_t funct7, uint8_t funct3, Register rd,
1332                                 Register rs1, Register rs2) {
1333   GenInstrR(funct7, funct3, OP_32, rd, rs1, rs2);
1334 }
1335 
GenInstrPriv(uint8_t funct7,Register rs1,Register rs2)1336 void Assembler::GenInstrPriv(uint8_t funct7, Register rs1, Register rs2) {
1337   GenInstrR(funct7, 0b000, SYSTEM, ToRegister(0), rs1, rs2);
1338 }
1339 
GenInstrLoadFP_ri(uint8_t funct3,FPURegister rd,Register rs1,int16_t imm12)1340 void Assembler::GenInstrLoadFP_ri(uint8_t funct3, FPURegister rd, Register rs1,
1341                                   int16_t imm12) {
1342   GenInstrI(funct3, LOAD_FP, rd, rs1, imm12);
1343 }
1344 
GenInstrStoreFP_rri(uint8_t funct3,Register rs1,FPURegister rs2,int16_t imm12)1345 void Assembler::GenInstrStoreFP_rri(uint8_t funct3, Register rs1,
1346                                     FPURegister rs2, int16_t imm12) {
1347   GenInstrS(funct3, STORE_FP, rs1, rs2, imm12);
1348 }
1349 
GenInstrALUFP_rr(uint8_t funct7,uint8_t funct3,FPURegister rd,FPURegister rs1,FPURegister rs2)1350 void Assembler::GenInstrALUFP_rr(uint8_t funct7, uint8_t funct3, FPURegister rd,
1351                                  FPURegister rs1, FPURegister rs2) {
1352   GenInstrR(funct7, funct3, OP_FP, rd, rs1, rs2);
1353 }
1354 
GenInstrALUFP_rr(uint8_t funct7,uint8_t funct3,FPURegister rd,Register rs1,Register rs2)1355 void Assembler::GenInstrALUFP_rr(uint8_t funct7, uint8_t funct3, FPURegister rd,
1356                                  Register rs1, Register rs2) {
1357   GenInstrR(funct7, funct3, OP_FP, rd, rs1, rs2);
1358 }
1359 
GenInstrALUFP_rr(uint8_t funct7,uint8_t funct3,FPURegister rd,FPURegister rs1,Register rs2)1360 void Assembler::GenInstrALUFP_rr(uint8_t funct7, uint8_t funct3, FPURegister rd,
1361                                  FPURegister rs1, Register rs2) {
1362   GenInstrR(funct7, funct3, OP_FP, rd, rs1, rs2);
1363 }
1364 
GenInstrALUFP_rr(uint8_t funct7,uint8_t funct3,Register rd,FPURegister rs1,Register rs2)1365 void Assembler::GenInstrALUFP_rr(uint8_t funct7, uint8_t funct3, Register rd,
1366                                  FPURegister rs1, Register rs2) {
1367   GenInstrR(funct7, funct3, OP_FP, rd, rs1, rs2);
1368 }
1369 
GenInstrALUFP_rr(uint8_t funct7,uint8_t funct3,Register rd,FPURegister rs1,FPURegister rs2)1370 void Assembler::GenInstrALUFP_rr(uint8_t funct7, uint8_t funct3, Register rd,
1371                                  FPURegister rs1, FPURegister rs2) {
1372   GenInstrR(funct7, funct3, OP_FP, rd, rs1, rs2);
1373 }
1374 
1375 // Returns the next free trampoline entry.
get_trampoline_entry(int32_t pos)1376 int32_t Assembler::get_trampoline_entry(int32_t pos) {
1377   int32_t trampoline_entry = kInvalidSlotPos;
1378   if (!internal_trampoline_exception_) {
1379     DEBUG_PRINTF("\tstart: %d,pos: %d\n", trampoline_.start(), pos);
1380     if (trampoline_.start() > pos) {
1381       trampoline_entry = trampoline_.take_slot();
1382     }
1383 
1384     if (kInvalidSlotPos == trampoline_entry) {
1385       internal_trampoline_exception_ = true;
1386     }
1387   }
1388   return trampoline_entry;
1389 }
1390 
jump_address(Label * L)1391 uint64_t Assembler::jump_address(Label* L) {
1392   int64_t target_pos;
1393   DEBUG_PRINTF("jump_address: %p to %p (%d)\n", L,
1394                reinterpret_cast<Instr*>(buffer_start_ + pc_offset()),
1395                pc_offset());
1396   if (L->is_bound()) {
1397     target_pos = L->pos();
1398   } else {
1399     if (L->is_linked()) {
1400       target_pos = L->pos();  // L's link.
1401       L->link_to(pc_offset());
1402     } else {
1403       L->link_to(pc_offset());
1404       if (!trampoline_emitted_) {
1405         unbound_labels_count_++;
1406         next_buffer_check_ -= kTrampolineSlotsSize;
1407       }
1408       DEBUG_PRINTF("\tstarted link\n");
1409       return kEndOfJumpChain;
1410     }
1411   }
1412   uint64_t imm = reinterpret_cast<uint64_t>(buffer_start_) + target_pos;
1413   if (FLAG_riscv_c_extension)
1414     DCHECK_EQ(imm & 1, 0);
1415   else
1416     DCHECK_EQ(imm & 3, 0);
1417 
1418   return imm;
1419 }
1420 
branch_long_offset(Label * L)1421 uint64_t Assembler::branch_long_offset(Label* L) {
1422   int64_t target_pos;
1423 
1424   DEBUG_PRINTF("branch_long_offset: %p to %p (%d)\n", L,
1425                reinterpret_cast<Instr*>(buffer_start_ + pc_offset()),
1426                pc_offset());
1427   if (L->is_bound()) {
1428     target_pos = L->pos();
1429   } else {
1430     if (L->is_linked()) {
1431       target_pos = L->pos();  // L's link.
1432       L->link_to(pc_offset());
1433     } else {
1434       L->link_to(pc_offset());
1435       if (!trampoline_emitted_) {
1436         unbound_labels_count_++;
1437         next_buffer_check_ -= kTrampolineSlotsSize;
1438       }
1439       DEBUG_PRINTF("\tstarted link\n");
1440       return kEndOfJumpChain;
1441     }
1442   }
1443   int64_t offset = target_pos - pc_offset();
1444   if (FLAG_riscv_c_extension)
1445     DCHECK_EQ(offset & 1, 0);
1446   else
1447     DCHECK_EQ(offset & 3, 0);
1448 
1449   return static_cast<uint64_t>(offset);
1450 }
1451 
branch_offset_helper(Label * L,OffsetSize bits)1452 int32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) {
1453   int32_t target_pos;
1454 
1455   DEBUG_PRINTF("branch_offset_helper: %p to %p (%d)\n", L,
1456                reinterpret_cast<Instr*>(buffer_start_ + pc_offset()),
1457                pc_offset());
1458   if (L->is_bound()) {
1459     target_pos = L->pos();
1460     DEBUG_PRINTF("\tbound: %d", target_pos);
1461   } else {
1462     if (L->is_linked()) {
1463       target_pos = L->pos();
1464       L->link_to(pc_offset());
1465       DEBUG_PRINTF("\tadded to link: %d\n", target_pos);
1466     } else {
1467       L->link_to(pc_offset());
1468       if (!trampoline_emitted_) {
1469         unbound_labels_count_++;
1470         next_buffer_check_ -= kTrampolineSlotsSize;
1471       }
1472       DEBUG_PRINTF("\tstarted link\n");
1473       return kEndOfJumpChain;
1474     }
1475   }
1476 
1477   int32_t offset = target_pos - pc_offset();
1478   DCHECK(is_intn(offset, bits));
1479   DCHECK_EQ(offset & 1, 0);
1480   DEBUG_PRINTF("\toffset = %d\n", offset);
1481   return offset;
1482 }
1483 
label_at_put(Label * L,int at_offset)1484 void Assembler::label_at_put(Label* L, int at_offset) {
1485   int target_pos;
1486   DEBUG_PRINTF("label_at_put: %p @ %p (%d)\n", L,
1487                reinterpret_cast<Instr*>(buffer_start_ + at_offset), at_offset);
1488   if (L->is_bound()) {
1489     target_pos = L->pos();
1490     instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
1491   } else {
1492     if (L->is_linked()) {
1493       target_pos = L->pos();  // L's link.
1494       int32_t imm18 = target_pos - at_offset;
1495       DCHECK_EQ(imm18 & 3, 0);
1496       int32_t imm16 = imm18 >> 2;
1497       DCHECK(is_int16(imm16));
1498       instr_at_put(at_offset, (int32_t)(imm16 & kImm16Mask));
1499     } else {
1500       target_pos = kEndOfJumpChain;
1501       instr_at_put(at_offset, target_pos);
1502       if (!trampoline_emitted_) {
1503         unbound_labels_count_++;
1504         next_buffer_check_ -= kTrampolineSlotsSize;
1505       }
1506     }
1507     L->link_to(at_offset);
1508   }
1509 }
1510 
1511 //===----------------------------------------------------------------------===//
1512 // Instructions
1513 //===----------------------------------------------------------------------===//
1514 
lui(Register rd,int32_t imm20)1515 void Assembler::lui(Register rd, int32_t imm20) { GenInstrU(LUI, rd, imm20); }
1516 
auipc(Register rd,int32_t imm20)1517 void Assembler::auipc(Register rd, int32_t imm20) {
1518   GenInstrU(AUIPC, rd, imm20);
1519 }
1520 
1521 // Jumps
1522 
jal(Register rd,int32_t imm21)1523 void Assembler::jal(Register rd, int32_t imm21) {
1524   GenInstrJ(JAL, rd, imm21);
1525   BlockTrampolinePoolFor(1);
1526 }
1527 
jalr(Register rd,Register rs1,int16_t imm12)1528 void Assembler::jalr(Register rd, Register rs1, int16_t imm12) {
1529   GenInstrI(0b000, JALR, rd, rs1, imm12);
1530   BlockTrampolinePoolFor(1);
1531 }
1532 
1533 // Branches
1534 
beq(Register rs1,Register rs2,int16_t imm13)1535 void Assembler::beq(Register rs1, Register rs2, int16_t imm13) {
1536   GenInstrBranchCC_rri(0b000, rs1, rs2, imm13);
1537 }
1538 
bne(Register rs1,Register rs2,int16_t imm13)1539 void Assembler::bne(Register rs1, Register rs2, int16_t imm13) {
1540   GenInstrBranchCC_rri(0b001, rs1, rs2, imm13);
1541 }
1542 
blt(Register rs1,Register rs2,int16_t imm13)1543 void Assembler::blt(Register rs1, Register rs2, int16_t imm13) {
1544   GenInstrBranchCC_rri(0b100, rs1, rs2, imm13);
1545 }
1546 
bge(Register rs1,Register rs2,int16_t imm13)1547 void Assembler::bge(Register rs1, Register rs2, int16_t imm13) {
1548   GenInstrBranchCC_rri(0b101, rs1, rs2, imm13);
1549 }
1550 
bltu(Register rs1,Register rs2,int16_t imm13)1551 void Assembler::bltu(Register rs1, Register rs2, int16_t imm13) {
1552   GenInstrBranchCC_rri(0b110, rs1, rs2, imm13);
1553 }
1554 
bgeu(Register rs1,Register rs2,int16_t imm13)1555 void Assembler::bgeu(Register rs1, Register rs2, int16_t imm13) {
1556   GenInstrBranchCC_rri(0b111, rs1, rs2, imm13);
1557 }
1558 
1559 // Loads
1560 
lb(Register rd,Register rs1,int16_t imm12)1561 void Assembler::lb(Register rd, Register rs1, int16_t imm12) {
1562   GenInstrLoad_ri(0b000, rd, rs1, imm12);
1563 }
1564 
lh(Register rd,Register rs1,int16_t imm12)1565 void Assembler::lh(Register rd, Register rs1, int16_t imm12) {
1566   GenInstrLoad_ri(0b001, rd, rs1, imm12);
1567 }
1568 
lw(Register rd,Register rs1,int16_t imm12)1569 void Assembler::lw(Register rd, Register rs1, int16_t imm12) {
1570   GenInstrLoad_ri(0b010, rd, rs1, imm12);
1571 }
1572 
lbu(Register rd,Register rs1,int16_t imm12)1573 void Assembler::lbu(Register rd, Register rs1, int16_t imm12) {
1574   GenInstrLoad_ri(0b100, rd, rs1, imm12);
1575 }
1576 
lhu(Register rd,Register rs1,int16_t imm12)1577 void Assembler::lhu(Register rd, Register rs1, int16_t imm12) {
1578   GenInstrLoad_ri(0b101, rd, rs1, imm12);
1579 }
1580 
1581 // Stores
1582 
sb(Register source,Register base,int16_t imm12)1583 void Assembler::sb(Register source, Register base, int16_t imm12) {
1584   GenInstrStore_rri(0b000, base, source, imm12);
1585 }
1586 
sh(Register source,Register base,int16_t imm12)1587 void Assembler::sh(Register source, Register base, int16_t imm12) {
1588   GenInstrStore_rri(0b001, base, source, imm12);
1589 }
1590 
sw(Register source,Register base,int16_t imm12)1591 void Assembler::sw(Register source, Register base, int16_t imm12) {
1592   GenInstrStore_rri(0b010, base, source, imm12);
1593 }
1594 
1595 // Arithmetic with immediate
1596 
addi(Register rd,Register rs1,int16_t imm12)1597 void Assembler::addi(Register rd, Register rs1, int16_t imm12) {
1598   GenInstrALU_ri(0b000, rd, rs1, imm12);
1599 }
1600 
slti(Register rd,Register rs1,int16_t imm12)1601 void Assembler::slti(Register rd, Register rs1, int16_t imm12) {
1602   GenInstrALU_ri(0b010, rd, rs1, imm12);
1603 }
1604 
sltiu(Register rd,Register rs1,int16_t imm12)1605 void Assembler::sltiu(Register rd, Register rs1, int16_t imm12) {
1606   GenInstrALU_ri(0b011, rd, rs1, imm12);
1607 }
1608 
xori(Register rd,Register rs1,int16_t imm12)1609 void Assembler::xori(Register rd, Register rs1, int16_t imm12) {
1610   GenInstrALU_ri(0b100, rd, rs1, imm12);
1611 }
1612 
ori(Register rd,Register rs1,int16_t imm12)1613 void Assembler::ori(Register rd, Register rs1, int16_t imm12) {
1614   GenInstrALU_ri(0b110, rd, rs1, imm12);
1615 }
1616 
andi(Register rd,Register rs1,int16_t imm12)1617 void Assembler::andi(Register rd, Register rs1, int16_t imm12) {
1618   GenInstrALU_ri(0b111, rd, rs1, imm12);
1619 }
1620 
slli(Register rd,Register rs1,uint8_t shamt)1621 void Assembler::slli(Register rd, Register rs1, uint8_t shamt) {
1622   GenInstrShift_ri(0, 0b001, rd, rs1, shamt & 0x3f);
1623 }
1624 
srli(Register rd,Register rs1,uint8_t shamt)1625 void Assembler::srli(Register rd, Register rs1, uint8_t shamt) {
1626   GenInstrShift_ri(0, 0b101, rd, rs1, shamt & 0x3f);
1627 }
1628 
srai(Register rd,Register rs1,uint8_t shamt)1629 void Assembler::srai(Register rd, Register rs1, uint8_t shamt) {
1630   GenInstrShift_ri(1, 0b101, rd, rs1, shamt & 0x3f);
1631 }
1632 
1633 // Arithmetic
1634 
add(Register rd,Register rs1,Register rs2)1635 void Assembler::add(Register rd, Register rs1, Register rs2) {
1636   GenInstrALU_rr(0b0000000, 0b000, rd, rs1, rs2);
1637 }
1638 
sub(Register rd,Register rs1,Register rs2)1639 void Assembler::sub(Register rd, Register rs1, Register rs2) {
1640   GenInstrALU_rr(0b0100000, 0b000, rd, rs1, rs2);
1641 }
1642 
sll(Register rd,Register rs1,Register rs2)1643 void Assembler::sll(Register rd, Register rs1, Register rs2) {
1644   GenInstrALU_rr(0b0000000, 0b001, rd, rs1, rs2);
1645 }
1646 
slt(Register rd,Register rs1,Register rs2)1647 void Assembler::slt(Register rd, Register rs1, Register rs2) {
1648   GenInstrALU_rr(0b0000000, 0b010, rd, rs1, rs2);
1649 }
1650 
sltu(Register rd,Register rs1,Register rs2)1651 void Assembler::sltu(Register rd, Register rs1, Register rs2) {
1652   GenInstrALU_rr(0b0000000, 0b011, rd, rs1, rs2);
1653 }
1654 
xor_(Register rd,Register rs1,Register rs2)1655 void Assembler::xor_(Register rd, Register rs1, Register rs2) {
1656   GenInstrALU_rr(0b0000000, 0b100, rd, rs1, rs2);
1657 }
1658 
srl(Register rd,Register rs1,Register rs2)1659 void Assembler::srl(Register rd, Register rs1, Register rs2) {
1660   GenInstrALU_rr(0b0000000, 0b101, rd, rs1, rs2);
1661 }
1662 
sra(Register rd,Register rs1,Register rs2)1663 void Assembler::sra(Register rd, Register rs1, Register rs2) {
1664   GenInstrALU_rr(0b0100000, 0b101, rd, rs1, rs2);
1665 }
1666 
or_(Register rd,Register rs1,Register rs2)1667 void Assembler::or_(Register rd, Register rs1, Register rs2) {
1668   GenInstrALU_rr(0b0000000, 0b110, rd, rs1, rs2);
1669 }
1670 
and_(Register rd,Register rs1,Register rs2)1671 void Assembler::and_(Register rd, Register rs1, Register rs2) {
1672   GenInstrALU_rr(0b0000000, 0b111, rd, rs1, rs2);
1673 }
1674 
1675 // Memory fences
1676 
fence(uint8_t pred,uint8_t succ)1677 void Assembler::fence(uint8_t pred, uint8_t succ) {
1678   DCHECK(is_uint4(pred) && is_uint4(succ));
1679   uint16_t imm12 = succ | (pred << 4) | (0b0000 << 8);
1680   GenInstrI(0b000, MISC_MEM, ToRegister(0), ToRegister(0), imm12);
1681 }
1682 
fence_tso()1683 void Assembler::fence_tso() {
1684   uint16_t imm12 = (0b0011) | (0b0011 << 4) | (0b1000 << 8);
1685   GenInstrI(0b000, MISC_MEM, ToRegister(0), ToRegister(0), imm12);
1686 }
1687 
1688 // Environment call / break
1689 
ecall()1690 void Assembler::ecall() {
1691   GenInstrI(0b000, SYSTEM, ToRegister(0), ToRegister(0), 0);
1692 }
1693 
ebreak()1694 void Assembler::ebreak() {
1695   GenInstrI(0b000, SYSTEM, ToRegister(0), ToRegister(0), 1);
1696 }
1697 
1698 // This is a de facto standard (as set by GNU binutils) 32-bit unimplemented
1699 // instruction (i.e., it should always trap, if your implementation has invalid
1700 // instruction traps).
unimp()1701 void Assembler::unimp() {
1702   GenInstrI(0b001, SYSTEM, ToRegister(0), ToRegister(0), 0b110000000000);
1703 }
1704 
1705 // CSR
1706 
csrrw(Register rd,ControlStatusReg csr,Register rs1)1707 void Assembler::csrrw(Register rd, ControlStatusReg csr, Register rs1) {
1708   GenInstrCSR_ir(0b001, rd, csr, rs1);
1709 }
1710 
csrrs(Register rd,ControlStatusReg csr,Register rs1)1711 void Assembler::csrrs(Register rd, ControlStatusReg csr, Register rs1) {
1712   GenInstrCSR_ir(0b010, rd, csr, rs1);
1713 }
1714 
csrrc(Register rd,ControlStatusReg csr,Register rs1)1715 void Assembler::csrrc(Register rd, ControlStatusReg csr, Register rs1) {
1716   GenInstrCSR_ir(0b011, rd, csr, rs1);
1717 }
1718 
csrrwi(Register rd,ControlStatusReg csr,uint8_t imm5)1719 void Assembler::csrrwi(Register rd, ControlStatusReg csr, uint8_t imm5) {
1720   GenInstrCSR_ii(0b101, rd, csr, imm5);
1721 }
1722 
csrrsi(Register rd,ControlStatusReg csr,uint8_t imm5)1723 void Assembler::csrrsi(Register rd, ControlStatusReg csr, uint8_t imm5) {
1724   GenInstrCSR_ii(0b110, rd, csr, imm5);
1725 }
1726 
csrrci(Register rd,ControlStatusReg csr,uint8_t imm5)1727 void Assembler::csrrci(Register rd, ControlStatusReg csr, uint8_t imm5) {
1728   GenInstrCSR_ii(0b111, rd, csr, imm5);
1729 }
1730 
1731 // RV64I
1732 
lwu(Register rd,Register rs1,int16_t imm12)1733 void Assembler::lwu(Register rd, Register rs1, int16_t imm12) {
1734   GenInstrLoad_ri(0b110, rd, rs1, imm12);
1735 }
1736 
ld(Register rd,Register rs1,int16_t imm12)1737 void Assembler::ld(Register rd, Register rs1, int16_t imm12) {
1738   GenInstrLoad_ri(0b011, rd, rs1, imm12);
1739 }
1740 
sd(Register source,Register base,int16_t imm12)1741 void Assembler::sd(Register source, Register base, int16_t imm12) {
1742   GenInstrStore_rri(0b011, base, source, imm12);
1743 }
1744 
addiw(Register rd,Register rs1,int16_t imm12)1745 void Assembler::addiw(Register rd, Register rs1, int16_t imm12) {
1746   GenInstrI(0b000, OP_IMM_32, rd, rs1, imm12);
1747 }
1748 
slliw(Register rd,Register rs1,uint8_t shamt)1749 void Assembler::slliw(Register rd, Register rs1, uint8_t shamt) {
1750   GenInstrShiftW_ri(0, 0b001, rd, rs1, shamt & 0x1f);
1751 }
1752 
srliw(Register rd,Register rs1,uint8_t shamt)1753 void Assembler::srliw(Register rd, Register rs1, uint8_t shamt) {
1754   GenInstrShiftW_ri(0, 0b101, rd, rs1, shamt & 0x1f);
1755 }
1756 
sraiw(Register rd,Register rs1,uint8_t shamt)1757 void Assembler::sraiw(Register rd, Register rs1, uint8_t shamt) {
1758   GenInstrShiftW_ri(1, 0b101, rd, rs1, shamt & 0x1f);
1759 }
1760 
addw(Register rd,Register rs1,Register rs2)1761 void Assembler::addw(Register rd, Register rs1, Register rs2) {
1762   GenInstrALUW_rr(0b0000000, 0b000, rd, rs1, rs2);
1763 }
1764 
subw(Register rd,Register rs1,Register rs2)1765 void Assembler::subw(Register rd, Register rs1, Register rs2) {
1766   GenInstrALUW_rr(0b0100000, 0b000, rd, rs1, rs2);
1767 }
1768 
sllw(Register rd,Register rs1,Register rs2)1769 void Assembler::sllw(Register rd, Register rs1, Register rs2) {
1770   GenInstrALUW_rr(0b0000000, 0b001, rd, rs1, rs2);
1771 }
1772 
srlw(Register rd,Register rs1,Register rs2)1773 void Assembler::srlw(Register rd, Register rs1, Register rs2) {
1774   GenInstrALUW_rr(0b0000000, 0b101, rd, rs1, rs2);
1775 }
1776 
sraw(Register rd,Register rs1,Register rs2)1777 void Assembler::sraw(Register rd, Register rs1, Register rs2) {
1778   GenInstrALUW_rr(0b0100000, 0b101, rd, rs1, rs2);
1779 }
1780 
1781 // RV32M Standard Extension
1782 
mul(Register rd,Register rs1,Register rs2)1783 void Assembler::mul(Register rd, Register rs1, Register rs2) {
1784   GenInstrALU_rr(0b0000001, 0b000, rd, rs1, rs2);
1785 }
1786 
mulh(Register rd,Register rs1,Register rs2)1787 void Assembler::mulh(Register rd, Register rs1, Register rs2) {
1788   GenInstrALU_rr(0b0000001, 0b001, rd, rs1, rs2);
1789 }
1790 
mulhsu(Register rd,Register rs1,Register rs2)1791 void Assembler::mulhsu(Register rd, Register rs1, Register rs2) {
1792   GenInstrALU_rr(0b0000001, 0b010, rd, rs1, rs2);
1793 }
1794 
mulhu(Register rd,Register rs1,Register rs2)1795 void Assembler::mulhu(Register rd, Register rs1, Register rs2) {
1796   GenInstrALU_rr(0b0000001, 0b011, rd, rs1, rs2);
1797 }
1798 
div(Register rd,Register rs1,Register rs2)1799 void Assembler::div(Register rd, Register rs1, Register rs2) {
1800   GenInstrALU_rr(0b0000001, 0b100, rd, rs1, rs2);
1801 }
1802 
divu(Register rd,Register rs1,Register rs2)1803 void Assembler::divu(Register rd, Register rs1, Register rs2) {
1804   GenInstrALU_rr(0b0000001, 0b101, rd, rs1, rs2);
1805 }
1806 
rem(Register rd,Register rs1,Register rs2)1807 void Assembler::rem(Register rd, Register rs1, Register rs2) {
1808   GenInstrALU_rr(0b0000001, 0b110, rd, rs1, rs2);
1809 }
1810 
remu(Register rd,Register rs1,Register rs2)1811 void Assembler::remu(Register rd, Register rs1, Register rs2) {
1812   GenInstrALU_rr(0b0000001, 0b111, rd, rs1, rs2);
1813 }
1814 
1815 // RV64M Standard Extension (in addition to RV32M)
1816 
mulw(Register rd,Register rs1,Register rs2)1817 void Assembler::mulw(Register rd, Register rs1, Register rs2) {
1818   GenInstrALUW_rr(0b0000001, 0b000, rd, rs1, rs2);
1819 }
1820 
divw(Register rd,Register rs1,Register rs2)1821 void Assembler::divw(Register rd, Register rs1, Register rs2) {
1822   GenInstrALUW_rr(0b0000001, 0b100, rd, rs1, rs2);
1823 }
1824 
divuw(Register rd,Register rs1,Register rs2)1825 void Assembler::divuw(Register rd, Register rs1, Register rs2) {
1826   GenInstrALUW_rr(0b0000001, 0b101, rd, rs1, rs2);
1827 }
1828 
remw(Register rd,Register rs1,Register rs2)1829 void Assembler::remw(Register rd, Register rs1, Register rs2) {
1830   GenInstrALUW_rr(0b0000001, 0b110, rd, rs1, rs2);
1831 }
1832 
remuw(Register rd,Register rs1,Register rs2)1833 void Assembler::remuw(Register rd, Register rs1, Register rs2) {
1834   GenInstrALUW_rr(0b0000001, 0b111, rd, rs1, rs2);
1835 }
1836 
1837 // RV32A Standard Extension
1838 
lr_w(bool aq,bool rl,Register rd,Register rs1)1839 void Assembler::lr_w(bool aq, bool rl, Register rd, Register rs1) {
1840   GenInstrRAtomic(0b00010, aq, rl, 0b010, rd, rs1, zero_reg);
1841 }
1842 
sc_w(bool aq,bool rl,Register rd,Register rs1,Register rs2)1843 void Assembler::sc_w(bool aq, bool rl, Register rd, Register rs1,
1844                      Register rs2) {
1845   GenInstrRAtomic(0b00011, aq, rl, 0b010, rd, rs1, rs2);
1846 }
1847 
amoswap_w(bool aq,bool rl,Register rd,Register rs1,Register rs2)1848 void Assembler::amoswap_w(bool aq, bool rl, Register rd, Register rs1,
1849                           Register rs2) {
1850   GenInstrRAtomic(0b00001, aq, rl, 0b010, rd, rs1, rs2);
1851 }
1852 
amoadd_w(bool aq,bool rl,Register rd,Register rs1,Register rs2)1853 void Assembler::amoadd_w(bool aq, bool rl, Register rd, Register rs1,
1854                          Register rs2) {
1855   GenInstrRAtomic(0b00000, aq, rl, 0b010, rd, rs1, rs2);
1856 }
1857 
amoxor_w(bool aq,bool rl,Register rd,Register rs1,Register rs2)1858 void Assembler::amoxor_w(bool aq, bool rl, Register rd, Register rs1,
1859                          Register rs2) {
1860   GenInstrRAtomic(0b00100, aq, rl, 0b010, rd, rs1, rs2);
1861 }
1862 
amoand_w(bool aq,bool rl,Register rd,Register rs1,Register rs2)1863 void Assembler::amoand_w(bool aq, bool rl, Register rd, Register rs1,
1864                          Register rs2) {
1865   GenInstrRAtomic(0b01100, aq, rl, 0b010, rd, rs1, rs2);
1866 }
1867 
amoor_w(bool aq,bool rl,Register rd,Register rs1,Register rs2)1868 void Assembler::amoor_w(bool aq, bool rl, Register rd, Register rs1,
1869                         Register rs2) {
1870   GenInstrRAtomic(0b01000, aq, rl, 0b010, rd, rs1, rs2);
1871 }
1872 
amomin_w(bool aq,bool rl,Register rd,Register rs1,Register rs2)1873 void Assembler::amomin_w(bool aq, bool rl, Register rd, Register rs1,
1874                          Register rs2) {
1875   GenInstrRAtomic(0b10000, aq, rl, 0b010, rd, rs1, rs2);
1876 }
1877 
amomax_w(bool aq,bool rl,Register rd,Register rs1,Register rs2)1878 void Assembler::amomax_w(bool aq, bool rl, Register rd, Register rs1,
1879                          Register rs2) {
1880   GenInstrRAtomic(0b10100, aq, rl, 0b010, rd, rs1, rs2);
1881 }
1882 
amominu_w(bool aq,bool rl,Register rd,Register rs1,Register rs2)1883 void Assembler::amominu_w(bool aq, bool rl, Register rd, Register rs1,
1884                           Register rs2) {
1885   GenInstrRAtomic(0b11000, aq, rl, 0b010, rd, rs1, rs2);
1886 }
1887 
amomaxu_w(bool aq,bool rl,Register rd,Register rs1,Register rs2)1888 void Assembler::amomaxu_w(bool aq, bool rl, Register rd, Register rs1,
1889                           Register rs2) {
1890   GenInstrRAtomic(0b11100, aq, rl, 0b010, rd, rs1, rs2);
1891 }
1892 
1893 // RV64A Standard Extension (in addition to RV32A)
1894 
lr_d(bool aq,bool rl,Register rd,Register rs1)1895 void Assembler::lr_d(bool aq, bool rl, Register rd, Register rs1) {
1896   GenInstrRAtomic(0b00010, aq, rl, 0b011, rd, rs1, zero_reg);
1897 }
1898 
sc_d(bool aq,bool rl,Register rd,Register rs1,Register rs2)1899 void Assembler::sc_d(bool aq, bool rl, Register rd, Register rs1,
1900                      Register rs2) {
1901   GenInstrRAtomic(0b00011, aq, rl, 0b011, rd, rs1, rs2);
1902 }
1903 
amoswap_d(bool aq,bool rl,Register rd,Register rs1,Register rs2)1904 void Assembler::amoswap_d(bool aq, bool rl, Register rd, Register rs1,
1905                           Register rs2) {
1906   GenInstrRAtomic(0b00001, aq, rl, 0b011, rd, rs1, rs2);
1907 }
1908 
amoadd_d(bool aq,bool rl,Register rd,Register rs1,Register rs2)1909 void Assembler::amoadd_d(bool aq, bool rl, Register rd, Register rs1,
1910                          Register rs2) {
1911   GenInstrRAtomic(0b00000, aq, rl, 0b011, rd, rs1, rs2);
1912 }
1913 
amoxor_d(bool aq,bool rl,Register rd,Register rs1,Register rs2)1914 void Assembler::amoxor_d(bool aq, bool rl, Register rd, Register rs1,
1915                          Register rs2) {
1916   GenInstrRAtomic(0b00100, aq, rl, 0b011, rd, rs1, rs2);
1917 }
1918 
amoand_d(bool aq,bool rl,Register rd,Register rs1,Register rs2)1919 void Assembler::amoand_d(bool aq, bool rl, Register rd, Register rs1,
1920                          Register rs2) {
1921   GenInstrRAtomic(0b01100, aq, rl, 0b011, rd, rs1, rs2);
1922 }
1923 
amoor_d(bool aq,bool rl,Register rd,Register rs1,Register rs2)1924 void Assembler::amoor_d(bool aq, bool rl, Register rd, Register rs1,
1925                         Register rs2) {
1926   GenInstrRAtomic(0b01000, aq, rl, 0b011, rd, rs1, rs2);
1927 }
1928 
amomin_d(bool aq,bool rl,Register rd,Register rs1,Register rs2)1929 void Assembler::amomin_d(bool aq, bool rl, Register rd, Register rs1,
1930                          Register rs2) {
1931   GenInstrRAtomic(0b10000, aq, rl, 0b011, rd, rs1, rs2);
1932 }
1933 
amomax_d(bool aq,bool rl,Register rd,Register rs1,Register rs2)1934 void Assembler::amomax_d(bool aq, bool rl, Register rd, Register rs1,
1935                          Register rs2) {
1936   GenInstrRAtomic(0b10100, aq, rl, 0b011, rd, rs1, rs2);
1937 }
1938 
amominu_d(bool aq,bool rl,Register rd,Register rs1,Register rs2)1939 void Assembler::amominu_d(bool aq, bool rl, Register rd, Register rs1,
1940                           Register rs2) {
1941   GenInstrRAtomic(0b11000, aq, rl, 0b011, rd, rs1, rs2);
1942 }
1943 
amomaxu_d(bool aq,bool rl,Register rd,Register rs1,Register rs2)1944 void Assembler::amomaxu_d(bool aq, bool rl, Register rd, Register rs1,
1945                           Register rs2) {
1946   GenInstrRAtomic(0b11100, aq, rl, 0b011, rd, rs1, rs2);
1947 }
1948 
1949 // RV32F Standard Extension
1950 
flw(FPURegister rd,Register rs1,int16_t imm12)1951 void Assembler::flw(FPURegister rd, Register rs1, int16_t imm12) {
1952   GenInstrLoadFP_ri(0b010, rd, rs1, imm12);
1953 }
1954 
fsw(FPURegister source,Register base,int16_t imm12)1955 void Assembler::fsw(FPURegister source, Register base, int16_t imm12) {
1956   GenInstrStoreFP_rri(0b010, base, source, imm12);
1957 }
1958 
fmadd_s(FPURegister rd,FPURegister rs1,FPURegister rs2,FPURegister rs3,RoundingMode frm)1959 void Assembler::fmadd_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
1960                         FPURegister rs3, RoundingMode frm) {
1961   GenInstrR4(0b00, MADD, rd, rs1, rs2, rs3, frm);
1962 }
1963 
fmsub_s(FPURegister rd,FPURegister rs1,FPURegister rs2,FPURegister rs3,RoundingMode frm)1964 void Assembler::fmsub_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
1965                         FPURegister rs3, RoundingMode frm) {
1966   GenInstrR4(0b00, MSUB, rd, rs1, rs2, rs3, frm);
1967 }
1968 
fnmsub_s(FPURegister rd,FPURegister rs1,FPURegister rs2,FPURegister rs3,RoundingMode frm)1969 void Assembler::fnmsub_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
1970                          FPURegister rs3, RoundingMode frm) {
1971   GenInstrR4(0b00, NMSUB, rd, rs1, rs2, rs3, frm);
1972 }
1973 
fnmadd_s(FPURegister rd,FPURegister rs1,FPURegister rs2,FPURegister rs3,RoundingMode frm)1974 void Assembler::fnmadd_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
1975                          FPURegister rs3, RoundingMode frm) {
1976   GenInstrR4(0b00, NMADD, rd, rs1, rs2, rs3, frm);
1977 }
1978 
fadd_s(FPURegister rd,FPURegister rs1,FPURegister rs2,RoundingMode frm)1979 void Assembler::fadd_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
1980                        RoundingMode frm) {
1981   GenInstrALUFP_rr(0b0000000, frm, rd, rs1, rs2);
1982 }
1983 
fsub_s(FPURegister rd,FPURegister rs1,FPURegister rs2,RoundingMode frm)1984 void Assembler::fsub_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
1985                        RoundingMode frm) {
1986   GenInstrALUFP_rr(0b0000100, frm, rd, rs1, rs2);
1987 }
1988 
fmul_s(FPURegister rd,FPURegister rs1,FPURegister rs2,RoundingMode frm)1989 void Assembler::fmul_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
1990                        RoundingMode frm) {
1991   GenInstrALUFP_rr(0b0001000, frm, rd, rs1, rs2);
1992 }
1993 
fdiv_s(FPURegister rd,FPURegister rs1,FPURegister rs2,RoundingMode frm)1994 void Assembler::fdiv_s(FPURegister rd, FPURegister rs1, FPURegister rs2,
1995                        RoundingMode frm) {
1996   GenInstrALUFP_rr(0b0001100, frm, rd, rs1, rs2);
1997 }
1998 
fsqrt_s(FPURegister rd,FPURegister rs1,RoundingMode frm)1999 void Assembler::fsqrt_s(FPURegister rd, FPURegister rs1, RoundingMode frm) {
2000   GenInstrALUFP_rr(0b0101100, frm, rd, rs1, zero_reg);
2001 }
2002 
fsgnj_s(FPURegister rd,FPURegister rs1,FPURegister rs2)2003 void Assembler::fsgnj_s(FPURegister rd, FPURegister rs1, FPURegister rs2) {
2004   GenInstrALUFP_rr(0b0010000, 0b000, rd, rs1, rs2);
2005 }
2006 
fsgnjn_s(FPURegister rd,FPURegister rs1,FPURegister rs2)2007 void Assembler::fsgnjn_s(FPURegister rd, FPURegister rs1, FPURegister rs2) {
2008   GenInstrALUFP_rr(0b0010000, 0b001, rd, rs1, rs2);
2009 }
2010 
fsgnjx_s(FPURegister rd,FPURegister rs1,FPURegister rs2)2011 void Assembler::fsgnjx_s(FPURegister rd, FPURegister rs1, FPURegister rs2) {
2012   GenInstrALUFP_rr(0b0010000, 0b010, rd, rs1, rs2);
2013 }
2014 
fmin_s(FPURegister rd,FPURegister rs1,FPURegister rs2)2015 void Assembler::fmin_s(FPURegister rd, FPURegister rs1, FPURegister rs2) {
2016   GenInstrALUFP_rr(0b0010100, 0b000, rd, rs1, rs2);
2017 }
2018 
fmax_s(FPURegister rd,FPURegister rs1,FPURegister rs2)2019 void Assembler::fmax_s(FPURegister rd, FPURegister rs1, FPURegister rs2) {
2020   GenInstrALUFP_rr(0b0010100, 0b001, rd, rs1, rs2);
2021 }
2022 
fcvt_w_s(Register rd,FPURegister rs1,RoundingMode frm)2023 void Assembler::fcvt_w_s(Register rd, FPURegister rs1, RoundingMode frm) {
2024   GenInstrALUFP_rr(0b1100000, frm, rd, rs1, zero_reg);
2025 }
2026 
fcvt_wu_s(Register rd,FPURegister rs1,RoundingMode frm)2027 void Assembler::fcvt_wu_s(Register rd, FPURegister rs1, RoundingMode frm) {
2028   GenInstrALUFP_rr(0b1100000, frm, rd, rs1, ToRegister(1));
2029 }
2030 
fmv_x_w(Register rd,FPURegister rs1)2031 void Assembler::fmv_x_w(Register rd, FPURegister rs1) {
2032   GenInstrALUFP_rr(0b1110000, 0b000, rd, rs1, zero_reg);
2033 }
2034 
feq_s(Register rd,FPURegister rs1,FPURegister rs2)2035 void Assembler::feq_s(Register rd, FPURegister rs1, FPURegister rs2) {
2036   GenInstrALUFP_rr(0b1010000, 0b010, rd, rs1, rs2);
2037 }
2038 
flt_s(Register rd,FPURegister rs1,FPURegister rs2)2039 void Assembler::flt_s(Register rd, FPURegister rs1, FPURegister rs2) {
2040   GenInstrALUFP_rr(0b1010000, 0b001, rd, rs1, rs2);
2041 }
2042 
fle_s(Register rd,FPURegister rs1,FPURegister rs2)2043 void Assembler::fle_s(Register rd, FPURegister rs1, FPURegister rs2) {
2044   GenInstrALUFP_rr(0b1010000, 0b000, rd, rs1, rs2);
2045 }
2046 
fclass_s(Register rd,FPURegister rs1)2047 void Assembler::fclass_s(Register rd, FPURegister rs1) {
2048   GenInstrALUFP_rr(0b1110000, 0b001, rd, rs1, zero_reg);
2049 }
2050 
fcvt_s_w(FPURegister rd,Register rs1,RoundingMode frm)2051 void Assembler::fcvt_s_w(FPURegister rd, Register rs1, RoundingMode frm) {
2052   GenInstrALUFP_rr(0b1101000, frm, rd, rs1, zero_reg);
2053 }
2054 
fcvt_s_wu(FPURegister rd,Register rs1,RoundingMode frm)2055 void Assembler::fcvt_s_wu(FPURegister rd, Register rs1, RoundingMode frm) {
2056   GenInstrALUFP_rr(0b1101000, frm, rd, rs1, ToRegister(1));
2057 }
2058 
fmv_w_x(FPURegister rd,Register rs1)2059 void Assembler::fmv_w_x(FPURegister rd, Register rs1) {
2060   GenInstrALUFP_rr(0b1111000, 0b000, rd, rs1, zero_reg);
2061 }
2062 
2063 // RV64F Standard Extension (in addition to RV32F)
2064 
fcvt_l_s(Register rd,FPURegister rs1,RoundingMode frm)2065 void Assembler::fcvt_l_s(Register rd, FPURegister rs1, RoundingMode frm) {
2066   GenInstrALUFP_rr(0b1100000, frm, rd, rs1, ToRegister(2));
2067 }
2068 
fcvt_lu_s(Register rd,FPURegister rs1,RoundingMode frm)2069 void Assembler::fcvt_lu_s(Register rd, FPURegister rs1, RoundingMode frm) {
2070   GenInstrALUFP_rr(0b1100000, frm, rd, rs1, ToRegister(3));
2071 }
2072 
fcvt_s_l(FPURegister rd,Register rs1,RoundingMode frm)2073 void Assembler::fcvt_s_l(FPURegister rd, Register rs1, RoundingMode frm) {
2074   GenInstrALUFP_rr(0b1101000, frm, rd, rs1, ToRegister(2));
2075 }
2076 
fcvt_s_lu(FPURegister rd,Register rs1,RoundingMode frm)2077 void Assembler::fcvt_s_lu(FPURegister rd, Register rs1, RoundingMode frm) {
2078   GenInstrALUFP_rr(0b1101000, frm, rd, rs1, ToRegister(3));
2079 }
2080 
2081 // RV32D Standard Extension
2082 
fld(FPURegister rd,Register rs1,int16_t imm12)2083 void Assembler::fld(FPURegister rd, Register rs1, int16_t imm12) {
2084   GenInstrLoadFP_ri(0b011, rd, rs1, imm12);
2085 }
2086 
fsd(FPURegister source,Register base,int16_t imm12)2087 void Assembler::fsd(FPURegister source, Register base, int16_t imm12) {
2088   GenInstrStoreFP_rri(0b011, base, source, imm12);
2089 }
2090 
fmadd_d(FPURegister rd,FPURegister rs1,FPURegister rs2,FPURegister rs3,RoundingMode frm)2091 void Assembler::fmadd_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
2092                         FPURegister rs3, RoundingMode frm) {
2093   GenInstrR4(0b01, MADD, rd, rs1, rs2, rs3, frm);
2094 }
2095 
fmsub_d(FPURegister rd,FPURegister rs1,FPURegister rs2,FPURegister rs3,RoundingMode frm)2096 void Assembler::fmsub_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
2097                         FPURegister rs3, RoundingMode frm) {
2098   GenInstrR4(0b01, MSUB, rd, rs1, rs2, rs3, frm);
2099 }
2100 
fnmsub_d(FPURegister rd,FPURegister rs1,FPURegister rs2,FPURegister rs3,RoundingMode frm)2101 void Assembler::fnmsub_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
2102                          FPURegister rs3, RoundingMode frm) {
2103   GenInstrR4(0b01, NMSUB, rd, rs1, rs2, rs3, frm);
2104 }
2105 
fnmadd_d(FPURegister rd,FPURegister rs1,FPURegister rs2,FPURegister rs3,RoundingMode frm)2106 void Assembler::fnmadd_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
2107                          FPURegister rs3, RoundingMode frm) {
2108   GenInstrR4(0b01, NMADD, rd, rs1, rs2, rs3, frm);
2109 }
2110 
fadd_d(FPURegister rd,FPURegister rs1,FPURegister rs2,RoundingMode frm)2111 void Assembler::fadd_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
2112                        RoundingMode frm) {
2113   GenInstrALUFP_rr(0b0000001, frm, rd, rs1, rs2);
2114 }
2115 
fsub_d(FPURegister rd,FPURegister rs1,FPURegister rs2,RoundingMode frm)2116 void Assembler::fsub_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
2117                        RoundingMode frm) {
2118   GenInstrALUFP_rr(0b0000101, frm, rd, rs1, rs2);
2119 }
2120 
fmul_d(FPURegister rd,FPURegister rs1,FPURegister rs2,RoundingMode frm)2121 void Assembler::fmul_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
2122                        RoundingMode frm) {
2123   GenInstrALUFP_rr(0b0001001, frm, rd, rs1, rs2);
2124 }
2125 
fdiv_d(FPURegister rd,FPURegister rs1,FPURegister rs2,RoundingMode frm)2126 void Assembler::fdiv_d(FPURegister rd, FPURegister rs1, FPURegister rs2,
2127                        RoundingMode frm) {
2128   GenInstrALUFP_rr(0b0001101, frm, rd, rs1, rs2);
2129 }
2130 
fsqrt_d(FPURegister rd,FPURegister rs1,RoundingMode frm)2131 void Assembler::fsqrt_d(FPURegister rd, FPURegister rs1, RoundingMode frm) {
2132   GenInstrALUFP_rr(0b0101101, frm, rd, rs1, zero_reg);
2133 }
2134 
fsgnj_d(FPURegister rd,FPURegister rs1,FPURegister rs2)2135 void Assembler::fsgnj_d(FPURegister rd, FPURegister rs1, FPURegister rs2) {
2136   GenInstrALUFP_rr(0b0010001, 0b000, rd, rs1, rs2);
2137 }
2138 
fsgnjn_d(FPURegister rd,FPURegister rs1,FPURegister rs2)2139 void Assembler::fsgnjn_d(FPURegister rd, FPURegister rs1, FPURegister rs2) {
2140   GenInstrALUFP_rr(0b0010001, 0b001, rd, rs1, rs2);
2141 }
2142 
fsgnjx_d(FPURegister rd,FPURegister rs1,FPURegister rs2)2143 void Assembler::fsgnjx_d(FPURegister rd, FPURegister rs1, FPURegister rs2) {
2144   GenInstrALUFP_rr(0b0010001, 0b010, rd, rs1, rs2);
2145 }
2146 
fmin_d(FPURegister rd,FPURegister rs1,FPURegister rs2)2147 void Assembler::fmin_d(FPURegister rd, FPURegister rs1, FPURegister rs2) {
2148   GenInstrALUFP_rr(0b0010101, 0b000, rd, rs1, rs2);
2149 }
2150 
fmax_d(FPURegister rd,FPURegister rs1,FPURegister rs2)2151 void Assembler::fmax_d(FPURegister rd, FPURegister rs1, FPURegister rs2) {
2152   GenInstrALUFP_rr(0b0010101, 0b001, rd, rs1, rs2);
2153 }
2154 
fcvt_s_d(FPURegister rd,FPURegister rs1,RoundingMode frm)2155 void Assembler::fcvt_s_d(FPURegister rd, FPURegister rs1, RoundingMode frm) {
2156   GenInstrALUFP_rr(0b0100000, frm, rd, rs1, ToRegister(1));
2157 }
2158 
fcvt_d_s(FPURegister rd,FPURegister rs1,RoundingMode frm)2159 void Assembler::fcvt_d_s(FPURegister rd, FPURegister rs1, RoundingMode frm) {
2160   GenInstrALUFP_rr(0b0100001, frm, rd, rs1, zero_reg);
2161 }
2162 
feq_d(Register rd,FPURegister rs1,FPURegister rs2)2163 void Assembler::feq_d(Register rd, FPURegister rs1, FPURegister rs2) {
2164   GenInstrALUFP_rr(0b1010001, 0b010, rd, rs1, rs2);
2165 }
2166 
flt_d(Register rd,FPURegister rs1,FPURegister rs2)2167 void Assembler::flt_d(Register rd, FPURegister rs1, FPURegister rs2) {
2168   GenInstrALUFP_rr(0b1010001, 0b001, rd, rs1, rs2);
2169 }
2170 
fle_d(Register rd,FPURegister rs1,FPURegister rs2)2171 void Assembler::fle_d(Register rd, FPURegister rs1, FPURegister rs2) {
2172   GenInstrALUFP_rr(0b1010001, 0b000, rd, rs1, rs2);
2173 }
2174 
fclass_d(Register rd,FPURegister rs1)2175 void Assembler::fclass_d(Register rd, FPURegister rs1) {
2176   GenInstrALUFP_rr(0b1110001, 0b001, rd, rs1, zero_reg);
2177 }
2178 
fcvt_w_d(Register rd,FPURegister rs1,RoundingMode frm)2179 void Assembler::fcvt_w_d(Register rd, FPURegister rs1, RoundingMode frm) {
2180   GenInstrALUFP_rr(0b1100001, frm, rd, rs1, zero_reg);
2181 }
2182 
fcvt_wu_d(Register rd,FPURegister rs1,RoundingMode frm)2183 void Assembler::fcvt_wu_d(Register rd, FPURegister rs1, RoundingMode frm) {
2184   GenInstrALUFP_rr(0b1100001, frm, rd, rs1, ToRegister(1));
2185 }
2186 
fcvt_d_w(FPURegister rd,Register rs1,RoundingMode frm)2187 void Assembler::fcvt_d_w(FPURegister rd, Register rs1, RoundingMode frm) {
2188   GenInstrALUFP_rr(0b1101001, frm, rd, rs1, zero_reg);
2189 }
2190 
fcvt_d_wu(FPURegister rd,Register rs1,RoundingMode frm)2191 void Assembler::fcvt_d_wu(FPURegister rd, Register rs1, RoundingMode frm) {
2192   GenInstrALUFP_rr(0b1101001, frm, rd, rs1, ToRegister(1));
2193 }
2194 
2195 // RV64D Standard Extension (in addition to RV32D)
2196 
fcvt_l_d(Register rd,FPURegister rs1,RoundingMode frm)2197 void Assembler::fcvt_l_d(Register rd, FPURegister rs1, RoundingMode frm) {
2198   GenInstrALUFP_rr(0b1100001, frm, rd, rs1, ToRegister(2));
2199 }
2200 
fcvt_lu_d(Register rd,FPURegister rs1,RoundingMode frm)2201 void Assembler::fcvt_lu_d(Register rd, FPURegister rs1, RoundingMode frm) {
2202   GenInstrALUFP_rr(0b1100001, frm, rd, rs1, ToRegister(3));
2203 }
2204 
fmv_x_d(Register rd,FPURegister rs1)2205 void Assembler::fmv_x_d(Register rd, FPURegister rs1) {
2206   GenInstrALUFP_rr(0b1110001, 0b000, rd, rs1, zero_reg);
2207 }
2208 
fcvt_d_l(FPURegister rd,Register rs1,RoundingMode frm)2209 void Assembler::fcvt_d_l(FPURegister rd, Register rs1, RoundingMode frm) {
2210   GenInstrALUFP_rr(0b1101001, frm, rd, rs1, ToRegister(2));
2211 }
2212 
fcvt_d_lu(FPURegister rd,Register rs1,RoundingMode frm)2213 void Assembler::fcvt_d_lu(FPURegister rd, Register rs1, RoundingMode frm) {
2214   GenInstrALUFP_rr(0b1101001, frm, rd, rs1, ToRegister(3));
2215 }
2216 
fmv_d_x(FPURegister rd,Register rs1)2217 void Assembler::fmv_d_x(FPURegister rd, Register rs1) {
2218   GenInstrALUFP_rr(0b1111001, 0b000, rd, rs1, zero_reg);
2219 }
2220 
2221 // RV64C Standard Extension
c_nop()2222 void Assembler::c_nop() { GenInstrCI(0b000, C1, zero_reg, 0); }
2223 
c_addi(Register rd,int8_t imm6)2224 void Assembler::c_addi(Register rd, int8_t imm6) {
2225   DCHECK(rd != zero_reg && imm6 != 0);
2226   GenInstrCI(0b000, C1, rd, imm6);
2227 }
2228 
c_addiw(Register rd,int8_t imm6)2229 void Assembler::c_addiw(Register rd, int8_t imm6) {
2230   DCHECK(rd != zero_reg);
2231   GenInstrCI(0b001, C1, rd, imm6);
2232 }
2233 
c_addi16sp(int16_t imm10)2234 void Assembler::c_addi16sp(int16_t imm10) {
2235   DCHECK(is_int10(imm10) && (imm10 & 0xf) == 0);
2236   uint8_t uimm6 = ((imm10 & 0x200) >> 4) | (imm10 & 0x10) |
2237                   ((imm10 & 0x40) >> 3) | ((imm10 & 0x180) >> 6) |
2238                   ((imm10 & 0x20) >> 5);
2239   GenInstrCIU(0b011, C1, sp, uimm6);
2240 }
2241 
c_addi4spn(Register rd,int16_t uimm10)2242 void Assembler::c_addi4spn(Register rd, int16_t uimm10) {
2243   DCHECK(is_uint10(uimm10) && (uimm10 != 0));
2244   uint8_t uimm8 = ((uimm10 & 0x4) >> 1) | ((uimm10 & 0x8) >> 3) |
2245                   ((uimm10 & 0x30) << 2) | ((uimm10 & 0x3c0) >> 4);
2246   GenInstrCIW(0b000, C0, rd, uimm8);
2247 }
2248 
c_li(Register rd,int8_t imm6)2249 void Assembler::c_li(Register rd, int8_t imm6) {
2250   DCHECK(rd != zero_reg);
2251   GenInstrCI(0b010, C1, rd, imm6);
2252 }
2253 
c_lui(Register rd,int8_t imm6)2254 void Assembler::c_lui(Register rd, int8_t imm6) {
2255   DCHECK(rd != zero_reg && rd != sp && imm6 != 0);
2256   GenInstrCI(0b011, C1, rd, imm6);
2257 }
2258 
c_slli(Register rd,uint8_t shamt6)2259 void Assembler::c_slli(Register rd, uint8_t shamt6) {
2260   DCHECK(rd != zero_reg && shamt6 != 0);
2261   GenInstrCIU(0b000, C2, rd, shamt6);
2262 }
2263 
c_fldsp(FPURegister rd,uint16_t uimm9)2264 void Assembler::c_fldsp(FPURegister rd, uint16_t uimm9) {
2265   DCHECK(is_uint9(uimm9) && (uimm9 & 0x7) == 0);
2266   uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6);
2267   GenInstrCIU(0b001, C2, rd, uimm6);
2268 }
2269 
c_lwsp(Register rd,uint16_t uimm8)2270 void Assembler::c_lwsp(Register rd, uint16_t uimm8) {
2271   DCHECK(rd != zero_reg && is_uint8(uimm8) && (uimm8 & 0x3) == 0);
2272   uint8_t uimm6 = (uimm8 & 0x3c) | ((uimm8 & 0xc0) >> 6);
2273   GenInstrCIU(0b010, C2, rd, uimm6);
2274 }
2275 
c_ldsp(Register rd,uint16_t uimm9)2276 void Assembler::c_ldsp(Register rd, uint16_t uimm9) {
2277   DCHECK(rd != zero_reg && is_uint9(uimm9) && (uimm9 & 0x7) == 0);
2278   uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6);
2279   GenInstrCIU(0b011, C2, rd, uimm6);
2280 }
2281 
c_jr(Register rs1)2282 void Assembler::c_jr(Register rs1) {
2283   DCHECK(rs1 != zero_reg);
2284   GenInstrCR(0b1000, C2, rs1, zero_reg);
2285   BlockTrampolinePoolFor(1);
2286 }
2287 
c_mv(Register rd,Register rs2)2288 void Assembler::c_mv(Register rd, Register rs2) {
2289   DCHECK(rd != zero_reg && rs2 != zero_reg);
2290   GenInstrCR(0b1000, C2, rd, rs2);
2291 }
2292 
c_ebreak()2293 void Assembler::c_ebreak() { GenInstrCR(0b1001, C2, zero_reg, zero_reg); }
2294 
c_jalr(Register rs1)2295 void Assembler::c_jalr(Register rs1) {
2296   DCHECK(rs1 != zero_reg);
2297   GenInstrCR(0b1001, C2, rs1, zero_reg);
2298   BlockTrampolinePoolFor(1);
2299 }
2300 
c_add(Register rd,Register rs2)2301 void Assembler::c_add(Register rd, Register rs2) {
2302   DCHECK(rd != zero_reg && rs2 != zero_reg);
2303   GenInstrCR(0b1001, C2, rd, rs2);
2304 }
2305 
2306 // CA Instructions
c_sub(Register rd,Register rs2)2307 void Assembler::c_sub(Register rd, Register rs2) {
2308   DCHECK(((rd.code() & 0b11000) == 0b01000) &&
2309          ((rs2.code() & 0b11000) == 0b01000));
2310   GenInstrCA(0b100011, C1, rd, 0b00, rs2);
2311 }
2312 
c_xor(Register rd,Register rs2)2313 void Assembler::c_xor(Register rd, Register rs2) {
2314   DCHECK(((rd.code() & 0b11000) == 0b01000) &&
2315          ((rs2.code() & 0b11000) == 0b01000));
2316   GenInstrCA(0b100011, C1, rd, 0b01, rs2);
2317 }
2318 
c_or(Register rd,Register rs2)2319 void Assembler::c_or(Register rd, Register rs2) {
2320   DCHECK(((rd.code() & 0b11000) == 0b01000) &&
2321          ((rs2.code() & 0b11000) == 0b01000));
2322   GenInstrCA(0b100011, C1, rd, 0b10, rs2);
2323 }
2324 
c_and(Register rd,Register rs2)2325 void Assembler::c_and(Register rd, Register rs2) {
2326   DCHECK(((rd.code() & 0b11000) == 0b01000) &&
2327          ((rs2.code() & 0b11000) == 0b01000));
2328   GenInstrCA(0b100011, C1, rd, 0b11, rs2);
2329 }
2330 
c_subw(Register rd,Register rs2)2331 void Assembler::c_subw(Register rd, Register rs2) {
2332   DCHECK(((rd.code() & 0b11000) == 0b01000) &&
2333          ((rs2.code() & 0b11000) == 0b01000));
2334   GenInstrCA(0b100111, C1, rd, 0b00, rs2);
2335 }
2336 
c_addw(Register rd,Register rs2)2337 void Assembler::c_addw(Register rd, Register rs2) {
2338   DCHECK(((rd.code() & 0b11000) == 0b01000) &&
2339          ((rs2.code() & 0b11000) == 0b01000));
2340   GenInstrCA(0b100111, C1, rd, 0b01, rs2);
2341 }
2342 
c_swsp(Register rs2,uint16_t uimm8)2343 void Assembler::c_swsp(Register rs2, uint16_t uimm8) {
2344   DCHECK(is_uint8(uimm8) && (uimm8 & 0x3) == 0);
2345   uint8_t uimm6 = (uimm8 & 0x3c) | ((uimm8 & 0xc0) >> 6);
2346   GenInstrCSS(0b110, C2, rs2, uimm6);
2347 }
2348 
c_sdsp(Register rs2,uint16_t uimm9)2349 void Assembler::c_sdsp(Register rs2, uint16_t uimm9) {
2350   DCHECK(is_uint9(uimm9) && (uimm9 & 0x7) == 0);
2351   uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6);
2352   GenInstrCSS(0b111, C2, rs2, uimm6);
2353 }
2354 
c_fsdsp(FPURegister rs2,uint16_t uimm9)2355 void Assembler::c_fsdsp(FPURegister rs2, uint16_t uimm9) {
2356   DCHECK(is_uint9(uimm9) && (uimm9 & 0x7) == 0);
2357   uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6);
2358   GenInstrCSS(0b101, C2, rs2, uimm6);
2359 }
2360 
2361 // CL Instructions
2362 
c_lw(Register rd,Register rs1,uint16_t uimm7)2363 void Assembler::c_lw(Register rd, Register rs1, uint16_t uimm7) {
2364   DCHECK(((rd.code() & 0b11000) == 0b01000) &&
2365          ((rs1.code() & 0b11000) == 0b01000) && is_uint7(uimm7) &&
2366          ((uimm7 & 0x3) == 0));
2367   uint8_t uimm5 =
2368       ((uimm7 & 0x4) >> 1) | ((uimm7 & 0x40) >> 6) | ((uimm7 & 0x38) >> 1);
2369   GenInstrCL(0b010, C0, rd, rs1, uimm5);
2370 }
2371 
c_ld(Register rd,Register rs1,uint16_t uimm8)2372 void Assembler::c_ld(Register rd, Register rs1, uint16_t uimm8) {
2373   DCHECK(((rd.code() & 0b11000) == 0b01000) &&
2374          ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
2375          ((uimm8 & 0x7) == 0));
2376   uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
2377   GenInstrCL(0b011, C0, rd, rs1, uimm5);
2378 }
2379 
c_fld(FPURegister rd,Register rs1,uint16_t uimm8)2380 void Assembler::c_fld(FPURegister rd, Register rs1, uint16_t uimm8) {
2381   DCHECK(((rd.code() & 0b11000) == 0b01000) &&
2382          ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
2383          ((uimm8 & 0x7) == 0));
2384   uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
2385   GenInstrCL(0b001, C0, rd, rs1, uimm5);
2386 }
2387 
2388 // CS Instructions
2389 
c_sw(Register rs2,Register rs1,uint16_t uimm7)2390 void Assembler::c_sw(Register rs2, Register rs1, uint16_t uimm7) {
2391   DCHECK(((rs2.code() & 0b11000) == 0b01000) &&
2392          ((rs1.code() & 0b11000) == 0b01000) && is_uint7(uimm7) &&
2393          ((uimm7 & 0x3) == 0));
2394   uint8_t uimm5 =
2395       ((uimm7 & 0x4) >> 1) | ((uimm7 & 0x40) >> 6) | ((uimm7 & 0x38) >> 1);
2396   GenInstrCS(0b110, C0, rs2, rs1, uimm5);
2397 }
2398 
c_sd(Register rs2,Register rs1,uint16_t uimm8)2399 void Assembler::c_sd(Register rs2, Register rs1, uint16_t uimm8) {
2400   DCHECK(((rs2.code() & 0b11000) == 0b01000) &&
2401          ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
2402          ((uimm8 & 0x7) == 0));
2403   uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
2404   GenInstrCS(0b111, C0, rs2, rs1, uimm5);
2405 }
2406 
c_fsd(FPURegister rs2,Register rs1,uint16_t uimm8)2407 void Assembler::c_fsd(FPURegister rs2, Register rs1, uint16_t uimm8) {
2408   DCHECK(((rs2.code() & 0b11000) == 0b01000) &&
2409          ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
2410          ((uimm8 & 0x7) == 0));
2411   uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
2412   GenInstrCS(0b101, C0, rs2, rs1, uimm5);
2413 }
2414 
2415 // CJ Instructions
2416 
c_j(int16_t imm12)2417 void Assembler::c_j(int16_t imm12) {
2418   DCHECK(is_int12(imm12));
2419   int16_t uimm11 = ((imm12 & 0x800) >> 1) | ((imm12 & 0x400) >> 4) |
2420                    ((imm12 & 0x300) >> 1) | ((imm12 & 0x80) >> 3) |
2421                    ((imm12 & 0x40) >> 1) | ((imm12 & 0x20) >> 5) |
2422                    ((imm12 & 0x10) << 5) | (imm12 & 0xe);
2423   GenInstrCJ(0b101, C1, uimm11);
2424   BlockTrampolinePoolFor(1);
2425 }
2426 
2427 // CB Instructions
2428 
c_bnez(Register rs1,int16_t imm9)2429 void Assembler::c_bnez(Register rs1, int16_t imm9) {
2430   DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int9(imm9));
2431   uint8_t uimm8 = ((imm9 & 0x20) >> 5) | ((imm9 & 0x6)) | ((imm9 & 0xc0) >> 3) |
2432                   ((imm9 & 0x18) << 2) | ((imm9 & 0x100) >> 1);
2433   GenInstrCB(0b111, C1, rs1, uimm8);
2434 }
2435 
c_beqz(Register rs1,int16_t imm9)2436 void Assembler::c_beqz(Register rs1, int16_t imm9) {
2437   DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int9(imm9));
2438   uint8_t uimm8 = ((imm9 & 0x20) >> 5) | ((imm9 & 0x6)) | ((imm9 & 0xc0) >> 3) |
2439                   ((imm9 & 0x18) << 2) | ((imm9 & 0x100) >> 1);
2440   GenInstrCB(0b110, C1, rs1, uimm8);
2441 }
2442 
c_srli(Register rs1,int8_t shamt6)2443 void Assembler::c_srli(Register rs1, int8_t shamt6) {
2444   DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int6(shamt6));
2445   GenInstrCBA(0b100, 0b00, C1, rs1, shamt6);
2446 }
2447 
c_srai(Register rs1,int8_t shamt6)2448 void Assembler::c_srai(Register rs1, int8_t shamt6) {
2449   DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int6(shamt6));
2450   GenInstrCBA(0b100, 0b01, C1, rs1, shamt6);
2451 }
2452 
c_andi(Register rs1,int8_t imm6)2453 void Assembler::c_andi(Register rs1, int8_t imm6) {
2454   DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int6(imm6));
2455   GenInstrCBA(0b100, 0b10, C1, rs1, imm6);
2456 }
2457 
2458 // Definitions for using compressed vs non compressed
2459 
NOP()2460 void Assembler::NOP() {
2461   if (FLAG_riscv_c_extension)
2462     c_nop();
2463   else
2464     nop();
2465 }
2466 
EBREAK()2467 void Assembler::EBREAK() {
2468   if (FLAG_riscv_c_extension)
2469     c_ebreak();
2470   else
2471     ebreak();
2472 }
2473 
2474 // RVV
2475 
vredmaxu_vs(VRegister vd,VRegister vs2,VRegister vs1,MaskType mask)2476 void Assembler::vredmaxu_vs(VRegister vd, VRegister vs2, VRegister vs1,
2477                             MaskType mask) {
2478   GenInstrV(VREDMAXU_FUNCT6, OP_MVV, vd, vs1, vs2, mask);
2479 }
2480 
vredmax_vs(VRegister vd,VRegister vs2,VRegister vs1,MaskType mask)2481 void Assembler::vredmax_vs(VRegister vd, VRegister vs2, VRegister vs1,
2482                            MaskType mask) {
2483   GenInstrV(VREDMAX_FUNCT6, OP_MVV, vd, vs1, vs2, mask);
2484 }
2485 
vredmin_vs(VRegister vd,VRegister vs2,VRegister vs1,MaskType mask)2486 void Assembler::vredmin_vs(VRegister vd, VRegister vs2, VRegister vs1,
2487                            MaskType mask) {
2488   GenInstrV(VREDMIN_FUNCT6, OP_MVV, vd, vs1, vs2, mask);
2489 }
2490 
vredminu_vs(VRegister vd,VRegister vs2,VRegister vs1,MaskType mask)2491 void Assembler::vredminu_vs(VRegister vd, VRegister vs2, VRegister vs1,
2492                             MaskType mask) {
2493   GenInstrV(VREDMINU_FUNCT6, OP_MVV, vd, vs1, vs2, mask);
2494 }
2495 
vmv_vv(VRegister vd,VRegister vs1)2496 void Assembler::vmv_vv(VRegister vd, VRegister vs1) {
2497   GenInstrV(VMV_FUNCT6, OP_IVV, vd, vs1, v0, NoMask);
2498 }
2499 
vmv_vx(VRegister vd,Register rs1)2500 void Assembler::vmv_vx(VRegister vd, Register rs1) {
2501   GenInstrV(VMV_FUNCT6, OP_IVX, vd, rs1, v0, NoMask);
2502 }
2503 
vmv_vi(VRegister vd,uint8_t simm5)2504 void Assembler::vmv_vi(VRegister vd, uint8_t simm5) {
2505   GenInstrV(VMV_FUNCT6, vd, simm5, v0, NoMask);
2506 }
2507 
vmv_xs(Register rd,VRegister vs2)2508 void Assembler::vmv_xs(Register rd, VRegister vs2) {
2509   GenInstrV(VWXUNARY0_FUNCT6, OP_MVV, rd, 0b00000, vs2, NoMask);
2510 }
2511 
vmv_sx(VRegister vd,Register rs1)2512 void Assembler::vmv_sx(VRegister vd, Register rs1) {
2513   GenInstrV(VRXUNARY0_FUNCT6, OP_MVX, vd, rs1, v0, NoMask);
2514 }
2515 
vmerge_vv(VRegister vd,VRegister vs1,VRegister vs2)2516 void Assembler::vmerge_vv(VRegister vd, VRegister vs1, VRegister vs2) {
2517   GenInstrV(VMV_FUNCT6, OP_IVV, vd, vs1, vs2, Mask);
2518 }
2519 
vmerge_vx(VRegister vd,Register rs1,VRegister vs2)2520 void Assembler::vmerge_vx(VRegister vd, Register rs1, VRegister vs2) {
2521   GenInstrV(VMV_FUNCT6, OP_IVX, vd, rs1, vs2, Mask);
2522 }
2523 
vmerge_vi(VRegister vd,uint8_t imm5,VRegister vs2)2524 void Assembler::vmerge_vi(VRegister vd, uint8_t imm5, VRegister vs2) {
2525   GenInstrV(VMV_FUNCT6, vd, imm5, vs2, Mask);
2526 }
2527 
vadc_vv(VRegister vd,VRegister vs1,VRegister vs2)2528 void Assembler::vadc_vv(VRegister vd, VRegister vs1, VRegister vs2) {
2529   GenInstrV(VADC_FUNCT6, OP_IVV, vd, vs1, vs2, Mask);
2530 }
2531 
vadc_vx(VRegister vd,Register rs1,VRegister vs2)2532 void Assembler::vadc_vx(VRegister vd, Register rs1, VRegister vs2) {
2533   GenInstrV(VADC_FUNCT6, OP_IVX, vd, rs1, vs2, Mask);
2534 }
2535 
vadc_vi(VRegister vd,uint8_t imm5,VRegister vs2)2536 void Assembler::vadc_vi(VRegister vd, uint8_t imm5, VRegister vs2) {
2537   GenInstrV(VADC_FUNCT6, vd, imm5, vs2, Mask);
2538 }
2539 
vmadc_vv(VRegister vd,VRegister vs1,VRegister vs2)2540 void Assembler::vmadc_vv(VRegister vd, VRegister vs1, VRegister vs2) {
2541   GenInstrV(VMADC_FUNCT6, OP_IVV, vd, vs1, vs2, Mask);
2542 }
2543 
vmadc_vx(VRegister vd,Register rs1,VRegister vs2)2544 void Assembler::vmadc_vx(VRegister vd, Register rs1, VRegister vs2) {
2545   GenInstrV(VMADC_FUNCT6, OP_IVX, vd, rs1, vs2, Mask);
2546 }
2547 
vmadc_vi(VRegister vd,uint8_t imm5,VRegister vs2)2548 void Assembler::vmadc_vi(VRegister vd, uint8_t imm5, VRegister vs2) {
2549   GenInstrV(VMADC_FUNCT6, vd, imm5, vs2, Mask);
2550 }
2551 
vrgather_vv(VRegister vd,VRegister vs2,VRegister vs1,MaskType mask)2552 void Assembler::vrgather_vv(VRegister vd, VRegister vs2, VRegister vs1,
2553                             MaskType mask) {
2554   DCHECK_NE(vd, vs1);
2555   DCHECK_NE(vd, vs2);
2556   GenInstrV(VRGATHER_FUNCT6, OP_IVV, vd, vs1, vs2, mask);
2557 }
2558 
vrgather_vi(VRegister vd,VRegister vs2,int8_t imm5,MaskType mask)2559 void Assembler::vrgather_vi(VRegister vd, VRegister vs2, int8_t imm5,
2560                             MaskType mask) {
2561   DCHECK_NE(vd, vs2);
2562   GenInstrV(VRGATHER_FUNCT6, vd, imm5, vs2, mask);
2563 }
2564 
vrgather_vx(VRegister vd,VRegister vs2,Register rs1,MaskType mask)2565 void Assembler::vrgather_vx(VRegister vd, VRegister vs2, Register rs1,
2566                             MaskType mask) {
2567   DCHECK_NE(vd, vs2);
2568   GenInstrV(VRGATHER_FUNCT6, OP_IVX, vd, rs1, vs2, mask);
2569 }
2570 
vwaddu_wx(VRegister vd,VRegister vs2,Register rs1,MaskType mask)2571 void Assembler::vwaddu_wx(VRegister vd, VRegister vs2, Register rs1,
2572                           MaskType mask) {
2573   GenInstrV(VWADDUW_FUNCT6, OP_MVX, vd, rs1, vs2, mask);
2574 }
2575 
vid_v(VRegister vd,MaskType mask)2576 void Assembler::vid_v(VRegister vd, MaskType mask) {
2577   GenInstrV(VMUNARY0_FUNCT6, OP_MVV, vd, VID_V, v0, mask);
2578 }
2579 
2580 #define DEFINE_OPIVV(name, funct6)                                      \
2581   void Assembler::name##_vv(VRegister vd, VRegister vs2, VRegister vs1, \
2582                             MaskType mask) {                            \
2583     GenInstrV(funct6, OP_IVV, vd, vs1, vs2, mask);                      \
2584   }
2585 
2586 #define DEFINE_OPFVV(name, funct6)                                      \
2587   void Assembler::name##_vv(VRegister vd, VRegister vs2, VRegister vs1, \
2588                             MaskType mask) {                            \
2589     GenInstrV(funct6, OP_FVV, vd, vs1, vs2, mask);                      \
2590   }
2591 
2592 #define DEFINE_OPFWV(name, funct6)                                      \
2593   void Assembler::name##_wv(VRegister vd, VRegister vs2, VRegister vs1, \
2594                             MaskType mask) {                            \
2595     GenInstrV(funct6, OP_FVV, vd, vs1, vs2, mask);                      \
2596   }
2597 
2598 #define DEFINE_OPFRED(name, funct6)                                     \
2599   void Assembler::name##_vs(VRegister vd, VRegister vs2, VRegister vs1, \
2600                             MaskType mask) {                            \
2601     GenInstrV(funct6, OP_FVV, vd, vs1, vs2, mask);                      \
2602   }
2603 
2604 #define DEFINE_OPIVX(name, funct6)                                     \
2605   void Assembler::name##_vx(VRegister vd, VRegister vs2, Register rs1, \
2606                             MaskType mask) {                           \
2607     GenInstrV(funct6, OP_IVX, vd, rs1, vs2, mask);                     \
2608   }
2609 
2610 #define DEFINE_OPIVI(name, funct6)                                    \
2611   void Assembler::name##_vi(VRegister vd, VRegister vs2, int8_t imm5, \
2612                             MaskType mask) {                          \
2613     GenInstrV(funct6, vd, imm5, vs2, mask);                           \
2614   }
2615 
2616 #define DEFINE_OPMVV(name, funct6)                                      \
2617   void Assembler::name##_vv(VRegister vd, VRegister vs2, VRegister vs1, \
2618                             MaskType mask) {                            \
2619     GenInstrV(funct6, OP_MVV, vd, vs1, vs2, mask);                      \
2620   }
2621 
2622 // void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, Register rs1,
2623 //                  VRegister vs2, MaskType mask = NoMask);
2624 #define DEFINE_OPMVX(name, funct6)                                     \
2625   void Assembler::name##_vx(VRegister vd, VRegister vs2, Register rs1, \
2626                             MaskType mask) {                           \
2627     GenInstrV(funct6, OP_MVX, vd, rs1, vs2, mask);                     \
2628   }
2629 
2630 #define DEFINE_OPFVF(name, funct6)                                        \
2631   void Assembler::name##_vf(VRegister vd, VRegister vs2, FPURegister fs1, \
2632                             MaskType mask) {                              \
2633     GenInstrV(funct6, OP_FVF, vd, fs1, vs2, mask);                        \
2634   }
2635 
2636 #define DEFINE_OPFWF(name, funct6)                                        \
2637   void Assembler::name##_wf(VRegister vd, VRegister vs2, FPURegister fs1, \
2638                             MaskType mask) {                              \
2639     GenInstrV(funct6, OP_FVF, vd, fs1, vs2, mask);                        \
2640   }
2641 
2642 #define DEFINE_OPFVV_FMA(name, funct6)                                  \
2643   void Assembler::name##_vv(VRegister vd, VRegister vs1, VRegister vs2, \
2644                             MaskType mask) {                            \
2645     GenInstrV(funct6, OP_FVV, vd, vs1, vs2, mask);                      \
2646   }
2647 
2648 #define DEFINE_OPFVF_FMA(name, funct6)                                    \
2649   void Assembler::name##_vf(VRegister vd, FPURegister fs1, VRegister vs2, \
2650                             MaskType mask) {                              \
2651     GenInstrV(funct6, OP_FVF, vd, fs1, vs2, mask);                        \
2652   }
2653 
2654 // vector integer extension
2655 #define DEFINE_OPMVV_VIE(name, vs1)                                  \
2656   void Assembler::name(VRegister vd, VRegister vs2, MaskType mask) { \
2657     GenInstrV(VXUNARY0_FUNCT6, OP_MVV, vd, vs1, vs2, mask);          \
2658   }
2659 
vfmv_vf(VRegister vd,FPURegister fs1,MaskType mask)2660 void Assembler::vfmv_vf(VRegister vd, FPURegister fs1, MaskType mask) {
2661   GenInstrV(VMV_FUNCT6, OP_FVF, vd, fs1, v0, mask);
2662 }
2663 
vfmv_fs(FPURegister fd,VRegister vs2)2664 void Assembler::vfmv_fs(FPURegister fd, VRegister vs2) {
2665   GenInstrV(VWFUNARY0_FUNCT6, OP_FVV, fd, v0, vs2, NoMask);
2666 }
2667 
vfmv_sf(VRegister vd,FPURegister fs)2668 void Assembler::vfmv_sf(VRegister vd, FPURegister fs) {
2669   GenInstrV(VRFUNARY0_FUNCT6, OP_FVF, vd, fs, v0, NoMask);
2670 }
2671 
DEFINE_OPIVV(vadd,VADD_FUNCT6)2672 DEFINE_OPIVV(vadd, VADD_FUNCT6)
2673 DEFINE_OPIVX(vadd, VADD_FUNCT6)
2674 DEFINE_OPIVI(vadd, VADD_FUNCT6)
2675 DEFINE_OPIVV(vsub, VSUB_FUNCT6)
2676 DEFINE_OPIVX(vsub, VSUB_FUNCT6)
2677 DEFINE_OPMVX(vdiv, VDIV_FUNCT6)
2678 DEFINE_OPMVX(vdivu, VDIVU_FUNCT6)
2679 DEFINE_OPMVX(vmul, VMUL_FUNCT6)
2680 DEFINE_OPMVX(vmulhu, VMULHU_FUNCT6)
2681 DEFINE_OPMVX(vmulhsu, VMULHSU_FUNCT6)
2682 DEFINE_OPMVX(vmulh, VMULH_FUNCT6)
2683 DEFINE_OPMVV(vdiv, VDIV_FUNCT6)
2684 DEFINE_OPMVV(vdivu, VDIVU_FUNCT6)
2685 DEFINE_OPMVV(vmul, VMUL_FUNCT6)
2686 DEFINE_OPMVV(vmulhu, VMULHU_FUNCT6)
2687 DEFINE_OPMVV(vmulhsu, VMULHSU_FUNCT6)
2688 DEFINE_OPMVV(vwmul, VWMUL_FUNCT6)
2689 DEFINE_OPMVV(vwmulu, VWMULU_FUNCT6)
2690 DEFINE_OPMVV(vmulh, VMULH_FUNCT6)
2691 DEFINE_OPMVV(vwadd, VWADD_FUNCT6)
2692 DEFINE_OPMVV(vwaddu, VWADDU_FUNCT6)
2693 DEFINE_OPMVV(vcompress, VCOMPRESS_FUNCT6)
2694 DEFINE_OPIVX(vsadd, VSADD_FUNCT6)
2695 DEFINE_OPIVV(vsadd, VSADD_FUNCT6)
2696 DEFINE_OPIVI(vsadd, VSADD_FUNCT6)
2697 DEFINE_OPIVX(vsaddu, VSADDU_FUNCT6)
2698 DEFINE_OPIVV(vsaddu, VSADDU_FUNCT6)
2699 DEFINE_OPIVI(vsaddu, VSADDU_FUNCT6)
2700 DEFINE_OPIVX(vssub, VSSUB_FUNCT6)
2701 DEFINE_OPIVV(vssub, VSSUB_FUNCT6)
2702 DEFINE_OPIVX(vssubu, VSSUBU_FUNCT6)
2703 DEFINE_OPIVV(vssubu, VSSUBU_FUNCT6)
2704 DEFINE_OPIVX(vrsub, VRSUB_FUNCT6)
2705 DEFINE_OPIVI(vrsub, VRSUB_FUNCT6)
2706 DEFINE_OPIVV(vminu, VMINU_FUNCT6)
2707 DEFINE_OPIVX(vminu, VMINU_FUNCT6)
2708 DEFINE_OPIVV(vmin, VMIN_FUNCT6)
2709 DEFINE_OPIVX(vmin, VMIN_FUNCT6)
2710 DEFINE_OPIVV(vmaxu, VMAXU_FUNCT6)
2711 DEFINE_OPIVX(vmaxu, VMAXU_FUNCT6)
2712 DEFINE_OPIVV(vmax, VMAX_FUNCT6)
2713 DEFINE_OPIVX(vmax, VMAX_FUNCT6)
2714 DEFINE_OPIVV(vand, VAND_FUNCT6)
2715 DEFINE_OPIVX(vand, VAND_FUNCT6)
2716 DEFINE_OPIVI(vand, VAND_FUNCT6)
2717 DEFINE_OPIVV(vor, VOR_FUNCT6)
2718 DEFINE_OPIVX(vor, VOR_FUNCT6)
2719 DEFINE_OPIVI(vor, VOR_FUNCT6)
2720 DEFINE_OPIVV(vxor, VXOR_FUNCT6)
2721 DEFINE_OPIVX(vxor, VXOR_FUNCT6)
2722 DEFINE_OPIVI(vxor, VXOR_FUNCT6)
2723 
2724 DEFINE_OPIVX(vslidedown, VSLIDEDOWN_FUNCT6)
2725 DEFINE_OPIVI(vslidedown, VSLIDEDOWN_FUNCT6)
2726 DEFINE_OPIVX(vslideup, VSLIDEUP_FUNCT6)
2727 DEFINE_OPIVI(vslideup, VSLIDEUP_FUNCT6)
2728 
2729 DEFINE_OPIVV(vmseq, VMSEQ_FUNCT6)
2730 DEFINE_OPIVX(vmseq, VMSEQ_FUNCT6)
2731 DEFINE_OPIVI(vmseq, VMSEQ_FUNCT6)
2732 
2733 DEFINE_OPIVV(vmsne, VMSNE_FUNCT6)
2734 DEFINE_OPIVX(vmsne, VMSNE_FUNCT6)
2735 DEFINE_OPIVI(vmsne, VMSNE_FUNCT6)
2736 
2737 DEFINE_OPIVV(vmsltu, VMSLTU_FUNCT6)
2738 DEFINE_OPIVX(vmsltu, VMSLTU_FUNCT6)
2739 
2740 DEFINE_OPIVV(vmslt, VMSLT_FUNCT6)
2741 DEFINE_OPIVX(vmslt, VMSLT_FUNCT6)
2742 
2743 DEFINE_OPIVV(vmsle, VMSLE_FUNCT6)
2744 DEFINE_OPIVX(vmsle, VMSLE_FUNCT6)
2745 DEFINE_OPIVI(vmsle, VMSLE_FUNCT6)
2746 
2747 DEFINE_OPIVV(vmsleu, VMSLEU_FUNCT6)
2748 DEFINE_OPIVX(vmsleu, VMSLEU_FUNCT6)
2749 DEFINE_OPIVI(vmsleu, VMSLEU_FUNCT6)
2750 
2751 DEFINE_OPIVI(vmsgt, VMSGT_FUNCT6)
2752 DEFINE_OPIVX(vmsgt, VMSGT_FUNCT6)
2753 
2754 DEFINE_OPIVI(vmsgtu, VMSGTU_FUNCT6)
2755 DEFINE_OPIVX(vmsgtu, VMSGTU_FUNCT6)
2756 
2757 DEFINE_OPIVV(vsrl, VSRL_FUNCT6)
2758 DEFINE_OPIVX(vsrl, VSRL_FUNCT6)
2759 DEFINE_OPIVI(vsrl, VSRL_FUNCT6)
2760 
2761 DEFINE_OPIVV(vsra, VSRA_FUNCT6)
2762 DEFINE_OPIVX(vsra, VSRA_FUNCT6)
2763 DEFINE_OPIVI(vsra, VSRA_FUNCT6)
2764 
2765 DEFINE_OPIVV(vsll, VSLL_FUNCT6)
2766 DEFINE_OPIVX(vsll, VSLL_FUNCT6)
2767 DEFINE_OPIVI(vsll, VSLL_FUNCT6)
2768 
2769 DEFINE_OPIVV(vsmul, VSMUL_FUNCT6)
2770 DEFINE_OPIVX(vsmul, VSMUL_FUNCT6)
2771 
2772 DEFINE_OPFVV(vfadd, VFADD_FUNCT6)
2773 DEFINE_OPFVF(vfadd, VFADD_FUNCT6)
2774 DEFINE_OPFVV(vfsub, VFSUB_FUNCT6)
2775 DEFINE_OPFVF(vfsub, VFSUB_FUNCT6)
2776 DEFINE_OPFVV(vfdiv, VFDIV_FUNCT6)
2777 DEFINE_OPFVF(vfdiv, VFDIV_FUNCT6)
2778 DEFINE_OPFVV(vfmul, VFMUL_FUNCT6)
2779 DEFINE_OPFVF(vfmul, VFMUL_FUNCT6)
2780 DEFINE_OPFVV(vmfeq, VMFEQ_FUNCT6)
2781 DEFINE_OPFVV(vmfne, VMFNE_FUNCT6)
2782 DEFINE_OPFVV(vmflt, VMFLT_FUNCT6)
2783 DEFINE_OPFVV(vmfle, VMFLE_FUNCT6)
2784 DEFINE_OPFVV(vfmax, VFMAX_FUNCT6)
2785 DEFINE_OPFVV(vfmin, VFMIN_FUNCT6)
2786 
2787 // Vector Widening Floating-Point Add/Subtract Instructions
2788 DEFINE_OPFVV(vfwadd, VFWADD_FUNCT6)
2789 DEFINE_OPFVF(vfwadd, VFWADD_FUNCT6)
2790 DEFINE_OPFVV(vfwsub, VFWSUB_FUNCT6)
2791 DEFINE_OPFVF(vfwsub, VFWSUB_FUNCT6)
2792 DEFINE_OPFWV(vfwadd, VFWADD_W_FUNCT6)
2793 DEFINE_OPFWF(vfwadd, VFWADD_W_FUNCT6)
2794 DEFINE_OPFWV(vfwsub, VFWSUB_W_FUNCT6)
2795 DEFINE_OPFWF(vfwsub, VFWSUB_W_FUNCT6)
2796 
2797 // Vector Widening Floating-Point Reduction Instructions
2798 DEFINE_OPFVV(vfwredusum, VFWREDUSUM_FUNCT6)
2799 DEFINE_OPFVV(vfwredosum, VFWREDOSUM_FUNCT6)
2800 
2801 // Vector Widening Floating-Point Multiply
2802 DEFINE_OPFVV(vfwmul, VFWMUL_FUNCT6)
2803 DEFINE_OPFVF(vfwmul, VFWMUL_FUNCT6)
2804 
2805 DEFINE_OPFRED(vfredmax, VFREDMAX_FUNCT6)
2806 
2807 DEFINE_OPFVV(vfsngj, VFSGNJ_FUNCT6)
2808 DEFINE_OPFVF(vfsngj, VFSGNJ_FUNCT6)
2809 DEFINE_OPFVV(vfsngjn, VFSGNJN_FUNCT6)
2810 DEFINE_OPFVF(vfsngjn, VFSGNJN_FUNCT6)
2811 DEFINE_OPFVV(vfsngjx, VFSGNJX_FUNCT6)
2812 DEFINE_OPFVF(vfsngjx, VFSGNJX_FUNCT6)
2813 
2814 // Vector Single-Width Floating-Point Fused Multiply-Add Instructions
2815 DEFINE_OPFVV_FMA(vfmadd, VFMADD_FUNCT6)
2816 DEFINE_OPFVF_FMA(vfmadd, VFMADD_FUNCT6)
2817 DEFINE_OPFVV_FMA(vfmsub, VFMSUB_FUNCT6)
2818 DEFINE_OPFVF_FMA(vfmsub, VFMSUB_FUNCT6)
2819 DEFINE_OPFVV_FMA(vfmacc, VFMACC_FUNCT6)
2820 DEFINE_OPFVF_FMA(vfmacc, VFMACC_FUNCT6)
2821 DEFINE_OPFVV_FMA(vfmsac, VFMSAC_FUNCT6)
2822 DEFINE_OPFVF_FMA(vfmsac, VFMSAC_FUNCT6)
2823 DEFINE_OPFVV_FMA(vfnmadd, VFNMADD_FUNCT6)
2824 DEFINE_OPFVF_FMA(vfnmadd, VFNMADD_FUNCT6)
2825 DEFINE_OPFVV_FMA(vfnmsub, VFNMSUB_FUNCT6)
2826 DEFINE_OPFVF_FMA(vfnmsub, VFNMSUB_FUNCT6)
2827 DEFINE_OPFVV_FMA(vfnmacc, VFNMACC_FUNCT6)
2828 DEFINE_OPFVF_FMA(vfnmacc, VFNMACC_FUNCT6)
2829 DEFINE_OPFVV_FMA(vfnmsac, VFNMSAC_FUNCT6)
2830 DEFINE_OPFVF_FMA(vfnmsac, VFNMSAC_FUNCT6)
2831 
2832 // Vector Widening Floating-Point Fused Multiply-Add Instructions
2833 DEFINE_OPFVV_FMA(vfwmacc, VFWMACC_FUNCT6)
2834 DEFINE_OPFVF_FMA(vfwmacc, VFWMACC_FUNCT6)
2835 DEFINE_OPFVV_FMA(vfwnmacc, VFWNMACC_FUNCT6)
2836 DEFINE_OPFVF_FMA(vfwnmacc, VFWNMACC_FUNCT6)
2837 DEFINE_OPFVV_FMA(vfwmsac, VFWMSAC_FUNCT6)
2838 DEFINE_OPFVF_FMA(vfwmsac, VFWMSAC_FUNCT6)
2839 DEFINE_OPFVV_FMA(vfwnmsac, VFWNMSAC_FUNCT6)
2840 DEFINE_OPFVF_FMA(vfwnmsac, VFWNMSAC_FUNCT6)
2841 
2842 // Vector Narrowing Fixed-Point Clip Instructions
2843 DEFINE_OPIVV(vnclip, VNCLIP_FUNCT6)
2844 DEFINE_OPIVX(vnclip, VNCLIP_FUNCT6)
2845 DEFINE_OPIVI(vnclip, VNCLIP_FUNCT6)
2846 DEFINE_OPIVV(vnclipu, VNCLIPU_FUNCT6)
2847 DEFINE_OPIVX(vnclipu, VNCLIPU_FUNCT6)
2848 DEFINE_OPIVI(vnclipu, VNCLIPU_FUNCT6)
2849 
2850 // Vector Integer Extension
2851 DEFINE_OPMVV_VIE(vzext_vf8, 0b00010)
2852 DEFINE_OPMVV_VIE(vsext_vf8, 0b00011)
2853 DEFINE_OPMVV_VIE(vzext_vf4, 0b00100)
2854 DEFINE_OPMVV_VIE(vsext_vf4, 0b00101)
2855 DEFINE_OPMVV_VIE(vzext_vf2, 0b00110)
2856 DEFINE_OPMVV_VIE(vsext_vf2, 0b00111)
2857 
2858 #undef DEFINE_OPIVI
2859 #undef DEFINE_OPIVV
2860 #undef DEFINE_OPIVX
2861 #undef DEFINE_OPFVV
2862 #undef DEFINE_OPFWV
2863 #undef DEFINE_OPFVF
2864 #undef DEFINE_OPFWF
2865 #undef DEFINE_OPFVV_FMA
2866 #undef DEFINE_OPFVF_FMA
2867 #undef DEFINE_OPMVV_VIE
2868 
2869 void Assembler::vsetvli(Register rd, Register rs1, VSew vsew, Vlmul vlmul,
2870                         TailAgnosticType tail, MaskAgnosticType mask) {
2871   int32_t zimm = GenZimm(vsew, vlmul, tail, mask);
2872   Instr instr = OP_V | ((rd.code() & 0x1F) << kRvvRdShift) | (0x7 << 12) |
2873                 ((rs1.code() & 0x1F) << kRvvRs1Shift) |
2874                 (((uint32_t)zimm << kRvvZimmShift) & kRvvZimmMask) | 0x0 << 31;
2875   emit(instr);
2876 }
2877 
vsetivli(Register rd,uint8_t uimm,VSew vsew,Vlmul vlmul,TailAgnosticType tail,MaskAgnosticType mask)2878 void Assembler::vsetivli(Register rd, uint8_t uimm, VSew vsew, Vlmul vlmul,
2879                          TailAgnosticType tail, MaskAgnosticType mask) {
2880   DCHECK(is_uint5(uimm));
2881   int32_t zimm = GenZimm(vsew, vlmul, tail, mask) & 0x3FF;
2882   Instr instr = OP_V | ((rd.code() & 0x1F) << kRvvRdShift) | (0x7 << 12) |
2883                 ((uimm & 0x1F) << kRvvUimmShift) |
2884                 (((uint32_t)zimm << kRvvZimmShift) & kRvvZimmMask) | 0x3 << 30;
2885   emit(instr);
2886 }
2887 
vsetvl(Register rd,Register rs1,Register rs2)2888 void Assembler::vsetvl(Register rd, Register rs1, Register rs2) {
2889   Instr instr = OP_V | ((rd.code() & 0x1F) << kRvvRdShift) | (0x7 << 12) |
2890                 ((rs1.code() & 0x1F) << kRvvRs1Shift) |
2891                 ((rs2.code() & 0x1F) << kRvvRs2Shift) | 0x40 << 25;
2892   emit(instr);
2893 }
2894 
vsew_switch(VSew vsew)2895 uint8_t vsew_switch(VSew vsew) {
2896   uint8_t width;
2897   switch (vsew) {
2898     case E8:
2899       width = 0b000;
2900       break;
2901     case E16:
2902       width = 0b101;
2903       break;
2904     case E32:
2905       width = 0b110;
2906       break;
2907     default:
2908       width = 0b111;
2909       break;
2910   }
2911   return width;
2912 }
2913 
vl(VRegister vd,Register rs1,uint8_t lumop,VSew vsew,MaskType mask)2914 void Assembler::vl(VRegister vd, Register rs1, uint8_t lumop, VSew vsew,
2915                    MaskType mask) {
2916   uint8_t width = vsew_switch(vsew);
2917   GenInstrV(LOAD_FP, width, vd, rs1, lumop, mask, 0b00, 0, 0b000);
2918 }
vls(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)2919 void Assembler::vls(VRegister vd, Register rs1, Register rs2, VSew vsew,
2920                     MaskType mask) {
2921   uint8_t width = vsew_switch(vsew);
2922   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b000);
2923 }
vlx(VRegister vd,Register rs1,VRegister vs2,VSew vsew,MaskType mask)2924 void Assembler::vlx(VRegister vd, Register rs1, VRegister vs2, VSew vsew,
2925                     MaskType mask) {
2926   uint8_t width = vsew_switch(vsew);
2927   GenInstrV(LOAD_FP, width, vd, rs1, vs2, mask, 0b11, 0, 0);
2928 }
2929 
vs(VRegister vd,Register rs1,uint8_t sumop,VSew vsew,MaskType mask)2930 void Assembler::vs(VRegister vd, Register rs1, uint8_t sumop, VSew vsew,
2931                    MaskType mask) {
2932   uint8_t width = vsew_switch(vsew);
2933   GenInstrV(STORE_FP, width, vd, rs1, sumop, mask, 0b00, 0, 0b000);
2934 }
vss(VRegister vs3,Register rs1,Register rs2,VSew vsew,MaskType mask)2935 void Assembler::vss(VRegister vs3, Register rs1, Register rs2, VSew vsew,
2936                     MaskType mask) {
2937   uint8_t width = vsew_switch(vsew);
2938   GenInstrV(STORE_FP, width, vs3, rs1, rs2, mask, 0b10, 0, 0b000);
2939 }
2940 
vsx(VRegister vd,Register rs1,VRegister vs2,VSew vsew,MaskType mask)2941 void Assembler::vsx(VRegister vd, Register rs1, VRegister vs2, VSew vsew,
2942                     MaskType mask) {
2943   uint8_t width = vsew_switch(vsew);
2944   GenInstrV(STORE_FP, width, vd, rs1, vs2, mask, 0b11, 0, 0b000);
2945 }
vsu(VRegister vd,Register rs1,VRegister vs2,VSew vsew,MaskType mask)2946 void Assembler::vsu(VRegister vd, Register rs1, VRegister vs2, VSew vsew,
2947                     MaskType mask) {
2948   uint8_t width = vsew_switch(vsew);
2949   GenInstrV(STORE_FP, width, vd, rs1, vs2, mask, 0b01, 0, 0b000);
2950 }
2951 
vlseg2(VRegister vd,Register rs1,uint8_t lumop,VSew vsew,MaskType mask)2952 void Assembler::vlseg2(VRegister vd, Register rs1, uint8_t lumop, VSew vsew,
2953                        MaskType mask) {
2954   uint8_t width = vsew_switch(vsew);
2955   GenInstrV(LOAD_FP, width, vd, rs1, lumop, mask, 0b00, 0, 0b001);
2956 }
2957 
vlseg3(VRegister vd,Register rs1,uint8_t lumop,VSew vsew,MaskType mask)2958 void Assembler::vlseg3(VRegister vd, Register rs1, uint8_t lumop, VSew vsew,
2959                        MaskType mask) {
2960   uint8_t width = vsew_switch(vsew);
2961   GenInstrV(LOAD_FP, width, vd, rs1, lumop, mask, 0b00, 0, 0b010);
2962 }
2963 
vlseg4(VRegister vd,Register rs1,uint8_t lumop,VSew vsew,MaskType mask)2964 void Assembler::vlseg4(VRegister vd, Register rs1, uint8_t lumop, VSew vsew,
2965                        MaskType mask) {
2966   uint8_t width = vsew_switch(vsew);
2967   GenInstrV(LOAD_FP, width, vd, rs1, lumop, mask, 0b00, 0, 0b011);
2968 }
2969 
vlseg5(VRegister vd,Register rs1,uint8_t lumop,VSew vsew,MaskType mask)2970 void Assembler::vlseg5(VRegister vd, Register rs1, uint8_t lumop, VSew vsew,
2971                        MaskType mask) {
2972   uint8_t width = vsew_switch(vsew);
2973   GenInstrV(LOAD_FP, width, vd, rs1, lumop, mask, 0b00, 0, 0b100);
2974 }
2975 
vlseg6(VRegister vd,Register rs1,uint8_t lumop,VSew vsew,MaskType mask)2976 void Assembler::vlseg6(VRegister vd, Register rs1, uint8_t lumop, VSew vsew,
2977                        MaskType mask) {
2978   uint8_t width = vsew_switch(vsew);
2979   GenInstrV(LOAD_FP, width, vd, rs1, lumop, mask, 0b00, 0, 0b101);
2980 }
2981 
vlseg7(VRegister vd,Register rs1,uint8_t lumop,VSew vsew,MaskType mask)2982 void Assembler::vlseg7(VRegister vd, Register rs1, uint8_t lumop, VSew vsew,
2983                        MaskType mask) {
2984   uint8_t width = vsew_switch(vsew);
2985   GenInstrV(LOAD_FP, width, vd, rs1, lumop, mask, 0b00, 0, 0b110);
2986 }
2987 
vlseg8(VRegister vd,Register rs1,uint8_t lumop,VSew vsew,MaskType mask)2988 void Assembler::vlseg8(VRegister vd, Register rs1, uint8_t lumop, VSew vsew,
2989                        MaskType mask) {
2990   uint8_t width = vsew_switch(vsew);
2991   GenInstrV(LOAD_FP, width, vd, rs1, lumop, mask, 0b00, 0, 0b111);
2992 }
vsseg2(VRegister vd,Register rs1,uint8_t sumop,VSew vsew,MaskType mask)2993 void Assembler::vsseg2(VRegister vd, Register rs1, uint8_t sumop, VSew vsew,
2994                        MaskType mask) {
2995   uint8_t width = vsew_switch(vsew);
2996   GenInstrV(STORE_FP, width, vd, rs1, sumop, mask, 0b00, 0, 0b001);
2997 }
vsseg3(VRegister vd,Register rs1,uint8_t sumop,VSew vsew,MaskType mask)2998 void Assembler::vsseg3(VRegister vd, Register rs1, uint8_t sumop, VSew vsew,
2999                        MaskType mask) {
3000   uint8_t width = vsew_switch(vsew);
3001   GenInstrV(STORE_FP, width, vd, rs1, sumop, mask, 0b00, 0, 0b010);
3002 }
vsseg4(VRegister vd,Register rs1,uint8_t sumop,VSew vsew,MaskType mask)3003 void Assembler::vsseg4(VRegister vd, Register rs1, uint8_t sumop, VSew vsew,
3004                        MaskType mask) {
3005   uint8_t width = vsew_switch(vsew);
3006   GenInstrV(STORE_FP, width, vd, rs1, sumop, mask, 0b00, 0, 0b011);
3007 }
vsseg5(VRegister vd,Register rs1,uint8_t sumop,VSew vsew,MaskType mask)3008 void Assembler::vsseg5(VRegister vd, Register rs1, uint8_t sumop, VSew vsew,
3009                        MaskType mask) {
3010   uint8_t width = vsew_switch(vsew);
3011   GenInstrV(STORE_FP, width, vd, rs1, sumop, mask, 0b00, 0, 0b100);
3012 }
vsseg6(VRegister vd,Register rs1,uint8_t sumop,VSew vsew,MaskType mask)3013 void Assembler::vsseg6(VRegister vd, Register rs1, uint8_t sumop, VSew vsew,
3014                        MaskType mask) {
3015   uint8_t width = vsew_switch(vsew);
3016   GenInstrV(STORE_FP, width, vd, rs1, sumop, mask, 0b00, 0, 0b101);
3017 }
vsseg7(VRegister vd,Register rs1,uint8_t sumop,VSew vsew,MaskType mask)3018 void Assembler::vsseg7(VRegister vd, Register rs1, uint8_t sumop, VSew vsew,
3019                        MaskType mask) {
3020   uint8_t width = vsew_switch(vsew);
3021   GenInstrV(STORE_FP, width, vd, rs1, sumop, mask, 0b00, 0, 0b110);
3022 }
vsseg8(VRegister vd,Register rs1,uint8_t sumop,VSew vsew,MaskType mask)3023 void Assembler::vsseg8(VRegister vd, Register rs1, uint8_t sumop, VSew vsew,
3024                        MaskType mask) {
3025   uint8_t width = vsew_switch(vsew);
3026   GenInstrV(STORE_FP, width, vd, rs1, sumop, mask, 0b00, 0, 0b111);
3027 }
3028 
vlsseg2(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3029 void Assembler::vlsseg2(VRegister vd, Register rs1, Register rs2, VSew vsew,
3030                         MaskType mask) {
3031   uint8_t width = vsew_switch(vsew);
3032   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b001);
3033 }
vlsseg3(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3034 void Assembler::vlsseg3(VRegister vd, Register rs1, Register rs2, VSew vsew,
3035                         MaskType mask) {
3036   uint8_t width = vsew_switch(vsew);
3037   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b010);
3038 }
vlsseg4(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3039 void Assembler::vlsseg4(VRegister vd, Register rs1, Register rs2, VSew vsew,
3040                         MaskType mask) {
3041   uint8_t width = vsew_switch(vsew);
3042   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b011);
3043 }
vlsseg5(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3044 void Assembler::vlsseg5(VRegister vd, Register rs1, Register rs2, VSew vsew,
3045                         MaskType mask) {
3046   uint8_t width = vsew_switch(vsew);
3047   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b100);
3048 }
vlsseg6(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3049 void Assembler::vlsseg6(VRegister vd, Register rs1, Register rs2, VSew vsew,
3050                         MaskType mask) {
3051   uint8_t width = vsew_switch(vsew);
3052   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b101);
3053 }
vlsseg7(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3054 void Assembler::vlsseg7(VRegister vd, Register rs1, Register rs2, VSew vsew,
3055                         MaskType mask) {
3056   uint8_t width = vsew_switch(vsew);
3057   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b110);
3058 }
vlsseg8(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3059 void Assembler::vlsseg8(VRegister vd, Register rs1, Register rs2, VSew vsew,
3060                         MaskType mask) {
3061   uint8_t width = vsew_switch(vsew);
3062   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b111);
3063 }
vssseg2(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3064 void Assembler::vssseg2(VRegister vd, Register rs1, Register rs2, VSew vsew,
3065                         MaskType mask) {
3066   uint8_t width = vsew_switch(vsew);
3067   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b001);
3068 }
vssseg3(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3069 void Assembler::vssseg3(VRegister vd, Register rs1, Register rs2, VSew vsew,
3070                         MaskType mask) {
3071   uint8_t width = vsew_switch(vsew);
3072   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b010);
3073 }
vssseg4(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3074 void Assembler::vssseg4(VRegister vd, Register rs1, Register rs2, VSew vsew,
3075                         MaskType mask) {
3076   uint8_t width = vsew_switch(vsew);
3077   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b011);
3078 }
vssseg5(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3079 void Assembler::vssseg5(VRegister vd, Register rs1, Register rs2, VSew vsew,
3080                         MaskType mask) {
3081   uint8_t width = vsew_switch(vsew);
3082   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b100);
3083 }
vssseg6(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3084 void Assembler::vssseg6(VRegister vd, Register rs1, Register rs2, VSew vsew,
3085                         MaskType mask) {
3086   uint8_t width = vsew_switch(vsew);
3087   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b101);
3088 }
vssseg7(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3089 void Assembler::vssseg7(VRegister vd, Register rs1, Register rs2, VSew vsew,
3090                         MaskType mask) {
3091   uint8_t width = vsew_switch(vsew);
3092   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b110);
3093 }
vssseg8(VRegister vd,Register rs1,Register rs2,VSew vsew,MaskType mask)3094 void Assembler::vssseg8(VRegister vd, Register rs1, Register rs2, VSew vsew,
3095                         MaskType mask) {
3096   uint8_t width = vsew_switch(vsew);
3097   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b10, 0, 0b111);
3098 }
3099 
vlxseg2(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3100 void Assembler::vlxseg2(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3101                         MaskType mask) {
3102   uint8_t width = vsew_switch(vsew);
3103   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b001);
3104 }
vlxseg3(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3105 void Assembler::vlxseg3(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3106                         MaskType mask) {
3107   uint8_t width = vsew_switch(vsew);
3108   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b010);
3109 }
vlxseg4(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3110 void Assembler::vlxseg4(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3111                         MaskType mask) {
3112   uint8_t width = vsew_switch(vsew);
3113   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b011);
3114 }
vlxseg5(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3115 void Assembler::vlxseg5(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3116                         MaskType mask) {
3117   uint8_t width = vsew_switch(vsew);
3118   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b100);
3119 }
vlxseg6(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3120 void Assembler::vlxseg6(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3121                         MaskType mask) {
3122   uint8_t width = vsew_switch(vsew);
3123   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b101);
3124 }
vlxseg7(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3125 void Assembler::vlxseg7(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3126                         MaskType mask) {
3127   uint8_t width = vsew_switch(vsew);
3128   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b110);
3129 }
vlxseg8(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3130 void Assembler::vlxseg8(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3131                         MaskType mask) {
3132   uint8_t width = vsew_switch(vsew);
3133   GenInstrV(LOAD_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b111);
3134 }
vsxseg2(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3135 void Assembler::vsxseg2(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3136                         MaskType mask) {
3137   uint8_t width = vsew_switch(vsew);
3138   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b001);
3139 }
vsxseg3(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3140 void Assembler::vsxseg3(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3141                         MaskType mask) {
3142   uint8_t width = vsew_switch(vsew);
3143   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b010);
3144 }
vsxseg4(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3145 void Assembler::vsxseg4(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3146                         MaskType mask) {
3147   uint8_t width = vsew_switch(vsew);
3148   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b011);
3149 }
vsxseg5(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3150 void Assembler::vsxseg5(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3151                         MaskType mask) {
3152   uint8_t width = vsew_switch(vsew);
3153   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b100);
3154 }
vsxseg6(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3155 void Assembler::vsxseg6(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3156                         MaskType mask) {
3157   uint8_t width = vsew_switch(vsew);
3158   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b101);
3159 }
vsxseg7(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3160 void Assembler::vsxseg7(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3161                         MaskType mask) {
3162   uint8_t width = vsew_switch(vsew);
3163   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b110);
3164 }
vsxseg8(VRegister vd,Register rs1,VRegister rs2,VSew vsew,MaskType mask)3165 void Assembler::vsxseg8(VRegister vd, Register rs1, VRegister rs2, VSew vsew,
3166                         MaskType mask) {
3167   uint8_t width = vsew_switch(vsew);
3168   GenInstrV(STORE_FP, width, vd, rs1, rs2, mask, 0b11, 0, 0b111);
3169 }
3170 
vfirst_m(Register rd,VRegister vs2,MaskType mask)3171 void Assembler::vfirst_m(Register rd, VRegister vs2, MaskType mask) {
3172   GenInstrV(VWXUNARY0_FUNCT6, OP_MVV, rd, 0b10001, vs2, mask);
3173 }
3174 
vcpop_m(Register rd,VRegister vs2,MaskType mask)3175 void Assembler::vcpop_m(Register rd, VRegister vs2, MaskType mask) {
3176   GenInstrV(VWXUNARY0_FUNCT6, OP_MVV, rd, 0b10000, vs2, mask);
3177 }
3178 
3179 // Privileged
uret()3180 void Assembler::uret() {
3181   GenInstrPriv(0b0000000, ToRegister(0), ToRegister(0b00010));
3182 }
3183 
sret()3184 void Assembler::sret() {
3185   GenInstrPriv(0b0001000, ToRegister(0), ToRegister(0b00010));
3186 }
3187 
mret()3188 void Assembler::mret() {
3189   GenInstrPriv(0b0011000, ToRegister(0), ToRegister(0b00010));
3190 }
3191 
wfi()3192 void Assembler::wfi() {
3193   GenInstrPriv(0b0001000, ToRegister(0), ToRegister(0b00101));
3194 }
3195 
sfence_vma(Register rs1,Register rs2)3196 void Assembler::sfence_vma(Register rs1, Register rs2) {
3197   GenInstrR(0b0001001, 0b000, SYSTEM, ToRegister(0), rs1, rs2);
3198 }
3199 
3200 // Assembler Pseudo Instructions (Tables 25.2 and 25.3, RISC-V Unprivileged ISA)
3201 
nop()3202 void Assembler::nop() { addi(ToRegister(0), ToRegister(0), 0); }
3203 
RV_li(Register rd,int64_t imm)3204 void Assembler::RV_li(Register rd, int64_t imm) {
3205   // 64-bit imm is put in the register rd.
3206   // In most cases the imm is 32 bit and 2 instructions are generated. If a
3207   // temporary register is available, in the worst case, 6 instructions are
3208   // generated for a full 64-bit immediate. If temporay register is not
3209   // available the maximum will be 8 instructions. If imm is more than 32 bits
3210   // and a temp register is available, imm is divided into two 32-bit parts,
3211   // low_32 and up_32. Each part is built in a separate register. low_32 is
3212   // built before up_32. If low_32 is negative (upper 32 bits are 1), 0xffffffff
3213   // is subtracted from up_32 before up_32 is built. This compensates for 32
3214   // bits of 1's in the lower when the two registers are added. If no temp is
3215   // available, the upper 32 bit is built in rd, and the lower 32 bits are
3216   // devided to 3 parts (11, 11, and 10 bits). The parts are shifted and added
3217   // to the upper part built in rd.
3218   if (is_int32(imm + 0x800)) {
3219     // 32-bit case. Maximum of 2 instructions generated
3220     int64_t high_20 = ((imm + 0x800) >> 12);
3221     int64_t low_12 = imm << 52 >> 52;
3222     if (high_20) {
3223       lui(rd, (int32_t)high_20);
3224       if (low_12) {
3225         addi(rd, rd, low_12);
3226       }
3227     } else {
3228       addi(rd, zero_reg, low_12);
3229     }
3230     return;
3231   } else {
3232     // 64-bit case: divide imm into two 32-bit parts, upper and lower
3233     int64_t up_32 = imm >> 32;
3234     int64_t low_32 = imm & 0xffffffffull;
3235     Register temp_reg = rd;
3236     // Check if a temporary register is available
3237     if (up_32 == 0 || low_32 == 0) {
3238       // No temp register is needed
3239     } else {
3240       UseScratchRegisterScope temps(this);
3241       BlockTrampolinePoolScope block_trampoline_pool(this);
3242       temp_reg = temps.hasAvailable() ? temps.Acquire() : no_reg;
3243     }
3244     if (temp_reg != no_reg) {
3245       // keep track of hardware behavior for lower part in sim_low
3246       int64_t sim_low = 0;
3247       // Build lower part
3248       if (low_32 != 0) {
3249         int64_t high_20 = ((low_32 + 0x800) >> 12);
3250         int64_t low_12 = low_32 & 0xfff;
3251         if (high_20) {
3252           // Adjust to 20 bits for the case of overflow
3253           high_20 &= 0xfffff;
3254           sim_low = ((high_20 << 12) << 32) >> 32;
3255           lui(rd, (int32_t)high_20);
3256           if (low_12) {
3257             sim_low += (low_12 << 52 >> 52) | low_12;
3258             addi(rd, rd, low_12);
3259           }
3260         } else {
3261           sim_low = low_12;
3262           ori(rd, zero_reg, low_12);
3263         }
3264       }
3265       if (sim_low & 0x100000000) {
3266         // Bit 31 is 1. Either an overflow or a negative 64 bit
3267         if (up_32 == 0) {
3268           // Positive number, but overflow because of the add 0x800
3269           slli(rd, rd, 32);
3270           srli(rd, rd, 32);
3271           return;
3272         }
3273         // low_32 is a negative 64 bit after the build
3274         up_32 = (up_32 - 0xffffffff) & 0xffffffff;
3275       }
3276       if (up_32 == 0) {
3277         return;
3278       }
3279       // Build upper part in a temporary register
3280       if (low_32 == 0) {
3281         // Build upper part in rd
3282         temp_reg = rd;
3283       }
3284       int64_t high_20 = (up_32 + 0x800) >> 12;
3285       int64_t low_12 = up_32 & 0xfff;
3286       if (high_20) {
3287         // Adjust to 20 bits for the case of overflow
3288         high_20 &= 0xfffff;
3289         lui(temp_reg, (int32_t)high_20);
3290         if (low_12) {
3291           addi(temp_reg, temp_reg, low_12);
3292         }
3293       } else {
3294         ori(temp_reg, zero_reg, low_12);
3295       }
3296       // Put it at the bgining of register
3297       slli(temp_reg, temp_reg, 32);
3298       if (low_32 != 0) {
3299         add(rd, rd, temp_reg);
3300       }
3301       return;
3302     }
3303     // No temp register. Build imm in rd.
3304     // Build upper 32 bits first in rd. Divide lower 32 bits parts and add
3305     // parts to the upper part by doing shift and add.
3306     // First build upper part in rd.
3307     int64_t high_20 = (up_32 + 0x800) >> 12;
3308     int64_t low_12 = up_32 & 0xfff;
3309     if (high_20) {
3310       // Adjust to 20 bits for the case of overflow
3311       high_20 &= 0xfffff;
3312       lui(rd, (int32_t)high_20);
3313       if (low_12) {
3314         addi(rd, rd, low_12);
3315       }
3316     } else {
3317       ori(rd, zero_reg, low_12);
3318     }
3319     // upper part already in rd. Each part to be added to rd, has maximum of 11
3320     // bits, and always starts with a 1. rd is shifted by the size of the part
3321     // plus the number of zeros between the parts. Each part is added after the
3322     // left shift.
3323     uint32_t mask = 0x80000000;
3324     int32_t shift_val = 0;
3325     int32_t i;
3326     for (i = 0; i < 32; i++) {
3327       if ((low_32 & mask) == 0) {
3328         mask >>= 1;
3329         shift_val++;
3330         if (i == 31) {
3331           // rest is zero
3332           slli(rd, rd, shift_val);
3333         }
3334         continue;
3335       }
3336       // The first 1 seen
3337       int32_t part;
3338       if ((i + 11) < 32) {
3339         // Pick 11 bits
3340         part = ((uint32_t)(low_32 << i) >> i) >> (32 - (i + 11));
3341         slli(rd, rd, shift_val + 11);
3342         ori(rd, rd, part);
3343         i += 10;
3344         mask >>= 11;
3345       } else {
3346         part = (uint32_t)(low_32 << i) >> i;
3347         slli(rd, rd, shift_val + (32 - i));
3348         ori(rd, rd, part);
3349         break;
3350       }
3351       shift_val = 0;
3352     }
3353   }
3354 }
3355 
li_estimate(int64_t imm,bool is_get_temp_reg)3356 int Assembler::li_estimate(int64_t imm, bool is_get_temp_reg) {
3357   int count = 0;
3358   // imitate Assembler::RV_li
3359   if (is_int32(imm + 0x800)) {
3360     // 32-bit case. Maximum of 2 instructions generated
3361     int64_t high_20 = ((imm + 0x800) >> 12);
3362     int64_t low_12 = imm << 52 >> 52;
3363     if (high_20) {
3364       count++;
3365       if (low_12) {
3366         count++;
3367       }
3368     } else {
3369       count++;
3370     }
3371     return count;
3372   } else {
3373     // 64-bit case: divide imm into two 32-bit parts, upper and lower
3374     int64_t up_32 = imm >> 32;
3375     int64_t low_32 = imm & 0xffffffffull;
3376     // Check if a temporary register is available
3377     if (is_get_temp_reg) {
3378       // keep track of hardware behavior for lower part in sim_low
3379       int64_t sim_low = 0;
3380       // Build lower part
3381       if (low_32 != 0) {
3382         int64_t high_20 = ((low_32 + 0x800) >> 12);
3383         int64_t low_12 = low_32 & 0xfff;
3384         if (high_20) {
3385           // Adjust to 20 bits for the case of overflow
3386           high_20 &= 0xfffff;
3387           sim_low = ((high_20 << 12) << 32) >> 32;
3388           count++;
3389           if (low_12) {
3390             sim_low += (low_12 << 52 >> 52) | low_12;
3391             count++;
3392           }
3393         } else {
3394           sim_low = low_12;
3395           count++;
3396         }
3397       }
3398       if (sim_low & 0x100000000) {
3399         // Bit 31 is 1. Either an overflow or a negative 64 bit
3400         if (up_32 == 0) {
3401           // Positive number, but overflow because of the add 0x800
3402           count++;
3403           count++;
3404           return count;
3405         }
3406         // low_32 is a negative 64 bit after the build
3407         up_32 = (up_32 - 0xffffffff) & 0xffffffff;
3408       }
3409       if (up_32 == 0) {
3410         return count;
3411       }
3412       int64_t high_20 = (up_32 + 0x800) >> 12;
3413       int64_t low_12 = up_32 & 0xfff;
3414       if (high_20) {
3415         // Adjust to 20 bits for the case of overflow
3416         high_20 &= 0xfffff;
3417         count++;
3418         if (low_12) {
3419           count++;
3420         }
3421       } else {
3422         count++;
3423       }
3424       // Put it at the bgining of register
3425       count++;
3426       if (low_32 != 0) {
3427         count++;
3428       }
3429       return count;
3430     }
3431     // No temp register. Build imm in rd.
3432     // Build upper 32 bits first in rd. Divide lower 32 bits parts and add
3433     // parts to the upper part by doing shift and add.
3434     // First build upper part in rd.
3435     int64_t high_20 = (up_32 + 0x800) >> 12;
3436     int64_t low_12 = up_32 & 0xfff;
3437     if (high_20) {
3438       // Adjust to 20 bits for the case of overflow
3439       high_20 &= 0xfffff;
3440       count++;
3441       if (low_12) {
3442         count++;
3443       }
3444     } else {
3445       count++;
3446     }
3447     // upper part already in rd. Each part to be added to rd, has maximum of 11
3448     // bits, and always starts with a 1. rd is shifted by the size of the part
3449     // plus the number of zeros between the parts. Each part is added after the
3450     // left shift.
3451     uint32_t mask = 0x80000000;
3452     int32_t i;
3453     for (i = 0; i < 32; i++) {
3454       if ((low_32 & mask) == 0) {
3455         mask >>= 1;
3456         if (i == 31) {
3457           // rest is zero
3458           count++;
3459         }
3460         continue;
3461       }
3462       // The first 1 seen
3463       if ((i + 11) < 32) {
3464         // Pick 11 bits
3465         count++;
3466         count++;
3467         i += 10;
3468         mask >>= 11;
3469       } else {
3470         count++;
3471         count++;
3472         break;
3473       }
3474     }
3475   }
3476   return count;
3477 }
3478 
li_ptr(Register rd,int64_t imm)3479 void Assembler::li_ptr(Register rd, int64_t imm) {
3480   // Initialize rd with an address
3481   // Pointers are 48 bits
3482   // 6 fixed instructions are generated
3483   DCHECK_EQ((imm & 0xfff0000000000000ll), 0);
3484   int64_t a6 = imm & 0x3f;                      // bits 0:5. 6 bits
3485   int64_t b11 = (imm >> 6) & 0x7ff;             // bits 6:11. 11 bits
3486   int64_t high_31 = (imm >> 17) & 0x7fffffff;   // 31 bits
3487   int64_t high_20 = ((high_31 + 0x800) >> 12);  // 19 bits
3488   int64_t low_12 = high_31 & 0xfff;             // 12 bits
3489   lui(rd, (int32_t)high_20);
3490   addi(rd, rd, low_12);  // 31 bits in rd.
3491   slli(rd, rd, 11);      // Space for next 11 bis
3492   ori(rd, rd, b11);      // 11 bits are put in. 42 bit in rd
3493   slli(rd, rd, 6);       // Space for next 6 bits
3494   ori(rd, rd, a6);       // 6 bits are put in. 48 bis in rd
3495 }
3496 
li_constant(Register rd,int64_t imm)3497 void Assembler::li_constant(Register rd, int64_t imm) {
3498   DEBUG_PRINTF("li_constant(%d, %lx <%ld>)\n", ToNumber(rd), imm, imm);
3499   lui(rd, (imm + (1LL << 47) + (1LL << 35) + (1LL << 23) + (1LL << 11)) >>
3500               48);  // Bits 63:48
3501   addiw(rd, rd,
3502         (imm + (1LL << 35) + (1LL << 23) + (1LL << 11)) << 16 >>
3503             52);  // Bits 47:36
3504   slli(rd, rd, 12);
3505   addi(rd, rd, (imm + (1LL << 23) + (1LL << 11)) << 28 >> 52);  // Bits 35:24
3506   slli(rd, rd, 12);
3507   addi(rd, rd, (imm + (1LL << 11)) << 40 >> 52);  // Bits 23:12
3508   slli(rd, rd, 12);
3509   addi(rd, rd, imm << 52 >> 52);  // Bits 11:0
3510 }
3511 
3512 // Break / Trap instructions.
break_(uint32_t code,bool break_as_stop)3513 void Assembler::break_(uint32_t code, bool break_as_stop) {
3514   // We need to invalidate breaks that could be stops as well because the
3515   // simulator expects a char pointer after the stop instruction.
3516   // See constants-mips.h for explanation.
3517   DCHECK(
3518       (break_as_stop && code <= kMaxStopCode && code > kMaxWatchpointCode) ||
3519       (!break_as_stop && (code > kMaxStopCode || code <= kMaxWatchpointCode)));
3520 
3521   // since ebreak does not allow additional immediate field, we use the
3522   // immediate field of lui instruction immediately following the ebreak to
3523   // encode the "code" info
3524   ebreak();
3525   DCHECK(is_uint20(code));
3526   lui(zero_reg, code);
3527 }
3528 
stop(uint32_t code)3529 void Assembler::stop(uint32_t code) {
3530   DCHECK_GT(code, kMaxWatchpointCode);
3531   DCHECK_LE(code, kMaxStopCode);
3532 #if defined(V8_HOST_ARCH_RISCV64)
3533   break_(0x54321);
3534 #else  // V8_HOST_ARCH_RISCV64
3535   break_(code, true);
3536 #endif
3537 }
3538 
3539 // Original MIPS Instructions
3540 
3541 // ------------Memory-instructions-------------
3542 
NeedAdjustBaseAndOffset(const MemOperand & src,OffsetAccessType access_type,int second_access_add_to_offset)3543 bool Assembler::NeedAdjustBaseAndOffset(const MemOperand& src,
3544                                         OffsetAccessType access_type,
3545                                         int second_access_add_to_offset) {
3546   bool two_accesses = static_cast<bool>(access_type);
3547   DCHECK_LE(second_access_add_to_offset, 7);  // Must be <= 7.
3548 
3549   // is_int12 must be passed a signed value, hence the static cast below.
3550   if (is_int12(src.offset()) &&
3551       (!two_accesses || is_int12(static_cast<int32_t>(
3552                             src.offset() + second_access_add_to_offset)))) {
3553     // Nothing to do: 'offset' (and, if needed, 'offset + 4', or other specified
3554     // value) fits into int12.
3555     return false;
3556   }
3557   return true;
3558 }
3559 
AdjustBaseAndOffset(MemOperand * src,Register scratch,OffsetAccessType access_type,int second_Access_add_to_offset)3560 void Assembler::AdjustBaseAndOffset(MemOperand* src, Register scratch,
3561                                     OffsetAccessType access_type,
3562                                     int second_Access_add_to_offset) {
3563   // This method is used to adjust the base register and offset pair
3564   // for a load/store when the offset doesn't fit into int12.
3565 
3566   // Must not overwrite the register 'base' while loading 'offset'.
3567   constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7F8;
3568   constexpr int32_t kMaxOffsetForSimpleAdjustment =
3569       2 * kMinOffsetForSimpleAdjustment;
3570   if (0 <= src->offset() && src->offset() <= kMaxOffsetForSimpleAdjustment) {
3571     addi(scratch, src->rm(), kMinOffsetForSimpleAdjustment);
3572     src->offset_ -= kMinOffsetForSimpleAdjustment;
3573   } else if (-kMaxOffsetForSimpleAdjustment <= src->offset() &&
3574              src->offset() < 0) {
3575     addi(scratch, src->rm(), -kMinOffsetForSimpleAdjustment);
3576     src->offset_ += kMinOffsetForSimpleAdjustment;
3577   } else if (access_type == OffsetAccessType::SINGLE_ACCESS) {
3578     RV_li(scratch, (static_cast<int64_t>(src->offset()) + 0x800) >> 12 << 12);
3579     add(scratch, scratch, src->rm());
3580     src->offset_ = src->offset() << 20 >> 20;
3581   } else {
3582     RV_li(scratch, src->offset());
3583     add(scratch, scratch, src->rm());
3584     src->offset_ = 0;
3585   }
3586   src->rm_ = scratch;
3587 }
3588 
RelocateInternalReference(RelocInfo::Mode rmode,Address pc,intptr_t pc_delta)3589 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, Address pc,
3590                                          intptr_t pc_delta) {
3591   if (RelocInfo::IsInternalReference(rmode)) {
3592     int64_t* p = reinterpret_cast<int64_t*>(pc);
3593     if (*p == kEndOfJumpChain) {
3594       return 0;  // Number of instructions patched.
3595     }
3596     *p += pc_delta;
3597     return 2;  // Number of instructions patched.
3598   }
3599   Instr instr = instr_at(pc);
3600   DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode));
3601   if (IsLui(instr)) {
3602     uint64_t target_address = target_address_at(pc) + pc_delta;
3603     DEBUG_PRINTF("target_address 0x%lx\n", target_address);
3604     set_target_value_at(pc, target_address);
3605     return 8;  // Number of instructions patched.
3606   } else {
3607     UNIMPLEMENTED();
3608   }
3609 }
3610 
RelocateRelativeReference(RelocInfo::Mode rmode,Address pc,intptr_t pc_delta)3611 void Assembler::RelocateRelativeReference(RelocInfo::Mode rmode, Address pc,
3612                                           intptr_t pc_delta) {
3613   Instr instr = instr_at(pc);
3614   Instr instr1 = instr_at(pc + 1 * kInstrSize);
3615   DCHECK(RelocInfo::IsRelativeCodeTarget(rmode));
3616   if (IsAuipc(instr) && IsJalr(instr1)) {
3617     int32_t imm;
3618     imm = BrachlongOffset(instr, instr1);
3619     imm -= pc_delta;
3620     PatchBranchlongOffset(pc, instr, instr1, imm);
3621     return;
3622   } else {
3623     UNREACHABLE();
3624   }
3625 }
3626 
GrowBuffer()3627 void Assembler::GrowBuffer() {
3628   DEBUG_PRINTF("GrowBuffer: %p -> ", buffer_start_);
3629   // Compute new buffer size.
3630   int old_size = buffer_->size();
3631   int new_size = std::min(2 * old_size, old_size + 1 * MB);
3632 
3633   // Some internal data structures overflow for very large buffers,
3634   // they must ensure that kMaximalBufferSize is not too large.
3635   if (new_size > kMaximalBufferSize) {
3636     V8::FatalProcessOutOfMemory(nullptr, "Assembler::GrowBuffer");
3637   }
3638 
3639   // Set up new buffer.
3640   std::unique_ptr<AssemblerBuffer> new_buffer = buffer_->Grow(new_size);
3641   DCHECK_EQ(new_size, new_buffer->size());
3642   byte* new_start = new_buffer->start();
3643 
3644   // Copy the data.
3645   intptr_t pc_delta = new_start - buffer_start_;
3646   intptr_t rc_delta = (new_start + new_size) - (buffer_start_ + old_size);
3647   size_t reloc_size = (buffer_start_ + old_size) - reloc_info_writer.pos();
3648   MemMove(new_start, buffer_start_, pc_offset());
3649   MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
3650           reloc_size);
3651 
3652   // Switch buffers.
3653   buffer_ = std::move(new_buffer);
3654   buffer_start_ = new_start;
3655   DEBUG_PRINTF("%p\n", buffer_start_);
3656   pc_ += pc_delta;
3657   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
3658                                reloc_info_writer.last_pc() + pc_delta);
3659 
3660   // Relocate runtime entries.
3661   base::Vector<byte> instructions{buffer_start_,
3662                                   static_cast<size_t>(pc_offset())};
3663   base::Vector<const byte> reloc_info{reloc_info_writer.pos(), reloc_size};
3664   for (RelocIterator it(instructions, reloc_info, 0); !it.done(); it.next()) {
3665     RelocInfo::Mode rmode = it.rinfo()->rmode();
3666     if (rmode == RelocInfo::INTERNAL_REFERENCE) {
3667       RelocateInternalReference(rmode, it.rinfo()->pc(), pc_delta);
3668     }
3669   }
3670 
3671   DCHECK(!overflow());
3672 }
3673 
db(uint8_t data)3674 void Assembler::db(uint8_t data) {
3675   if (!is_buffer_growth_blocked()) CheckBuffer();
3676   DEBUG_PRINTF("%p: constant 0x%x\n", pc_, data);
3677   EmitHelper(data);
3678 }
3679 
dd(uint32_t data,RelocInfo::Mode rmode)3680 void Assembler::dd(uint32_t data, RelocInfo::Mode rmode) {
3681   if (!RelocInfo::IsNoInfo(rmode)) {
3682     DCHECK(RelocInfo::IsDataEmbeddedObject(rmode) ||
3683            RelocInfo::IsLiteralConstant(rmode));
3684     RecordRelocInfo(rmode);
3685   }
3686   if (!is_buffer_growth_blocked()) CheckBuffer();
3687   DEBUG_PRINTF("%p: constant 0x%x\n", pc_, data);
3688   EmitHelper(data);
3689 }
3690 
dq(uint64_t data,RelocInfo::Mode rmode)3691 void Assembler::dq(uint64_t data, RelocInfo::Mode rmode) {
3692   if (!RelocInfo::IsNoInfo(rmode)) {
3693     DCHECK(RelocInfo::IsDataEmbeddedObject(rmode) ||
3694            RelocInfo::IsLiteralConstant(rmode));
3695     RecordRelocInfo(rmode);
3696   }
3697   if (!is_buffer_growth_blocked()) CheckBuffer();
3698   DEBUG_PRINTF("%p: constant 0x%lx\n", pc_, data);
3699   EmitHelper(data);
3700 }
3701 
dd(Label * label)3702 void Assembler::dd(Label* label) {
3703   uint64_t data;
3704   if (!is_buffer_growth_blocked()) CheckBuffer();
3705   if (label->is_bound()) {
3706     data = reinterpret_cast<uint64_t>(buffer_start_ + label->pos());
3707   } else {
3708     data = jump_address(label);
3709     internal_reference_positions_.insert(label->pos());
3710   }
3711   RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
3712   EmitHelper(data);
3713 }
3714 
RecordRelocInfo(RelocInfo::Mode rmode,intptr_t data)3715 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3716   if (!ShouldRecordRelocInfo(rmode)) return;
3717   // We do not try to reuse pool constants.
3718   RelocInfo rinfo(reinterpret_cast<Address>(pc_), rmode, data, Code());
3719   DCHECK_GE(buffer_space(), kMaxRelocSize);  // Too late to grow buffer here.
3720   reloc_info_writer.Write(&rinfo);
3721 }
3722 
BlockTrampolinePoolFor(int instructions)3723 void Assembler::BlockTrampolinePoolFor(int instructions) {
3724   DEBUG_PRINTF("\tBlockTrampolinePoolFor %d", instructions);
3725   CheckTrampolinePoolQuick(instructions);
3726   DEBUG_PRINTF("\tpc_offset %d,BlockTrampolinePoolBefore %d\n", pc_offset(),
3727                pc_offset() + instructions * kInstrSize);
3728   BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
3729 }
3730 
CheckTrampolinePool()3731 void Assembler::CheckTrampolinePool() {
3732   // Some small sequences of instructions must not be broken up by the
3733   // insertion of a trampoline pool; such sequences are protected by setting
3734   // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
3735   // which are both checked here. Also, recursive calls to CheckTrampolinePool
3736   // are blocked by trampoline_pool_blocked_nesting_.
3737   DEBUG_PRINTF("\tpc_offset %d no_trampoline_pool_before:%d\n", pc_offset(),
3738                no_trampoline_pool_before_);
3739   DEBUG_PRINTF("\ttrampoline_pool_blocked_nesting:%d\n",
3740                trampoline_pool_blocked_nesting_);
3741   if ((trampoline_pool_blocked_nesting_ > 0) ||
3742       (pc_offset() < no_trampoline_pool_before_)) {
3743     // Emission is currently blocked; make sure we try again as soon as
3744     // possible.
3745     if (trampoline_pool_blocked_nesting_ > 0) {
3746       next_buffer_check_ = pc_offset() + kInstrSize;
3747     } else {
3748       next_buffer_check_ = no_trampoline_pool_before_;
3749     }
3750     return;
3751   }
3752 
3753   DCHECK(!trampoline_emitted_);
3754   DCHECK_GE(unbound_labels_count_, 0);
3755   if (unbound_labels_count_ > 0) {
3756     // First we emit jump, then we emit trampoline pool.
3757     {
3758       DEBUG_PRINTF("inserting trampoline pool at %p (%d)\n",
3759                    reinterpret_cast<Instr*>(buffer_start_ + pc_offset()),
3760                    pc_offset());
3761       BlockTrampolinePoolScope block_trampoline_pool(this);
3762       Label after_pool;
3763       j(&after_pool);
3764 
3765       int pool_start = pc_offset();
3766       for (int i = 0; i < unbound_labels_count_; i++) {
3767         int64_t imm64;
3768         imm64 = branch_long_offset(&after_pool);
3769         CHECK(is_int32(imm64 + 0x800));
3770         int32_t Hi20 = (((int32_t)imm64 + 0x800) >> 12);
3771         int32_t Lo12 = (int32_t)imm64 << 20 >> 20;
3772         auipc(t6, Hi20);  // Read PC + Hi20 into t6
3773         jr(t6, Lo12);     // jump PC + Hi20 + Lo12
3774       }
3775       // If unbound_labels_count_ is big enough, label after_pool will
3776       // need a trampoline too, so we must create the trampoline before
3777       // the bind operation to make sure function 'bind' can get this
3778       // information.
3779       trampoline_ = Trampoline(pool_start, unbound_labels_count_);
3780       bind(&after_pool);
3781 
3782       trampoline_emitted_ = true;
3783       // As we are only going to emit trampoline once, we need to prevent any
3784       // further emission.
3785       next_buffer_check_ = kMaxInt;
3786     }
3787   } else {
3788     // Number of branches to unbound label at this point is zero, so we can
3789     // move next buffer check to maximum.
3790     next_buffer_check_ =
3791         pc_offset() + kMaxBranchOffset - kTrampolineSlotsSize * 16;
3792   }
3793   return;
3794 }
3795 
set_target_address_at(Address pc,Address constant_pool,Address target,ICacheFlushMode icache_flush_mode)3796 void Assembler::set_target_address_at(Address pc, Address constant_pool,
3797                                       Address target,
3798                                       ICacheFlushMode icache_flush_mode) {
3799   Instr* instr = reinterpret_cast<Instr*>(pc);
3800   if (IsAuipc(*instr)) {
3801     if (IsLd(*reinterpret_cast<Instr*>(pc + 4))) {
3802       int32_t Hi20 = AuipcOffset(*instr);
3803       int32_t Lo12 = LdOffset(*reinterpret_cast<Instr*>(pc + 4));
3804       Memory<Address>(pc + Hi20 + Lo12) = target;
3805       if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
3806         FlushInstructionCache(pc + Hi20 + Lo12, 2 * kInstrSize);
3807       }
3808     } else {
3809       DCHECK(IsJalr(*reinterpret_cast<Instr*>(pc + 4)));
3810       int64_t imm = (int64_t)target - (int64_t)pc;
3811       Instr instr = instr_at(pc);
3812       Instr instr1 = instr_at(pc + 1 * kInstrSize);
3813       DCHECK(is_int32(imm + 0x800));
3814       int num = PatchBranchlongOffset(pc, instr, instr1, (int32_t)imm);
3815       if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
3816         FlushInstructionCache(pc, num * kInstrSize);
3817       }
3818     }
3819   } else {
3820     set_target_address_at(pc, target, icache_flush_mode);
3821   }
3822 }
3823 
target_address_at(Address pc,Address constant_pool)3824 Address Assembler::target_address_at(Address pc, Address constant_pool) {
3825   Instr* instr = reinterpret_cast<Instr*>(pc);
3826   if (IsAuipc(*instr)) {
3827     if (IsLd(*reinterpret_cast<Instr*>(pc + 4))) {
3828       int32_t Hi20 = AuipcOffset(*instr);
3829       int32_t Lo12 = LdOffset(*reinterpret_cast<Instr*>(pc + 4));
3830       return Memory<Address>(pc + Hi20 + Lo12);
3831     } else {
3832       DCHECK(IsJalr(*reinterpret_cast<Instr*>(pc + 4)));
3833       int32_t Hi20 = AuipcOffset(*instr);
3834       int32_t Lo12 = JalrOffset(*reinterpret_cast<Instr*>(pc + 4));
3835       return pc + Hi20 + Lo12;
3836     }
3837 
3838   } else {
3839     return target_address_at(pc);
3840   }
3841 }
target_address_at(Address pc)3842 Address Assembler::target_address_at(Address pc) {
3843   DEBUG_PRINTF("target_address_at: pc: %lx\t", pc);
3844   Instruction* instr0 = Instruction::At((unsigned char*)pc);
3845   Instruction* instr1 = Instruction::At((unsigned char*)(pc + 1 * kInstrSize));
3846   Instruction* instr2 = Instruction::At((unsigned char*)(pc + 2 * kInstrSize));
3847   Instruction* instr3 = Instruction::At((unsigned char*)(pc + 3 * kInstrSize));
3848   Instruction* instr4 = Instruction::At((unsigned char*)(pc + 4 * kInstrSize));
3849   Instruction* instr5 = Instruction::At((unsigned char*)(pc + 5 * kInstrSize));
3850 
3851   // Interpret instructions for address generated by li: See listing in
3852   // Assembler::set_target_address_at() just below.
3853   if (IsLui(*reinterpret_cast<Instr*>(instr0)) &&
3854       IsAddi(*reinterpret_cast<Instr*>(instr1)) &&
3855       IsSlli(*reinterpret_cast<Instr*>(instr2)) &&
3856       IsOri(*reinterpret_cast<Instr*>(instr3)) &&
3857       IsSlli(*reinterpret_cast<Instr*>(instr4)) &&
3858       IsOri(*reinterpret_cast<Instr*>(instr5))) {
3859     // Assemble the 64 bit value.
3860     int64_t addr = (int64_t)(instr0->Imm20UValue() << kImm20Shift) +
3861                    (int64_t)instr1->Imm12Value();
3862     addr <<= 11;
3863     addr |= (int64_t)instr3->Imm12Value();
3864     addr <<= 6;
3865     addr |= (int64_t)instr5->Imm12Value();
3866 
3867     DEBUG_PRINTF("addr: %lx\n", addr);
3868     return static_cast<Address>(addr);
3869   }
3870   // We should never get here, force a bad address if we do.
3871   UNREACHABLE();
3872 }
3873 // On RISC-V, a 48-bit target address is stored in an 6-instruction sequence:
3874 //  lui(reg, (int32_t)high_20); // 19 high bits
3875 //  addi(reg, reg, low_12); // 12 following bits. total is 31 high bits in reg.
3876 //  slli(reg, reg, 11); // Space for next 11 bits
3877 //  ori(reg, reg, b11); // 11 bits are put in. 42 bit in reg
3878 //  slli(reg, reg, 6); // Space for next 6 bits
3879 //  ori(reg, reg, a6); // 6 bits are put in. all 48 bis in reg
3880 //
3881 // Patching the address must replace all instructions, and flush the i-cache.
3882 // Note that this assumes the use of SV48, the 48-bit virtual memory system.
set_target_value_at(Address pc,uint64_t target,ICacheFlushMode icache_flush_mode)3883 void Assembler::set_target_value_at(Address pc, uint64_t target,
3884                                     ICacheFlushMode icache_flush_mode) {
3885   DEBUG_PRINTF("set_target_value_at: pc: %lx\ttarget: %lx\n", pc, target);
3886   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
3887   DCHECK_EQ((target & 0xffff000000000000ll), 0);
3888 #ifdef DEBUG
3889   // Check we have the result from a li macro-instruction.
3890   Instruction* instr0 = Instruction::At((unsigned char*)pc);
3891   Instruction* instr1 = Instruction::At((unsigned char*)(pc + 1 * kInstrSize));
3892   Instruction* instr3 = Instruction::At((unsigned char*)(pc + 3 * kInstrSize));
3893   Instruction* instr5 = Instruction::At((unsigned char*)(pc + 5 * kInstrSize));
3894   DCHECK(IsLui(*reinterpret_cast<Instr*>(instr0)) &&
3895          IsAddi(*reinterpret_cast<Instr*>(instr1)) &&
3896          IsOri(*reinterpret_cast<Instr*>(instr3)) &&
3897          IsOri(*reinterpret_cast<Instr*>(instr5)));
3898 #endif
3899   int64_t a6 = target & 0x3f;                     // bits 0:6. 6 bits
3900   int64_t b11 = (target >> 6) & 0x7ff;            // bits 6:11. 11 bits
3901   int64_t high_31 = (target >> 17) & 0x7fffffff;  // 31 bits
3902   int64_t high_20 = ((high_31 + 0x800) >> 12);    // 19 bits
3903   int64_t low_12 = high_31 & 0xfff;               // 12 bits
3904   *p = *p & 0xfff;
3905   *p = *p | ((int32_t)high_20 << 12);
3906   *(p + 1) = *(p + 1) & 0xfffff;
3907   *(p + 1) = *(p + 1) | ((int32_t)low_12 << 20);
3908   *(p + 2) = *(p + 2) & 0xfffff;
3909   *(p + 2) = *(p + 2) | (11 << 20);
3910   *(p + 3) = *(p + 3) & 0xfffff;
3911   *(p + 3) = *(p + 3) | ((int32_t)b11 << 20);
3912   *(p + 4) = *(p + 4) & 0xfffff;
3913   *(p + 4) = *(p + 4) | (6 << 20);
3914   *(p + 5) = *(p + 5) & 0xfffff;
3915   *(p + 5) = *(p + 5) | ((int32_t)a6 << 20);
3916   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
3917     FlushInstructionCache(pc, 8 * kInstrSize);
3918   }
3919   DCHECK_EQ(target_address_at(pc), target);
3920 }
UseScratchRegisterScope(Assembler * assembler)3921 UseScratchRegisterScope::UseScratchRegisterScope(Assembler* assembler)
3922     : available_(assembler->GetScratchRegisterList()),
3923       old_available_(*available_) {}
3924 
~UseScratchRegisterScope()3925 UseScratchRegisterScope::~UseScratchRegisterScope() {
3926   *available_ = old_available_;
3927 }
3928 
Acquire()3929 Register UseScratchRegisterScope::Acquire() {
3930   DCHECK_NOT_NULL(available_);
3931   DCHECK(!available_->is_empty());
3932   int index =
3933       static_cast<int>(base::bits::CountTrailingZeros32(available_->bits()));
3934   *available_ &= RegList::FromBits(~(1U << index));
3935 
3936   return Register::from_code(index);
3937 }
3938 
hasAvailable() const3939 bool UseScratchRegisterScope::hasAvailable() const {
3940   return !available_->is_empty();
3941 }
3942 
IsConstantPoolAt(Instruction * instr)3943 bool Assembler::IsConstantPoolAt(Instruction* instr) {
3944   // The constant pool marker is made of two instructions. These instructions
3945   // will never be emitted by the JIT, so checking for the first one is enough:
3946   // 0: ld x0, x0, #offset
3947   Instr instr_value = *reinterpret_cast<Instr*>(instr);
3948   bool result = IsLd(instr_value) && (instr->Rs1Value() == kRegCode_zero_reg) &&
3949                 (instr->RdValue() == kRegCode_zero_reg);
3950 #ifdef DEBUG
3951   // It is still worth asserting the marker is complete.
3952   // 1: j 0x0
3953   Instruction* instr_following = instr + kInstrSize;
3954   DCHECK(!result || (IsJal(*reinterpret_cast<Instr*>(instr_following)) &&
3955                      instr_following->Imm20JValue() == 0 &&
3956                      instr_following->RdValue() == kRegCode_zero_reg));
3957 #endif
3958   return result;
3959 }
3960 
ConstantPoolSizeAt(Instruction * instr)3961 int Assembler::ConstantPoolSizeAt(Instruction* instr) {
3962   if (IsConstantPoolAt(instr)) {
3963     return instr->Imm12Value();
3964   } else {
3965     return -1;
3966   }
3967 }
3968 
RecordConstPool(int size)3969 void Assembler::RecordConstPool(int size) {
3970   // We only need this for debugger support, to correctly compute offsets in the
3971   // code.
3972   Assembler::BlockPoolsScope block_pools(this);
3973   RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
3974 }
3975 
EmitPoolGuard()3976 void Assembler::EmitPoolGuard() {
3977   // We must generate only one instruction as this is used in scopes that
3978   // control the size of the code generated.
3979   j(0);
3980 }
3981 
3982 // Constant Pool
3983 
EmitPrologue(Alignment require_alignment)3984 void ConstantPool::EmitPrologue(Alignment require_alignment) {
3985   // Recorded constant pool size is expressed in number of 32-bits words,
3986   // and includes prologue and alignment, but not the jump around the pool
3987   // and the size of the marker itself.
3988   const int marker_size = 1;
3989   int word_count =
3990       ComputeSize(Jump::kOmitted, require_alignment) / kInt32Size - marker_size;
3991   assm_->ld(zero_reg, zero_reg, word_count);
3992   assm_->EmitPoolGuard();
3993 }
3994 
PrologueSize(Jump require_jump) const3995 int ConstantPool::PrologueSize(Jump require_jump) const {
3996   // Prologue is:
3997   //   j over  ;; if require_jump
3998   //   ld x0, x0, #pool_size
3999   //   j 0x0
4000   int prologue_size = require_jump == Jump::kRequired ? kInstrSize : 0;
4001   prologue_size += 2 * kInstrSize;
4002   return prologue_size;
4003 }
4004 
SetLoadOffsetToConstPoolEntry(int load_offset,Instruction * entry_offset,const ConstantPoolKey & key)4005 void ConstantPool::SetLoadOffsetToConstPoolEntry(int load_offset,
4006                                                  Instruction* entry_offset,
4007                                                  const ConstantPoolKey& key) {
4008   Instr instr_auipc = assm_->instr_at(load_offset);
4009   Instr instr_ld = assm_->instr_at(load_offset + 4);
4010   // Instruction to patch must be 'ld rd, offset(rd)' with 'offset == 0'.
4011   DCHECK(assm_->IsAuipc(instr_auipc));
4012   DCHECK(assm_->IsLd(instr_ld));
4013   DCHECK_EQ(assm_->LdOffset(instr_ld), 0);
4014   DCHECK_EQ(assm_->AuipcOffset(instr_auipc), 0);
4015   int32_t distance = static_cast<int32_t>(
4016       reinterpret_cast<Address>(entry_offset) -
4017       reinterpret_cast<Address>(assm_->toAddress(load_offset)));
4018   CHECK(is_int32(distance + 0x800));
4019   int32_t Hi20 = (((int32_t)distance + 0x800) >> 12);
4020   int32_t Lo12 = (int32_t)distance << 20 >> 20;
4021   assm_->instr_at_put(load_offset, SetAuipcOffset(Hi20, instr_auipc));
4022   assm_->instr_at_put(load_offset + 4, SetLdOffset(Lo12, instr_ld));
4023 }
4024 
Check(Emission force_emit,Jump require_jump,size_t margin)4025 void ConstantPool::Check(Emission force_emit, Jump require_jump,
4026                          size_t margin) {
4027   // Some short sequence of instruction must not be broken up by constant pool
4028   // emission, such sequences are protected by a ConstPool::BlockScope.
4029   if (IsBlocked()) {
4030     // Something is wrong if emission is forced and blocked at the same time.
4031     DCHECK_EQ(force_emit, Emission::kIfNeeded);
4032     return;
4033   }
4034 
4035   // We emit a constant pool only if :
4036   //  * it is not empty
4037   //  * emission is forced by parameter force_emit (e.g. at function end).
4038   //  * emission is mandatory or opportune according to {ShouldEmitNow}.
4039   if (!IsEmpty() && (force_emit == Emission::kForced ||
4040                      ShouldEmitNow(require_jump, margin))) {
4041     // Emit veneers for branches that would go out of range during emission of
4042     // the constant pool.
4043     int worst_case_size = ComputeSize(Jump::kRequired, Alignment::kRequired);
4044 
4045     // Check that the code buffer is large enough before emitting the constant
4046     // pool (this includes the gap to the relocation information).
4047     int needed_space = worst_case_size + assm_->kGap;
4048     while (assm_->buffer_space() <= needed_space) {
4049       assm_->GrowBuffer();
4050     }
4051 
4052     EmitAndClear(require_jump);
4053   }
4054   // Since a constant pool is (now) empty, move the check offset forward by
4055   // the standard interval.
4056   SetNextCheckIn(ConstantPool::kCheckInterval);
4057 }
4058 
LoadStoreLaneParams(MachineRepresentation rep,uint8_t laneidx)4059 LoadStoreLaneParams::LoadStoreLaneParams(MachineRepresentation rep,
4060                                          uint8_t laneidx) {
4061   switch (rep) {
4062     case MachineRepresentation::kWord8:
4063       *this = LoadStoreLaneParams(laneidx, 8, kRvvVLEN / 16);
4064       break;
4065     case MachineRepresentation::kWord16:
4066       *this = LoadStoreLaneParams(laneidx, 16, kRvvVLEN / 8);
4067       break;
4068     case MachineRepresentation::kWord32:
4069       *this = LoadStoreLaneParams(laneidx, 32, kRvvVLEN / 4);
4070       break;
4071     case MachineRepresentation::kWord64:
4072       *this = LoadStoreLaneParams(laneidx, 64, kRvvVLEN / 2);
4073       break;
4074     default:
4075       UNREACHABLE();
4076   }
4077 }
4078 
4079 // Pool entries are accessed with pc relative load therefore this cannot be more
4080 // than 1 * MB. Since constant pool emission checks are interval based, and we
4081 // want to keep entries close to the code, we try to emit every 64KB.
4082 const size_t ConstantPool::kMaxDistToPool32 = 1 * MB;
4083 const size_t ConstantPool::kMaxDistToPool64 = 1 * MB;
4084 const size_t ConstantPool::kCheckInterval = 128 * kInstrSize;
4085 const size_t ConstantPool::kApproxDistToPool32 = 64 * KB;
4086 const size_t ConstantPool::kApproxDistToPool64 = kApproxDistToPool32;
4087 
4088 const size_t ConstantPool::kOpportunityDistToPool32 = 64 * KB;
4089 const size_t ConstantPool::kOpportunityDistToPool64 = 64 * KB;
4090 const size_t ConstantPool::kApproxMaxEntryCount = 512;
4091 
4092 }  // namespace internal
4093 }  // namespace v8
4094 
4095 #endif  // V8_TARGET_ARCH_RISCV64
4096