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