• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/codegen/loong64/assembler-loong64.h"
6 
7 #if V8_TARGET_ARCH_LOONG64
8 
9 #include "src/base/cpu.h"
10 #include "src/codegen/loong64/assembler-loong64-inl.h"
11 #include "src/codegen/machine-type.h"
12 #include "src/codegen/safepoint-table.h"
13 #include "src/codegen/string-constants.h"
14 #include "src/deoptimizer/deoptimizer.h"
15 #include "src/objects/heap-number-inl.h"
16 
17 namespace v8 {
18 namespace internal {
19 
SupportsWasmSimd128()20 bool CpuFeatures::SupportsWasmSimd128() { return false; }
21 
ProbeImpl(bool cross_compile)22 void CpuFeatures::ProbeImpl(bool cross_compile) {
23   supported_ |= 1u << FPU;
24 
25   // Only use statically determined features for cross compile (snapshot).
26   if (cross_compile) return;
27 
28 #ifdef __loongarch__
29   // Probe for additional features at runtime.
30   base::CPU cpu;
31   supported_ |= 1u << FPU;
32 #endif
33 
34   // Set a static value on whether Simd is supported.
35   // This variable is only used for certain archs to query SupportWasmSimd128()
36   // at runtime in builtins using an extern ref. Other callers should use
37   // CpuFeatures::SupportWasmSimd128().
38   CpuFeatures::supports_wasm_simd_128_ = CpuFeatures::SupportsWasmSimd128();
39 }
40 
PrintTarget()41 void CpuFeatures::PrintTarget() {}
PrintFeatures()42 void CpuFeatures::PrintFeatures() {}
43 
ToNumber(Register reg)44 int ToNumber(Register reg) {
45   DCHECK(reg.is_valid());
46   const int kNumbers[] = {
47       0,   // zero_reg
48       1,   // ra
49       2,   // tp
50       3,   // sp
51       4,   // a0 v0
52       5,   // a1 v1
53       6,   // a2
54       7,   // a3
55       8,   // a4
56       9,   // a5
57       10,  // a6
58       11,  // a7
59       12,  // t0
60       13,  // t1
61       14,  // t2
62       15,  // t3
63       16,  // t4
64       17,  // t5
65       18,  // t6
66       19,  // t7
67       20,  // t8
68       21,  // x_reg
69       22,  // fp
70       23,  // s0
71       24,  // s1
72       25,  // s2
73       26,  // s3
74       27,  // s4
75       28,  // s5
76       29,  // s6
77       30,  // s7
78       31,  // s8
79   };
80   return kNumbers[reg.code()];
81 }
82 
ToRegister(int num)83 Register ToRegister(int num) {
84   DCHECK(num >= 0 && num < kNumRegisters);
85   const Register kRegisters[] = {
86       zero_reg, ra, tp, sp, a0, a1,    a2, a3, a4, a5, a6, a7, t0, t1, t2, t3,
87       t4,       t5, t6, t7, t8, x_reg, fp, s0, s1, s2, s3, s4, s5, s6, s7, s8};
88   return kRegisters[num];
89 }
90 
91 // -----------------------------------------------------------------------------
92 // Implementation of RelocInfo.
93 
94 const int RelocInfo::kApplyMask =
95     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
96     RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET);
97 
IsCodedSpecially()98 bool RelocInfo::IsCodedSpecially() {
99   // The deserializer needs to know whether a pointer is specially coded.  Being
100   // specially coded on LoongArch64 means that it is a lu12i_w/ori instruction,
101   // and that is always the case inside code objects.
102   return true;
103 }
104 
IsInConstantPool()105 bool RelocInfo::IsInConstantPool() { return false; }
106 
wasm_call_tag() const107 uint32_t RelocInfo::wasm_call_tag() const {
108   DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL);
109   return static_cast<uint32_t>(
110       Assembler::target_address_at(pc_, constant_pool_));
111 }
112 
113 // -----------------------------------------------------------------------------
114 // Implementation of Operand and MemOperand.
115 // See assembler-loong64-inl.h for inlined constructors.
116 
Operand(Handle<HeapObject> handle)117 Operand::Operand(Handle<HeapObject> handle)
118     : rm_(no_reg), rmode_(RelocInfo::FULL_EMBEDDED_OBJECT) {
119   value_.immediate = static_cast<intptr_t>(handle.address());
120 }
121 
EmbeddedNumber(double value)122 Operand Operand::EmbeddedNumber(double value) {
123   int32_t smi;
124   if (DoubleToSmiInteger(value, &smi)) return Operand(Smi::FromInt(smi));
125   Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
126   result.is_heap_object_request_ = true;
127   result.value_.heap_object_request = HeapObjectRequest(value);
128   return result;
129 }
130 
EmbeddedStringConstant(const StringConstantBase * str)131 Operand Operand::EmbeddedStringConstant(const StringConstantBase* str) {
132   Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
133   result.is_heap_object_request_ = true;
134   result.value_.heap_object_request = HeapObjectRequest(str);
135   return result;
136 }
137 
MemOperand(Register base,int32_t offset)138 MemOperand::MemOperand(Register base, int32_t offset)
139     : base_(base), index_(no_reg), offset_(offset) {}
140 
MemOperand(Register base,Register index)141 MemOperand::MemOperand(Register base, Register index)
142     : base_(base), index_(index), offset_(0) {}
143 
AllocateAndInstallRequestedHeapObjects(Isolate * isolate)144 void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
145   DCHECK_IMPLIES(isolate == nullptr, heap_object_requests_.empty());
146   for (auto& request : heap_object_requests_) {
147     Handle<HeapObject> object;
148     switch (request.kind()) {
149       case HeapObjectRequest::kHeapNumber:
150         object = isolate->factory()->NewHeapNumber<AllocationType::kOld>(
151             request.heap_number());
152         break;
153       case HeapObjectRequest::kStringConstant:
154         const StringConstantBase* str = request.string();
155         CHECK_NOT_NULL(str);
156         object = str->AllocateStringConstant(isolate);
157         break;
158     }
159     Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
160     set_target_value_at(pc, reinterpret_cast<uint64_t>(object.location()));
161   }
162 }
163 
164 // -----------------------------------------------------------------------------
165 // Specific instructions, constants, and masks.
166 
Assembler(const AssemblerOptions & options,std::unique_ptr<AssemblerBuffer> buffer)167 Assembler::Assembler(const AssemblerOptions& options,
168                      std::unique_ptr<AssemblerBuffer> buffer)
169     : AssemblerBase(options, std::move(buffer)),
170       scratch_register_list_({t7, t6}) {
171   reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
172 
173   last_trampoline_pool_end_ = 0;
174   no_trampoline_pool_before_ = 0;
175   trampoline_pool_blocked_nesting_ = 0;
176   // We leave space (16 * kTrampolineSlotsSize)
177   // for BlockTrampolinePoolScope buffer.
178   next_buffer_check_ = FLAG_force_long_branches
179                            ? kMaxInt
180                            : kMax16BranchOffset - kTrampolineSlotsSize * 16;
181   internal_trampoline_exception_ = false;
182   last_bound_pos_ = 0;
183 
184   trampoline_emitted_ = FLAG_force_long_branches;
185   unbound_labels_count_ = 0;
186   block_buffer_growth_ = false;
187 }
188 
GetCode(Isolate * isolate,CodeDesc * desc,SafepointTableBuilder * safepoint_table_builder,int handler_table_offset)189 void Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
190                         SafepointTableBuilder* safepoint_table_builder,
191                         int handler_table_offset) {
192   // As a crutch to avoid having to add manual Align calls wherever we use a
193   // raw workflow to create Code objects (mostly in tests), add another Align
194   // call here. It does no harm - the end of the Code object is aligned to the
195   // (larger) kCodeAlignment anyways.
196   // TODO(jgruber): Consider moving responsibility for proper alignment to
197   // metadata table builders (safepoint, handler, constant pool, code
198   // comments).
199   DataAlign(Code::kMetadataAlignment);
200 
201   // EmitForbiddenSlotInstruction(); TODO:LOONG64 why?
202 
203   int code_comments_size = WriteCodeComments();
204 
205   DCHECK(pc_ <= reloc_info_writer.pos());  // No overlap.
206 
207   AllocateAndInstallRequestedHeapObjects(isolate);
208 
209   // Set up code descriptor.
210   // TODO(jgruber): Reconsider how these offsets and sizes are maintained up to
211   // this point to make CodeDesc initialization less fiddly.
212 
213   static constexpr int kConstantPoolSize = 0;
214   const int instruction_size = pc_offset();
215   const int code_comments_offset = instruction_size - code_comments_size;
216   const int constant_pool_offset = code_comments_offset - kConstantPoolSize;
217   const int handler_table_offset2 = (handler_table_offset == kNoHandlerTable)
218                                         ? constant_pool_offset
219                                         : handler_table_offset;
220   const int safepoint_table_offset =
221       (safepoint_table_builder == kNoSafepointTable)
222           ? handler_table_offset2
223           : safepoint_table_builder->safepoint_table_offset();
224   const int reloc_info_offset =
225       static_cast<int>(reloc_info_writer.pos() - buffer_->start());
226   CodeDesc::Initialize(desc, this, safepoint_table_offset,
227                        handler_table_offset2, constant_pool_offset,
228                        code_comments_offset, reloc_info_offset);
229 }
230 
Align(int m)231 void Assembler::Align(int m) {
232   // If not, the loop below won't terminate.
233   DCHECK(IsAligned(pc_offset(), kInstrSize));
234   DCHECK(m >= kInstrSize && base::bits::IsPowerOfTwo(m));
235   while ((pc_offset() & (m - 1)) != 0) {
236     nop();
237   }
238 }
239 
CodeTargetAlign()240 void Assembler::CodeTargetAlign() {
241   // No advantage to aligning branch/call targets to more than
242   // single instruction, that I am aware of.
243   Align(4);
244 }
245 
GetRkReg(Instr instr)246 Register Assembler::GetRkReg(Instr instr) {
247   return Register::from_code((instr & kRkFieldMask) >> kRkShift);
248 }
249 
GetRjReg(Instr instr)250 Register Assembler::GetRjReg(Instr instr) {
251   return Register::from_code((instr & kRjFieldMask) >> kRjShift);
252 }
253 
GetRdReg(Instr instr)254 Register Assembler::GetRdReg(Instr instr) {
255   return Register::from_code((instr & kRdFieldMask) >> kRdShift);
256 }
257 
GetRk(Instr instr)258 uint32_t Assembler::GetRk(Instr instr) {
259   return (instr & kRkFieldMask) >> kRkShift;
260 }
261 
GetRkField(Instr instr)262 uint32_t Assembler::GetRkField(Instr instr) { return instr & kRkFieldMask; }
263 
GetRj(Instr instr)264 uint32_t Assembler::GetRj(Instr instr) {
265   return (instr & kRjFieldMask) >> kRjShift;
266 }
267 
GetRjField(Instr instr)268 uint32_t Assembler::GetRjField(Instr instr) { return instr & kRjFieldMask; }
269 
GetRd(Instr instr)270 uint32_t Assembler::GetRd(Instr instr) {
271   return (instr & kRdFieldMask) >> kRdShift;
272 }
273 
GetRdField(Instr instr)274 uint32_t Assembler::GetRdField(Instr instr) { return instr & kRdFieldMask; }
275 
GetSa2(Instr instr)276 uint32_t Assembler::GetSa2(Instr instr) {
277   return (instr & kSa2FieldMask) >> kSaShift;
278 }
279 
GetSa2Field(Instr instr)280 uint32_t Assembler::GetSa2Field(Instr instr) { return instr & kSa2FieldMask; }
281 
GetSa3(Instr instr)282 uint32_t Assembler::GetSa3(Instr instr) {
283   return (instr & kSa3FieldMask) >> kSaShift;
284 }
285 
GetSa3Field(Instr instr)286 uint32_t Assembler::GetSa3Field(Instr instr) { return instr & kSa3FieldMask; }
287 
288 // Labels refer to positions in the (to be) generated code.
289 // There are bound, linked, and unused labels.
290 //
291 // Bound labels refer to known positions in the already
292 // generated code. pos() is the position the label refers to.
293 //
294 // Linked labels refer to unknown positions in the code
295 // to be generated; pos() is the position of the last
296 // instruction using the label.
297 
298 // The link chain is terminated by a value in the instruction of 0,
299 // which is an otherwise illegal value (branch 0 is inf loop).
300 // The instruction 16-bit offset field addresses 32-bit words, but in
301 // code is conv to an 18-bit value addressing bytes, hence the -4 value.
302 
303 const int kEndOfChain = 0;
304 // Determines the end of the Jump chain (a subset of the label link chain).
305 const int kEndOfJumpChain = 0;
306 
IsBranch(Instr instr)307 bool Assembler::IsBranch(Instr instr) {
308   uint32_t opcode = (instr >> 26) << 26;
309   // Checks if the instruction is a branch.
310   bool isBranch = opcode == BEQZ || opcode == BNEZ || opcode == BCZ ||
311                   opcode == B || opcode == BL || opcode == BEQ ||
312                   opcode == BNE || opcode == BLT || opcode == BGE ||
313                   opcode == BLTU || opcode == BGEU;
314   return isBranch;
315 }
316 
IsB(Instr instr)317 bool Assembler::IsB(Instr instr) {
318   uint32_t opcode = (instr >> 26) << 26;
319   // Checks if the instruction is a b.
320   bool isBranch = opcode == B || opcode == BL;
321   return isBranch;
322 }
323 
IsBz(Instr instr)324 bool Assembler::IsBz(Instr instr) {
325   uint32_t opcode = (instr >> 26) << 26;
326   // Checks if the instruction is a branch.
327   bool isBranch = opcode == BEQZ || opcode == BNEZ || opcode == BCZ;
328   return isBranch;
329 }
330 
IsEmittedConstant(Instr instr)331 bool Assembler::IsEmittedConstant(Instr instr) {
332   // Add GetLabelConst function?
333   uint32_t label_constant = instr & ~kImm16Mask;
334   return label_constant == 0;  // Emitted label const in reg-exp engine.
335 }
336 
IsJ(Instr instr)337 bool Assembler::IsJ(Instr instr) {
338   uint32_t opcode = (instr >> 26) << 26;
339   // Checks if the instruction is a jump.
340   return opcode == JIRL;
341 }
342 
IsLu12i_w(Instr instr)343 bool Assembler::IsLu12i_w(Instr instr) {
344   uint32_t opcode = (instr >> 25) << 25;
345   return opcode == LU12I_W;
346 }
347 
IsOri(Instr instr)348 bool Assembler::IsOri(Instr instr) {
349   uint32_t opcode = (instr >> 22) << 22;
350   return opcode == ORI;
351 }
352 
IsLu32i_d(Instr instr)353 bool Assembler::IsLu32i_d(Instr instr) {
354   uint32_t opcode = (instr >> 25) << 25;
355   return opcode == LU32I_D;
356 }
357 
IsLu52i_d(Instr instr)358 bool Assembler::IsLu52i_d(Instr instr) {
359   uint32_t opcode = (instr >> 22) << 22;
360   return opcode == LU52I_D;
361 }
362 
IsMov(Instr instr,Register rd,Register rj)363 bool Assembler::IsMov(Instr instr, Register rd, Register rj) {
364   // Checks if the instruction is a OR with zero_reg argument (aka MOV).
365   Instr instr1 =
366       OR | zero_reg.code() << kRkShift | rj.code() << kRjShift | rd.code();
367   return instr == instr1;
368 }
369 
IsPcAddi(Instr instr,Register rd,int32_t si20)370 bool Assembler::IsPcAddi(Instr instr, Register rd, int32_t si20) {
371   DCHECK(is_int20(si20));
372   Instr instr1 = PCADDI | (si20 & 0xfffff) << kRjShift | rd.code();
373   return instr == instr1;
374 }
375 
IsNop(Instr instr,unsigned int type)376 bool Assembler::IsNop(Instr instr, unsigned int type) {
377   // See Assembler::nop(type).
378   DCHECK_LT(type, 32);
379 
380   Instr instr1 =
381       ANDI | ((type & kImm12Mask) << kRkShift) | (zero_reg.code() << kRjShift);
382 
383   return instr == instr1;
384 }
385 
GetOffsetOfBranch(Instr instr,Assembler::OffsetSize bits)386 static inline int32_t GetOffsetOfBranch(Instr instr,
387                                         Assembler::OffsetSize bits) {
388   int32_t result = 0;
389   if (bits == 16) {
390     result = (instr << 6) >> 16;
391   } else if (bits == 21) {
392     uint32_t low16 = instr << 6;
393     low16 = low16 >> 16;
394     low16 &= 0xffff;
395     int32_t hi5 = (instr << 27) >> 11;
396     result = hi5 | low16;
397   } else {
398     uint32_t low16 = instr << 6;
399     low16 = low16 >> 16;
400     low16 &= 0xffff;
401     int32_t hi10 = (instr << 22) >> 6;
402     result = hi10 | low16;
403     DCHECK_EQ(bits, 26);
404   }
405   return result << 2;
406 }
407 
OffsetSizeInBits(Instr instr)408 static Assembler::OffsetSize OffsetSizeInBits(Instr instr) {
409   if (Assembler::IsB(instr)) {
410     return Assembler::OffsetSize::kOffset26;
411   } else if (Assembler::IsBz(instr)) {
412     return Assembler::OffsetSize::kOffset21;
413   } else {
414     DCHECK(Assembler::IsBranch(instr));
415     return Assembler::OffsetSize::kOffset16;
416   }
417 }
418 
AddBranchOffset(int pos,Instr instr)419 static inline int32_t AddBranchOffset(int pos, Instr instr) {
420   Assembler::OffsetSize bits = OffsetSizeInBits(instr);
421 
422   int32_t imm = GetOffsetOfBranch(instr, bits);
423 
424   if (imm == kEndOfChain) {
425     // EndOfChain sentinel is returned directly, not relative to pc or pos.
426     return kEndOfChain;
427   } else {
428     // Handle the case that next branch position is 0.
429     // TODO(LOONG_dev): Define -4 as a constant
430     int32_t offset = pos + imm;
431     return offset == 0 ? -4 : offset;
432   }
433 }
434 
target_at(int pos,bool is_internal)435 int Assembler::target_at(int pos, bool is_internal) {
436   if (is_internal) {
437     int64_t* p = reinterpret_cast<int64_t*>(buffer_start_ + pos);
438     int64_t address = *p;
439     if (address == kEndOfJumpChain) {
440       return kEndOfChain;
441     } else {
442       int64_t instr_address = reinterpret_cast<int64_t>(p);
443       DCHECK(instr_address - address < INT_MAX);
444       int delta = static_cast<int>(instr_address - address);
445       DCHECK(pos > delta);
446       return pos - delta;
447     }
448   }
449   Instr instr = instr_at(pos);
450 
451   // TODO(LOONG_dev) remove after remove label_at_put?
452   if ((instr & ~kImm16Mask) == 0) {
453     // Emitted label constant, not part of a branch.
454     if (instr == 0) {
455       return kEndOfChain;
456     } else {
457       int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
458       return (imm18 + pos);
459     }
460   }
461 
462   // Check we have a branch or jump instruction.
463   DCHECK(IsBranch(instr) || IsPcAddi(instr, t8, 16));
464   // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
465   // the compiler uses arithmetic shifts for signed integers.
466   if (IsBranch(instr)) {
467     return AddBranchOffset(pos, instr);
468   } else {
469     DCHECK(IsPcAddi(instr, t8, 16));
470     // see BranchLong(Label* L) and BranchAndLinkLong ??
471     int32_t imm32;
472     Instr instr_lu12i_w = instr_at(pos + 1 * kInstrSize);
473     Instr instr_ori = instr_at(pos + 2 * kInstrSize);
474     DCHECK(IsLu12i_w(instr_lu12i_w));
475     imm32 = ((instr_lu12i_w >> 5) & 0xfffff) << 12;
476     imm32 |= ((instr_ori >> 10) & static_cast<int32_t>(kImm12Mask));
477     if (imm32 == kEndOfJumpChain) {
478       // EndOfChain sentinel is returned directly, not relative to pc or pos.
479       return kEndOfChain;
480     }
481     return pos + imm32;
482   }
483 }
484 
SetBranchOffset(int32_t pos,int32_t target_pos,Instr instr)485 static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos,
486                                     Instr instr) {
487   int32_t bits = OffsetSizeInBits(instr);
488   int32_t imm = target_pos - pos;
489   DCHECK_EQ(imm & 3, 0);
490   imm >>= 2;
491 
492   DCHECK(is_intn(imm, bits));
493 
494   if (bits == 16) {
495     const int32_t mask = ((1 << 16) - 1) << 10;
496     instr &= ~mask;
497     return instr | ((imm << 10) & mask);
498   } else if (bits == 21) {
499     const int32_t mask = 0x3fffc1f;
500     instr &= ~mask;
501     uint32_t low16 = (imm & kImm16Mask) << 10;
502     int32_t hi5 = (imm >> 16) & 0x1f;
503     return instr | low16 | hi5;
504   } else {
505     DCHECK_EQ(bits, 26);
506     const int32_t mask = 0x3ffffff;
507     instr &= ~mask;
508     uint32_t low16 = (imm & kImm16Mask) << 10;
509     int32_t hi10 = (imm >> 16) & 0x3ff;
510     return instr | low16 | hi10;
511   }
512 }
513 
target_at_put(int pos,int target_pos,bool is_internal)514 void Assembler::target_at_put(int pos, int target_pos, bool is_internal) {
515   if (is_internal) {
516     uint64_t imm = reinterpret_cast<uint64_t>(buffer_start_) + target_pos;
517     *reinterpret_cast<uint64_t*>(buffer_start_ + pos) = imm;
518     return;
519   }
520   Instr instr = instr_at(pos);
521   if ((instr & ~kImm16Mask) == 0) {
522     DCHECK(target_pos == kEndOfChain || target_pos >= 0);
523     // Emitted label constant, not part of a branch.
524     // Make label relative to Code pointer of generated Code object.
525     instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
526     return;
527   }
528 
529   DCHECK(IsBranch(instr));
530   instr = SetBranchOffset(pos, target_pos, instr);
531   instr_at_put(pos, instr);
532 }
533 
print(const Label * L)534 void Assembler::print(const Label* L) {
535   if (L->is_unused()) {
536     PrintF("unused label\n");
537   } else if (L->is_bound()) {
538     PrintF("bound label to %d\n", L->pos());
539   } else if (L->is_linked()) {
540     Label l;
541     l.link_to(L->pos());
542     PrintF("unbound label");
543     while (l.is_linked()) {
544       PrintF("@ %d ", l.pos());
545       Instr instr = instr_at(l.pos());
546       if ((instr & ~kImm16Mask) == 0) {
547         PrintF("value\n");
548       } else {
549         PrintF("%d\n", instr);
550       }
551       next(&l, is_internal_reference(&l));
552     }
553   } else {
554     PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
555   }
556 }
557 
bind_to(Label * L,int pos)558 void Assembler::bind_to(Label* L, int pos) {
559   DCHECK(0 <= pos && pos <= pc_offset());  // Must have valid binding position.
560   int trampoline_pos = kInvalidSlotPos;
561   bool is_internal = false;
562   if (L->is_linked() && !trampoline_emitted_) {
563     unbound_labels_count_--;
564     if (!is_internal_reference(L)) {
565       next_buffer_check_ += kTrampolineSlotsSize;
566     }
567   }
568 
569   while (L->is_linked()) {
570     int fixup_pos = L->pos();
571     int dist = pos - fixup_pos;
572     is_internal = is_internal_reference(L);
573     next(L, is_internal);  // Call next before overwriting link with target at
574                            // fixup_pos.
575     Instr instr = instr_at(fixup_pos);
576     if (is_internal) {
577       target_at_put(fixup_pos, pos, is_internal);
578     } else {
579       if (IsBranch(instr)) {
580         int branch_offset = BranchOffset(instr);
581         if (dist > branch_offset) {
582           if (trampoline_pos == kInvalidSlotPos) {
583             trampoline_pos = get_trampoline_entry(fixup_pos);
584             CHECK_NE(trampoline_pos, kInvalidSlotPos);
585           }
586           CHECK((trampoline_pos - fixup_pos) <= branch_offset);
587           target_at_put(fixup_pos, trampoline_pos, false);
588           fixup_pos = trampoline_pos;
589         }
590         target_at_put(fixup_pos, pos, false);
591       } else {
592         DCHECK(IsJ(instr) || IsLu12i_w(instr) || IsEmittedConstant(instr) ||
593                IsPcAddi(instr, t8, 8));
594         target_at_put(fixup_pos, pos, false);
595       }
596     }
597   }
598   L->bind_to(pos);
599 
600   // Keep track of the last bound label so we don't eliminate any instructions
601   // before a bound label.
602   if (pos > last_bound_pos_) last_bound_pos_ = pos;
603 }
604 
bind(Label * L)605 void Assembler::bind(Label* L) {
606   DCHECK(!L->is_bound());  // Label can only be bound once.
607   bind_to(L, pc_offset());
608 }
609 
next(Label * L,bool is_internal)610 void Assembler::next(Label* L, bool is_internal) {
611   DCHECK(L->is_linked());
612   int link = target_at(L->pos(), is_internal);
613   if (link == kEndOfChain) {
614     L->Unuse();
615   } else if (link == -4) {
616     // Next position is pc_offset == 0
617     L->link_to(0);
618   } else {
619     DCHECK_GE(link, 0);
620     L->link_to(link);
621   }
622 }
623 
is_near_c(Label * L)624 bool Assembler::is_near_c(Label* L) {
625   DCHECK(L->is_bound());
626   return pc_offset() - L->pos() < kMax16BranchOffset - 4 * kInstrSize;
627 }
628 
is_near(Label * L,OffsetSize bits)629 bool Assembler::is_near(Label* L, OffsetSize bits) {
630   DCHECK(L->is_bound());
631   return ((pc_offset() - L->pos()) <
632           (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize);
633 }
634 
is_near_a(Label * L)635 bool Assembler::is_near_a(Label* L) {
636   DCHECK(L->is_bound());
637   return pc_offset() - L->pos() <= kMax26BranchOffset - 4 * kInstrSize;
638 }
639 
BranchOffset(Instr instr)640 int Assembler::BranchOffset(Instr instr) {
641   int bits = OffsetSize::kOffset16;
642 
643   uint32_t opcode = (instr >> 26) << 26;
644   switch (opcode) {
645     case B:
646     case BL:
647       bits = OffsetSize::kOffset26;
648       break;
649     case BNEZ:
650     case BEQZ:
651     case BCZ:
652       bits = OffsetSize::kOffset21;
653       break;
654     case BNE:
655     case BEQ:
656     case BLT:
657     case BGE:
658     case BLTU:
659     case BGEU:
660     case JIRL:
661       bits = OffsetSize::kOffset16;
662       break;
663     default:
664       break;
665   }
666 
667   return (1 << (bits + 2 - 1)) - 1;
668 }
669 
670 // We have to use a temporary register for things that can be relocated even
671 // if they can be encoded in the LOONG's 16 bits of immediate-offset
672 // instruction space. There is no guarantee that the relocated location can be
673 // similarly encoded.
MustUseReg(RelocInfo::Mode rmode)674 bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
675   return !RelocInfo::IsNoInfo(rmode);
676 }
677 
GenB(Opcode opcode,Register rj,int32_t si21)678 void Assembler::GenB(Opcode opcode, Register rj, int32_t si21) {
679   BlockTrampolinePoolScope block_trampoline_pool(this);
680   DCHECK((BEQZ == opcode || BNEZ == opcode) && is_int21(si21) && rj.is_valid());
681   Instr instr = opcode | (si21 & kImm16Mask) << kRkShift |
682                 (rj.code() << kRjShift) | ((si21 & 0x1fffff) >> 16);
683   emit(instr);
684 }
685 
GenB(Opcode opcode,CFRegister cj,int32_t si21,bool isEq)686 void Assembler::GenB(Opcode opcode, CFRegister cj, int32_t si21, bool isEq) {
687   BlockTrampolinePoolScope block_trampoline_pool(this);
688   DCHECK(BCZ == opcode && is_int21(si21));
689   DCHECK(cj >= 0 && cj <= 7);
690   int32_t sc = (isEq ? cj : cj + 8);
691   Instr instr = opcode | (si21 & kImm16Mask) << kRkShift | (sc << kRjShift) |
692                 ((si21 & 0x1fffff) >> 16);
693   emit(instr);
694 }
695 
GenB(Opcode opcode,int32_t si26)696 void Assembler::GenB(Opcode opcode, int32_t si26) {
697   BlockTrampolinePoolScope block_trampoline_pool(this);
698   DCHECK((B == opcode || BL == opcode) && is_int26(si26));
699   Instr instr =
700       opcode | ((si26 & kImm16Mask) << kRkShift) | ((si26 & kImm26Mask) >> 16);
701   emit(instr);
702 }
703 
GenBJ(Opcode opcode,Register rj,Register rd,int32_t si16)704 void Assembler::GenBJ(Opcode opcode, Register rj, Register rd, int32_t si16) {
705   BlockTrampolinePoolScope block_trampoline_pool(this);
706   DCHECK(is_int16(si16));
707   Instr instr = opcode | ((si16 & kImm16Mask) << kRkShift) |
708                 (rj.code() << kRjShift) | rd.code();
709   emit(instr);
710 }
711 
GenCmp(Opcode opcode,FPUCondition cond,FPURegister fk,FPURegister fj,CFRegister cd)712 void Assembler::GenCmp(Opcode opcode, FPUCondition cond, FPURegister fk,
713                        FPURegister fj, CFRegister cd) {
714   DCHECK(opcode == FCMP_COND_S || opcode == FCMP_COND_D);
715   Instr instr = opcode | cond << kCondShift | (fk.code() << kFkShift) |
716                 (fj.code() << kFjShift) | cd;
717   emit(instr);
718 }
719 
GenSel(Opcode opcode,CFRegister ca,FPURegister fk,FPURegister fj,FPURegister rd)720 void Assembler::GenSel(Opcode opcode, CFRegister ca, FPURegister fk,
721                        FPURegister fj, FPURegister rd) {
722   DCHECK((opcode == FSEL));
723   Instr instr = opcode | ca << kCondShift | (fk.code() << kFkShift) |
724                 (fj.code() << kFjShift) | rd.code();
725   emit(instr);
726 }
727 
GenRegister(Opcode opcode,Register rj,Register rd,bool rjrd)728 void Assembler::GenRegister(Opcode opcode, Register rj, Register rd,
729                             bool rjrd) {
730   DCHECK(rjrd);
731   Instr instr = 0;
732   instr = opcode | (rj.code() << kRjShift) | rd.code();
733   emit(instr);
734 }
735 
GenRegister(Opcode opcode,FPURegister fj,FPURegister fd)736 void Assembler::GenRegister(Opcode opcode, FPURegister fj, FPURegister fd) {
737   Instr instr = opcode | (fj.code() << kFjShift) | fd.code();
738   emit(instr);
739 }
740 
GenRegister(Opcode opcode,Register rj,FPURegister fd)741 void Assembler::GenRegister(Opcode opcode, Register rj, FPURegister fd) {
742   DCHECK((opcode == MOVGR2FR_W) || (opcode == MOVGR2FR_D) ||
743          (opcode == MOVGR2FRH_W));
744   Instr instr = opcode | (rj.code() << kRjShift) | fd.code();
745   emit(instr);
746 }
747 
GenRegister(Opcode opcode,FPURegister fj,Register rd)748 void Assembler::GenRegister(Opcode opcode, FPURegister fj, Register rd) {
749   DCHECK((opcode == MOVFR2GR_S) || (opcode == MOVFR2GR_D) ||
750          (opcode == MOVFRH2GR_S));
751   Instr instr = opcode | (fj.code() << kFjShift) | rd.code();
752   emit(instr);
753 }
754 
GenRegister(Opcode opcode,Register rj,FPUControlRegister fd)755 void Assembler::GenRegister(Opcode opcode, Register rj, FPUControlRegister fd) {
756   DCHECK((opcode == MOVGR2FCSR));
757   Instr instr = opcode | (rj.code() << kRjShift) | fd.code();
758   emit(instr);
759 }
760 
GenRegister(Opcode opcode,FPUControlRegister fj,Register rd)761 void Assembler::GenRegister(Opcode opcode, FPUControlRegister fj, Register rd) {
762   DCHECK((opcode == MOVFCSR2GR));
763   Instr instr = opcode | (fj.code() << kFjShift) | rd.code();
764   emit(instr);
765 }
766 
GenRegister(Opcode opcode,FPURegister fj,CFRegister cd)767 void Assembler::GenRegister(Opcode opcode, FPURegister fj, CFRegister cd) {
768   DCHECK((opcode == MOVFR2CF));
769   Instr instr = opcode | (fj.code() << kFjShift) | cd;
770   emit(instr);
771 }
772 
GenRegister(Opcode opcode,CFRegister cj,FPURegister fd)773 void Assembler::GenRegister(Opcode opcode, CFRegister cj, FPURegister fd) {
774   DCHECK((opcode == MOVCF2FR));
775   Instr instr = opcode | cj << kFjShift | fd.code();
776   emit(instr);
777 }
778 
GenRegister(Opcode opcode,Register rj,CFRegister cd)779 void Assembler::GenRegister(Opcode opcode, Register rj, CFRegister cd) {
780   DCHECK((opcode == MOVGR2CF));
781   Instr instr = opcode | (rj.code() << kRjShift) | cd;
782   emit(instr);
783 }
784 
GenRegister(Opcode opcode,CFRegister cj,Register rd)785 void Assembler::GenRegister(Opcode opcode, CFRegister cj, Register rd) {
786   DCHECK((opcode == MOVCF2GR));
787   Instr instr = opcode | cj << kFjShift | rd.code();
788   emit(instr);
789 }
790 
GenRegister(Opcode opcode,Register rk,Register rj,Register rd)791 void Assembler::GenRegister(Opcode opcode, Register rk, Register rj,
792                             Register rd) {
793   Instr instr =
794       opcode | (rk.code() << kRkShift) | (rj.code() << kRjShift) | rd.code();
795   emit(instr);
796 }
797 
GenRegister(Opcode opcode,FPURegister fk,FPURegister fj,FPURegister fd)798 void Assembler::GenRegister(Opcode opcode, FPURegister fk, FPURegister fj,
799                             FPURegister fd) {
800   Instr instr =
801       opcode | (fk.code() << kFkShift) | (fj.code() << kFjShift) | fd.code();
802   emit(instr);
803 }
804 
GenRegister(Opcode opcode,FPURegister fa,FPURegister fk,FPURegister fj,FPURegister fd)805 void Assembler::GenRegister(Opcode opcode, FPURegister fa, FPURegister fk,
806                             FPURegister fj, FPURegister fd) {
807   Instr instr = opcode | (fa.code() << kFaShift) | (fk.code() << kFkShift) |
808                 (fj.code() << kFjShift) | fd.code();
809   emit(instr);
810 }
811 
GenRegister(Opcode opcode,Register rk,Register rj,FPURegister fd)812 void Assembler::GenRegister(Opcode opcode, Register rk, Register rj,
813                             FPURegister fd) {
814   Instr instr =
815       opcode | (rk.code() << kRkShift) | (rj.code() << kRjShift) | fd.code();
816   emit(instr);
817 }
818 
GenImm(Opcode opcode,int32_t bit3,Register rk,Register rj,Register rd)819 void Assembler::GenImm(Opcode opcode, int32_t bit3, Register rk, Register rj,
820                        Register rd) {
821   DCHECK(is_uint3(bit3));
822   Instr instr = opcode | (bit3 & 0x7) << kSaShift | (rk.code() << kRkShift) |
823                 (rj.code() << kRjShift) | rd.code();
824   emit(instr);
825 }
826 
GenImm(Opcode opcode,int32_t bit6m,int32_t bit6l,Register rj,Register rd)827 void Assembler::GenImm(Opcode opcode, int32_t bit6m, int32_t bit6l, Register rj,
828                        Register rd) {
829   DCHECK(is_uint6(bit6m) && is_uint6(bit6l));
830   Instr instr = opcode | (bit6m & 0x3f) << 16 | (bit6l & 0x3f) << kRkShift |
831                 (rj.code() << kRjShift) | rd.code();
832   emit(instr);
833 }
834 
GenImm(Opcode opcode,int32_t bit20,Register rd)835 void Assembler::GenImm(Opcode opcode, int32_t bit20, Register rd) {
836   //  DCHECK(is_uint20(bit20) || is_int20(bit20));
837   Instr instr = opcode | (bit20 & 0xfffff) << kRjShift | rd.code();
838   emit(instr);
839 }
840 
GenImm(Opcode opcode,int32_t bit15)841 void Assembler::GenImm(Opcode opcode, int32_t bit15) {
842   DCHECK(is_uint15(bit15));
843   Instr instr = opcode | (bit15 & 0x7fff);
844   emit(instr);
845 }
846 
GenImm(Opcode opcode,int32_t value,Register rj,Register rd,int32_t value_bits)847 void Assembler::GenImm(Opcode opcode, int32_t value, Register rj, Register rd,
848                        int32_t value_bits) {
849   DCHECK(value_bits == 6 || value_bits == 12 || value_bits == 14 ||
850          value_bits == 16);
851   uint32_t imm = value & 0x3f;
852   if (value_bits == 12) {
853     imm = value & kImm12Mask;
854   } else if (value_bits == 14) {
855     imm = value & 0x3fff;
856   } else if (value_bits == 16) {
857     imm = value & kImm16Mask;
858   }
859   Instr instr = opcode | imm << kRkShift | (rj.code() << kRjShift) | rd.code();
860   emit(instr);
861 }
862 
GenImm(Opcode opcode,int32_t bit12,Register rj,FPURegister fd)863 void Assembler::GenImm(Opcode opcode, int32_t bit12, Register rj,
864                        FPURegister fd) {
865   DCHECK(is_int12(bit12));
866   Instr instr = opcode | ((bit12 & kImm12Mask) << kRkShift) |
867                 (rj.code() << kRjShift) | fd.code();
868   emit(instr);
869 }
870 
871 // Returns the next free trampoline entry.
get_trampoline_entry(int32_t pos)872 int32_t Assembler::get_trampoline_entry(int32_t pos) {
873   int32_t trampoline_entry = kInvalidSlotPos;
874   if (!internal_trampoline_exception_) {
875     if (trampoline_.start() > pos) {
876       trampoline_entry = trampoline_.take_slot();
877     }
878 
879     if (kInvalidSlotPos == trampoline_entry) {
880       internal_trampoline_exception_ = true;
881     }
882   }
883   return trampoline_entry;
884 }
885 
jump_address(Label * L)886 uint64_t Assembler::jump_address(Label* L) {
887   int64_t target_pos;
888   if (L->is_bound()) {
889     target_pos = L->pos();
890   } else {
891     if (L->is_linked()) {
892       target_pos = L->pos();  // L's link.
893       L->link_to(pc_offset());
894     } else {
895       L->link_to(pc_offset());
896       return kEndOfJumpChain;
897     }
898   }
899   uint64_t imm = reinterpret_cast<uint64_t>(buffer_start_) + target_pos;
900   DCHECK_EQ(imm & 3, 0);
901 
902   return imm;
903 }
904 
branch_long_offset(Label * L)905 uint64_t Assembler::branch_long_offset(Label* L) {
906   int64_t target_pos;
907 
908   if (L->is_bound()) {
909     target_pos = L->pos();
910   } else {
911     if (L->is_linked()) {
912       target_pos = L->pos();  // L's link.
913       L->link_to(pc_offset());
914     } else {
915       L->link_to(pc_offset());
916       return kEndOfJumpChain;
917     }
918   }
919   int64_t offset = target_pos - pc_offset();
920   DCHECK_EQ(offset & 3, 0);
921 
922   return static_cast<uint64_t>(offset);
923 }
924 
branch_offset_helper(Label * L,OffsetSize bits)925 int32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) {
926   int32_t target_pos;
927 
928   if (L->is_bound()) {
929     target_pos = L->pos();
930   } else {
931     if (L->is_linked()) {
932       target_pos = L->pos();
933       L->link_to(pc_offset());
934     } else {
935       L->link_to(pc_offset());
936       if (!trampoline_emitted_) {
937         unbound_labels_count_++;
938         next_buffer_check_ -= kTrampolineSlotsSize;
939       }
940       return kEndOfChain;
941     }
942   }
943 
944   int32_t offset = target_pos - pc_offset();
945   DCHECK(is_intn(offset, bits + 2));
946   DCHECK_EQ(offset & 3, 0);
947 
948   return offset;
949 }
950 
label_at_put(Label * L,int at_offset)951 void Assembler::label_at_put(Label* L, int at_offset) {
952   int target_pos;
953   if (L->is_bound()) {
954     target_pos = L->pos();
955     instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
956   } else {
957     if (L->is_linked()) {
958       target_pos = L->pos();  // L's link.
959       int32_t imm18 = target_pos - at_offset;
960       DCHECK_EQ(imm18 & 3, 0);
961       int32_t imm16 = imm18 >> 2;
962       DCHECK(is_int16(imm16));
963       instr_at_put(at_offset, (imm16 & kImm16Mask));
964     } else {
965       target_pos = kEndOfChain;
966       instr_at_put(at_offset, 0);
967       if (!trampoline_emitted_) {
968         unbound_labels_count_++;
969         next_buffer_check_ -= kTrampolineSlotsSize;
970       }
971     }
972     L->link_to(at_offset);
973   }
974 }
975 
976 //------- Branch and jump instructions --------
977 
b(int32_t offset)978 void Assembler::b(int32_t offset) { GenB(B, offset); }
979 
bl(int32_t offset)980 void Assembler::bl(int32_t offset) { GenB(BL, offset); }
981 
beq(Register rj,Register rd,int32_t offset)982 void Assembler::beq(Register rj, Register rd, int32_t offset) {
983   GenBJ(BEQ, rj, rd, offset);
984 }
985 
bne(Register rj,Register rd,int32_t offset)986 void Assembler::bne(Register rj, Register rd, int32_t offset) {
987   GenBJ(BNE, rj, rd, offset);
988 }
989 
blt(Register rj,Register rd,int32_t offset)990 void Assembler::blt(Register rj, Register rd, int32_t offset) {
991   GenBJ(BLT, rj, rd, offset);
992 }
993 
bge(Register rj,Register rd,int32_t offset)994 void Assembler::bge(Register rj, Register rd, int32_t offset) {
995   GenBJ(BGE, rj, rd, offset);
996 }
997 
bltu(Register rj,Register rd,int32_t offset)998 void Assembler::bltu(Register rj, Register rd, int32_t offset) {
999   GenBJ(BLTU, rj, rd, offset);
1000 }
1001 
bgeu(Register rj,Register rd,int32_t offset)1002 void Assembler::bgeu(Register rj, Register rd, int32_t offset) {
1003   GenBJ(BGEU, rj, rd, offset);
1004 }
1005 
beqz(Register rj,int32_t offset)1006 void Assembler::beqz(Register rj, int32_t offset) { GenB(BEQZ, rj, offset); }
bnez(Register rj,int32_t offset)1007 void Assembler::bnez(Register rj, int32_t offset) { GenB(BNEZ, rj, offset); }
1008 
jirl(Register rd,Register rj,int32_t offset)1009 void Assembler::jirl(Register rd, Register rj, int32_t offset) {
1010   GenBJ(JIRL, rj, rd, offset);
1011 }
1012 
bceqz(CFRegister cj,int32_t si21)1013 void Assembler::bceqz(CFRegister cj, int32_t si21) {
1014   GenB(BCZ, cj, si21, true);
1015 }
1016 
bcnez(CFRegister cj,int32_t si21)1017 void Assembler::bcnez(CFRegister cj, int32_t si21) {
1018   GenB(BCZ, cj, si21, false);
1019 }
1020 
1021 // -------Data-processing-instructions---------
1022 
1023 // Arithmetic.
add_w(Register rd,Register rj,Register rk)1024 void Assembler::add_w(Register rd, Register rj, Register rk) {
1025   GenRegister(ADD_W, rk, rj, rd);
1026 }
1027 
add_d(Register rd,Register rj,Register rk)1028 void Assembler::add_d(Register rd, Register rj, Register rk) {
1029   GenRegister(ADD_D, rk, rj, rd);
1030 }
1031 
sub_w(Register rd,Register rj,Register rk)1032 void Assembler::sub_w(Register rd, Register rj, Register rk) {
1033   GenRegister(SUB_W, rk, rj, rd);
1034 }
1035 
sub_d(Register rd,Register rj,Register rk)1036 void Assembler::sub_d(Register rd, Register rj, Register rk) {
1037   GenRegister(SUB_D, rk, rj, rd);
1038 }
1039 
addi_w(Register rd,Register rj,int32_t si12)1040 void Assembler::addi_w(Register rd, Register rj, int32_t si12) {
1041   GenImm(ADDI_W, si12, rj, rd, 12);
1042 }
1043 
addi_d(Register rd,Register rj,int32_t si12)1044 void Assembler::addi_d(Register rd, Register rj, int32_t si12) {
1045   GenImm(ADDI_D, si12, rj, rd, 12);
1046 }
1047 
addu16i_d(Register rd,Register rj,int32_t si16)1048 void Assembler::addu16i_d(Register rd, Register rj, int32_t si16) {
1049   GenImm(ADDU16I_D, si16, rj, rd, 16);
1050 }
1051 
alsl_w(Register rd,Register rj,Register rk,int32_t sa2)1052 void Assembler::alsl_w(Register rd, Register rj, Register rk, int32_t sa2) {
1053   DCHECK(is_uint2(sa2 - 1));
1054   GenImm(ALSL_W, sa2 - 1, rk, rj, rd);
1055 }
1056 
alsl_wu(Register rd,Register rj,Register rk,int32_t sa2)1057 void Assembler::alsl_wu(Register rd, Register rj, Register rk, int32_t sa2) {
1058   DCHECK(is_uint2(sa2 - 1));
1059   GenImm(ALSL_WU, sa2 + 3, rk, rj, rd);
1060 }
1061 
alsl_d(Register rd,Register rj,Register rk,int32_t sa2)1062 void Assembler::alsl_d(Register rd, Register rj, Register rk, int32_t sa2) {
1063   DCHECK(is_uint2(sa2 - 1));
1064   GenImm(ALSL_D, sa2 - 1, rk, rj, rd);
1065 }
1066 
lu12i_w(Register rd,int32_t si20)1067 void Assembler::lu12i_w(Register rd, int32_t si20) {
1068   GenImm(LU12I_W, si20, rd);
1069 }
1070 
lu32i_d(Register rd,int32_t si20)1071 void Assembler::lu32i_d(Register rd, int32_t si20) {
1072   GenImm(LU32I_D, si20, rd);
1073 }
1074 
lu52i_d(Register rd,Register rj,int32_t si12)1075 void Assembler::lu52i_d(Register rd, Register rj, int32_t si12) {
1076   GenImm(LU52I_D, si12, rj, rd, 12);
1077 }
1078 
slt(Register rd,Register rj,Register rk)1079 void Assembler::slt(Register rd, Register rj, Register rk) {
1080   GenRegister(SLT, rk, rj, rd);
1081 }
1082 
sltu(Register rd,Register rj,Register rk)1083 void Assembler::sltu(Register rd, Register rj, Register rk) {
1084   GenRegister(SLTU, rk, rj, rd);
1085 }
1086 
slti(Register rd,Register rj,int32_t si12)1087 void Assembler::slti(Register rd, Register rj, int32_t si12) {
1088   GenImm(SLTI, si12, rj, rd, 12);
1089 }
1090 
sltui(Register rd,Register rj,int32_t si12)1091 void Assembler::sltui(Register rd, Register rj, int32_t si12) {
1092   GenImm(SLTUI, si12, rj, rd, 12);
1093 }
1094 
pcaddi(Register rd,int32_t si20)1095 void Assembler::pcaddi(Register rd, int32_t si20) { GenImm(PCADDI, si20, rd); }
1096 
pcaddu12i(Register rd,int32_t si20)1097 void Assembler::pcaddu12i(Register rd, int32_t si20) {
1098   GenImm(PCADDU12I, si20, rd);
1099 }
1100 
pcaddu18i(Register rd,int32_t si20)1101 void Assembler::pcaddu18i(Register rd, int32_t si20) {
1102   GenImm(PCADDU18I, si20, rd);
1103 }
1104 
pcalau12i(Register rd,int32_t si20)1105 void Assembler::pcalau12i(Register rd, int32_t si20) {
1106   GenImm(PCALAU12I, si20, rd);
1107 }
1108 
and_(Register rd,Register rj,Register rk)1109 void Assembler::and_(Register rd, Register rj, Register rk) {
1110   GenRegister(AND, rk, rj, rd);
1111 }
1112 
or_(Register rd,Register rj,Register rk)1113 void Assembler::or_(Register rd, Register rj, Register rk) {
1114   GenRegister(OR, rk, rj, rd);
1115 }
1116 
xor_(Register rd,Register rj,Register rk)1117 void Assembler::xor_(Register rd, Register rj, Register rk) {
1118   GenRegister(XOR, rk, rj, rd);
1119 }
1120 
nor(Register rd,Register rj,Register rk)1121 void Assembler::nor(Register rd, Register rj, Register rk) {
1122   GenRegister(NOR, rk, rj, rd);
1123 }
1124 
andn(Register rd,Register rj,Register rk)1125 void Assembler::andn(Register rd, Register rj, Register rk) {
1126   GenRegister(ANDN, rk, rj, rd);
1127 }
1128 
orn(Register rd,Register rj,Register rk)1129 void Assembler::orn(Register rd, Register rj, Register rk) {
1130   GenRegister(ORN, rk, rj, rd);
1131 }
1132 
andi(Register rd,Register rj,int32_t ui12)1133 void Assembler::andi(Register rd, Register rj, int32_t ui12) {
1134   GenImm(ANDI, ui12, rj, rd, 12);
1135 }
1136 
ori(Register rd,Register rj,int32_t ui12)1137 void Assembler::ori(Register rd, Register rj, int32_t ui12) {
1138   GenImm(ORI, ui12, rj, rd, 12);
1139 }
1140 
xori(Register rd,Register rj,int32_t ui12)1141 void Assembler::xori(Register rd, Register rj, int32_t ui12) {
1142   GenImm(XORI, ui12, rj, rd, 12);
1143 }
1144 
mul_w(Register rd,Register rj,Register rk)1145 void Assembler::mul_w(Register rd, Register rj, Register rk) {
1146   GenRegister(MUL_W, rk, rj, rd);
1147 }
1148 
mulh_w(Register rd,Register rj,Register rk)1149 void Assembler::mulh_w(Register rd, Register rj, Register rk) {
1150   GenRegister(MULH_W, rk, rj, rd);
1151 }
1152 
mulh_wu(Register rd,Register rj,Register rk)1153 void Assembler::mulh_wu(Register rd, Register rj, Register rk) {
1154   GenRegister(MULH_WU, rk, rj, rd);
1155 }
1156 
mul_d(Register rd,Register rj,Register rk)1157 void Assembler::mul_d(Register rd, Register rj, Register rk) {
1158   GenRegister(MUL_D, rk, rj, rd);
1159 }
1160 
mulh_d(Register rd,Register rj,Register rk)1161 void Assembler::mulh_d(Register rd, Register rj, Register rk) {
1162   GenRegister(MULH_D, rk, rj, rd);
1163 }
1164 
mulh_du(Register rd,Register rj,Register rk)1165 void Assembler::mulh_du(Register rd, Register rj, Register rk) {
1166   GenRegister(MULH_DU, rk, rj, rd);
1167 }
1168 
mulw_d_w(Register rd,Register rj,Register rk)1169 void Assembler::mulw_d_w(Register rd, Register rj, Register rk) {
1170   GenRegister(MULW_D_W, rk, rj, rd);
1171 }
1172 
mulw_d_wu(Register rd,Register rj,Register rk)1173 void Assembler::mulw_d_wu(Register rd, Register rj, Register rk) {
1174   GenRegister(MULW_D_WU, rk, rj, rd);
1175 }
1176 
div_w(Register rd,Register rj,Register rk)1177 void Assembler::div_w(Register rd, Register rj, Register rk) {
1178   GenRegister(DIV_W, rk, rj, rd);
1179 }
1180 
mod_w(Register rd,Register rj,Register rk)1181 void Assembler::mod_w(Register rd, Register rj, Register rk) {
1182   GenRegister(MOD_W, rk, rj, rd);
1183 }
1184 
div_wu(Register rd,Register rj,Register rk)1185 void Assembler::div_wu(Register rd, Register rj, Register rk) {
1186   GenRegister(DIV_WU, rk, rj, rd);
1187 }
1188 
mod_wu(Register rd,Register rj,Register rk)1189 void Assembler::mod_wu(Register rd, Register rj, Register rk) {
1190   GenRegister(MOD_WU, rk, rj, rd);
1191 }
1192 
div_d(Register rd,Register rj,Register rk)1193 void Assembler::div_d(Register rd, Register rj, Register rk) {
1194   GenRegister(DIV_D, rk, rj, rd);
1195 }
1196 
mod_d(Register rd,Register rj,Register rk)1197 void Assembler::mod_d(Register rd, Register rj, Register rk) {
1198   GenRegister(MOD_D, rk, rj, rd);
1199 }
1200 
div_du(Register rd,Register rj,Register rk)1201 void Assembler::div_du(Register rd, Register rj, Register rk) {
1202   GenRegister(DIV_DU, rk, rj, rd);
1203 }
1204 
mod_du(Register rd,Register rj,Register rk)1205 void Assembler::mod_du(Register rd, Register rj, Register rk) {
1206   GenRegister(MOD_DU, rk, rj, rd);
1207 }
1208 
1209 // Shifts.
sll_w(Register rd,Register rj,Register rk)1210 void Assembler::sll_w(Register rd, Register rj, Register rk) {
1211   GenRegister(SLL_W, rk, rj, rd);
1212 }
1213 
srl_w(Register rd,Register rj,Register rk)1214 void Assembler::srl_w(Register rd, Register rj, Register rk) {
1215   GenRegister(SRL_W, rk, rj, rd);
1216 }
1217 
sra_w(Register rd,Register rj,Register rk)1218 void Assembler::sra_w(Register rd, Register rj, Register rk) {
1219   GenRegister(SRA_W, rk, rj, rd);
1220 }
1221 
rotr_w(Register rd,Register rj,Register rk)1222 void Assembler::rotr_w(Register rd, Register rj, Register rk) {
1223   GenRegister(ROTR_W, rk, rj, rd);
1224 }
1225 
slli_w(Register rd,Register rj,int32_t ui5)1226 void Assembler::slli_w(Register rd, Register rj, int32_t ui5) {
1227   DCHECK(is_uint5(ui5));
1228   GenImm(SLLI_W, ui5 + 0x20, rj, rd, 6);
1229 }
1230 
srli_w(Register rd,Register rj,int32_t ui5)1231 void Assembler::srli_w(Register rd, Register rj, int32_t ui5) {
1232   DCHECK(is_uint5(ui5));
1233   GenImm(SRLI_W, ui5 + 0x20, rj, rd, 6);
1234 }
1235 
srai_w(Register rd,Register rj,int32_t ui5)1236 void Assembler::srai_w(Register rd, Register rj, int32_t ui5) {
1237   DCHECK(is_uint5(ui5));
1238   GenImm(SRAI_W, ui5 + 0x20, rj, rd, 6);
1239 }
1240 
rotri_w(Register rd,Register rj,int32_t ui5)1241 void Assembler::rotri_w(Register rd, Register rj, int32_t ui5) {
1242   DCHECK(is_uint5(ui5));
1243   GenImm(ROTRI_W, ui5 + 0x20, rj, rd, 6);
1244 }
1245 
sll_d(Register rd,Register rj,Register rk)1246 void Assembler::sll_d(Register rd, Register rj, Register rk) {
1247   GenRegister(SLL_D, rk, rj, rd);
1248 }
1249 
srl_d(Register rd,Register rj,Register rk)1250 void Assembler::srl_d(Register rd, Register rj, Register rk) {
1251   GenRegister(SRL_D, rk, rj, rd);
1252 }
1253 
sra_d(Register rd,Register rj,Register rk)1254 void Assembler::sra_d(Register rd, Register rj, Register rk) {
1255   GenRegister(SRA_D, rk, rj, rd);
1256 }
1257 
rotr_d(Register rd,Register rj,Register rk)1258 void Assembler::rotr_d(Register rd, Register rj, Register rk) {
1259   GenRegister(ROTR_D, rk, rj, rd);
1260 }
1261 
slli_d(Register rd,Register rj,int32_t ui6)1262 void Assembler::slli_d(Register rd, Register rj, int32_t ui6) {
1263   GenImm(SLLI_D, ui6, rj, rd, 6);
1264 }
1265 
srli_d(Register rd,Register rj,int32_t ui6)1266 void Assembler::srli_d(Register rd, Register rj, int32_t ui6) {
1267   GenImm(SRLI_D, ui6, rj, rd, 6);
1268 }
1269 
srai_d(Register rd,Register rj,int32_t ui6)1270 void Assembler::srai_d(Register rd, Register rj, int32_t ui6) {
1271   GenImm(SRAI_D, ui6, rj, rd, 6);
1272 }
1273 
rotri_d(Register rd,Register rj,int32_t ui6)1274 void Assembler::rotri_d(Register rd, Register rj, int32_t ui6) {
1275   GenImm(ROTRI_D, ui6, rj, rd, 6);
1276 }
1277 
1278 // Bit twiddling.
ext_w_b(Register rd,Register rj)1279 void Assembler::ext_w_b(Register rd, Register rj) {
1280   GenRegister(EXT_W_B, rj, rd);
1281 }
1282 
ext_w_h(Register rd,Register rj)1283 void Assembler::ext_w_h(Register rd, Register rj) {
1284   GenRegister(EXT_W_H, rj, rd);
1285 }
1286 
clo_w(Register rd,Register rj)1287 void Assembler::clo_w(Register rd, Register rj) { GenRegister(CLO_W, rj, rd); }
1288 
clz_w(Register rd,Register rj)1289 void Assembler::clz_w(Register rd, Register rj) { GenRegister(CLZ_W, rj, rd); }
1290 
cto_w(Register rd,Register rj)1291 void Assembler::cto_w(Register rd, Register rj) { GenRegister(CTO_W, rj, rd); }
1292 
ctz_w(Register rd,Register rj)1293 void Assembler::ctz_w(Register rd, Register rj) { GenRegister(CTZ_W, rj, rd); }
1294 
clo_d(Register rd,Register rj)1295 void Assembler::clo_d(Register rd, Register rj) { GenRegister(CLO_D, rj, rd); }
1296 
clz_d(Register rd,Register rj)1297 void Assembler::clz_d(Register rd, Register rj) { GenRegister(CLZ_D, rj, rd); }
1298 
cto_d(Register rd,Register rj)1299 void Assembler::cto_d(Register rd, Register rj) { GenRegister(CTO_D, rj, rd); }
1300 
ctz_d(Register rd,Register rj)1301 void Assembler::ctz_d(Register rd, Register rj) { GenRegister(CTZ_D, rj, rd); }
1302 
bytepick_w(Register rd,Register rj,Register rk,int32_t sa2)1303 void Assembler::bytepick_w(Register rd, Register rj, Register rk, int32_t sa2) {
1304   DCHECK(is_uint2(sa2));
1305   GenImm(BYTEPICK_W, sa2, rk, rj, rd);
1306 }
1307 
bytepick_d(Register rd,Register rj,Register rk,int32_t sa3)1308 void Assembler::bytepick_d(Register rd, Register rj, Register rk, int32_t sa3) {
1309   GenImm(BYTEPICK_D, sa3, rk, rj, rd);
1310 }
1311 
revb_2h(Register rd,Register rj)1312 void Assembler::revb_2h(Register rd, Register rj) {
1313   GenRegister(REVB_2H, rj, rd);
1314 }
1315 
revb_4h(Register rd,Register rj)1316 void Assembler::revb_4h(Register rd, Register rj) {
1317   GenRegister(REVB_4H, rj, rd);
1318 }
1319 
revb_2w(Register rd,Register rj)1320 void Assembler::revb_2w(Register rd, Register rj) {
1321   GenRegister(REVB_2W, rj, rd);
1322 }
1323 
revb_d(Register rd,Register rj)1324 void Assembler::revb_d(Register rd, Register rj) {
1325   GenRegister(REVB_D, rj, rd);
1326 }
1327 
revh_2w(Register rd,Register rj)1328 void Assembler::revh_2w(Register rd, Register rj) {
1329   GenRegister(REVH_2W, rj, rd);
1330 }
1331 
revh_d(Register rd,Register rj)1332 void Assembler::revh_d(Register rd, Register rj) {
1333   GenRegister(REVH_D, rj, rd);
1334 }
1335 
bitrev_4b(Register rd,Register rj)1336 void Assembler::bitrev_4b(Register rd, Register rj) {
1337   GenRegister(BITREV_4B, rj, rd);
1338 }
1339 
bitrev_8b(Register rd,Register rj)1340 void Assembler::bitrev_8b(Register rd, Register rj) {
1341   GenRegister(BITREV_8B, rj, rd);
1342 }
1343 
bitrev_w(Register rd,Register rj)1344 void Assembler::bitrev_w(Register rd, Register rj) {
1345   GenRegister(BITREV_W, rj, rd);
1346 }
1347 
bitrev_d(Register rd,Register rj)1348 void Assembler::bitrev_d(Register rd, Register rj) {
1349   GenRegister(BITREV_D, rj, rd);
1350 }
1351 
bstrins_w(Register rd,Register rj,int32_t msbw,int32_t lsbw)1352 void Assembler::bstrins_w(Register rd, Register rj, int32_t msbw,
1353                           int32_t lsbw) {
1354   DCHECK(is_uint5(msbw) && is_uint5(lsbw));
1355   GenImm(BSTR_W, msbw + 0x20, lsbw, rj, rd);
1356 }
1357 
bstrins_d(Register rd,Register rj,int32_t msbd,int32_t lsbd)1358 void Assembler::bstrins_d(Register rd, Register rj, int32_t msbd,
1359                           int32_t lsbd) {
1360   GenImm(BSTRINS_D, msbd, lsbd, rj, rd);
1361 }
1362 
bstrpick_w(Register rd,Register rj,int32_t msbw,int32_t lsbw)1363 void Assembler::bstrpick_w(Register rd, Register rj, int32_t msbw,
1364                            int32_t lsbw) {
1365   DCHECK(is_uint5(msbw) && is_uint5(lsbw));
1366   GenImm(BSTR_W, msbw + 0x20, lsbw + 0x20, rj, rd);
1367 }
1368 
bstrpick_d(Register rd,Register rj,int32_t msbd,int32_t lsbd)1369 void Assembler::bstrpick_d(Register rd, Register rj, int32_t msbd,
1370                            int32_t lsbd) {
1371   GenImm(BSTRPICK_D, msbd, lsbd, rj, rd);
1372 }
1373 
maskeqz(Register rd,Register rj,Register rk)1374 void Assembler::maskeqz(Register rd, Register rj, Register rk) {
1375   GenRegister(MASKEQZ, rk, rj, rd);
1376 }
1377 
masknez(Register rd,Register rj,Register rk)1378 void Assembler::masknez(Register rd, Register rj, Register rk) {
1379   GenRegister(MASKNEZ, rk, rj, rd);
1380 }
1381 
1382 // Memory-instructions
ld_b(Register rd,Register rj,int32_t si12)1383 void Assembler::ld_b(Register rd, Register rj, int32_t si12) {
1384   GenImm(LD_B, si12, rj, rd, 12);
1385 }
1386 
ld_h(Register rd,Register rj,int32_t si12)1387 void Assembler::ld_h(Register rd, Register rj, int32_t si12) {
1388   GenImm(LD_H, si12, rj, rd, 12);
1389 }
1390 
ld_w(Register rd,Register rj,int32_t si12)1391 void Assembler::ld_w(Register rd, Register rj, int32_t si12) {
1392   GenImm(LD_W, si12, rj, rd, 12);
1393 }
1394 
ld_d(Register rd,Register rj,int32_t si12)1395 void Assembler::ld_d(Register rd, Register rj, int32_t si12) {
1396   GenImm(LD_D, si12, rj, rd, 12);
1397 }
1398 
ld_bu(Register rd,Register rj,int32_t si12)1399 void Assembler::ld_bu(Register rd, Register rj, int32_t si12) {
1400   GenImm(LD_BU, si12, rj, rd, 12);
1401 }
1402 
ld_hu(Register rd,Register rj,int32_t si12)1403 void Assembler::ld_hu(Register rd, Register rj, int32_t si12) {
1404   GenImm(LD_HU, si12, rj, rd, 12);
1405 }
1406 
ld_wu(Register rd,Register rj,int32_t si12)1407 void Assembler::ld_wu(Register rd, Register rj, int32_t si12) {
1408   GenImm(LD_WU, si12, rj, rd, 12);
1409 }
1410 
st_b(Register rd,Register rj,int32_t si12)1411 void Assembler::st_b(Register rd, Register rj, int32_t si12) {
1412   GenImm(ST_B, si12, rj, rd, 12);
1413 }
1414 
st_h(Register rd,Register rj,int32_t si12)1415 void Assembler::st_h(Register rd, Register rj, int32_t si12) {
1416   GenImm(ST_H, si12, rj, rd, 12);
1417 }
1418 
st_w(Register rd,Register rj,int32_t si12)1419 void Assembler::st_w(Register rd, Register rj, int32_t si12) {
1420   GenImm(ST_W, si12, rj, rd, 12);
1421 }
1422 
st_d(Register rd,Register rj,int32_t si12)1423 void Assembler::st_d(Register rd, Register rj, int32_t si12) {
1424   GenImm(ST_D, si12, rj, rd, 12);
1425 }
1426 
ldx_b(Register rd,Register rj,Register rk)1427 void Assembler::ldx_b(Register rd, Register rj, Register rk) {
1428   GenRegister(LDX_B, rk, rj, rd);
1429 }
1430 
ldx_h(Register rd,Register rj,Register rk)1431 void Assembler::ldx_h(Register rd, Register rj, Register rk) {
1432   GenRegister(LDX_H, rk, rj, rd);
1433 }
1434 
ldx_w(Register rd,Register rj,Register rk)1435 void Assembler::ldx_w(Register rd, Register rj, Register rk) {
1436   GenRegister(LDX_W, rk, rj, rd);
1437 }
1438 
ldx_d(Register rd,Register rj,Register rk)1439 void Assembler::ldx_d(Register rd, Register rj, Register rk) {
1440   GenRegister(LDX_D, rk, rj, rd);
1441 }
1442 
ldx_bu(Register rd,Register rj,Register rk)1443 void Assembler::ldx_bu(Register rd, Register rj, Register rk) {
1444   GenRegister(LDX_BU, rk, rj, rd);
1445 }
1446 
ldx_hu(Register rd,Register rj,Register rk)1447 void Assembler::ldx_hu(Register rd, Register rj, Register rk) {
1448   GenRegister(LDX_HU, rk, rj, rd);
1449 }
1450 
ldx_wu(Register rd,Register rj,Register rk)1451 void Assembler::ldx_wu(Register rd, Register rj, Register rk) {
1452   GenRegister(LDX_WU, rk, rj, rd);
1453 }
1454 
stx_b(Register rd,Register rj,Register rk)1455 void Assembler::stx_b(Register rd, Register rj, Register rk) {
1456   GenRegister(STX_B, rk, rj, rd);
1457 }
1458 
stx_h(Register rd,Register rj,Register rk)1459 void Assembler::stx_h(Register rd, Register rj, Register rk) {
1460   GenRegister(STX_H, rk, rj, rd);
1461 }
1462 
stx_w(Register rd,Register rj,Register rk)1463 void Assembler::stx_w(Register rd, Register rj, Register rk) {
1464   GenRegister(STX_W, rk, rj, rd);
1465 }
1466 
stx_d(Register rd,Register rj,Register rk)1467 void Assembler::stx_d(Register rd, Register rj, Register rk) {
1468   GenRegister(STX_D, rk, rj, rd);
1469 }
1470 
ldptr_w(Register rd,Register rj,int32_t si14)1471 void Assembler::ldptr_w(Register rd, Register rj, int32_t si14) {
1472   DCHECK(is_int16(si14) && ((si14 & 0x3) == 0));
1473   GenImm(LDPTR_W, si14 >> 2, rj, rd, 14);
1474 }
1475 
ldptr_d(Register rd,Register rj,int32_t si14)1476 void Assembler::ldptr_d(Register rd, Register rj, int32_t si14) {
1477   DCHECK(is_int16(si14) && ((si14 & 0x3) == 0));
1478   GenImm(LDPTR_D, si14 >> 2, rj, rd, 14);
1479 }
1480 
stptr_w(Register rd,Register rj,int32_t si14)1481 void Assembler::stptr_w(Register rd, Register rj, int32_t si14) {
1482   DCHECK(is_int16(si14) && ((si14 & 0x3) == 0));
1483   GenImm(STPTR_W, si14 >> 2, rj, rd, 14);
1484 }
1485 
stptr_d(Register rd,Register rj,int32_t si14)1486 void Assembler::stptr_d(Register rd, Register rj, int32_t si14) {
1487   DCHECK(is_int16(si14) && ((si14 & 0x3) == 0));
1488   GenImm(STPTR_D, si14 >> 2, rj, rd, 14);
1489 }
1490 
amswap_w(Register rd,Register rk,Register rj)1491 void Assembler::amswap_w(Register rd, Register rk, Register rj) {
1492   GenRegister(AMSWAP_W, rk, rj, rd);
1493 }
1494 
amswap_d(Register rd,Register rk,Register rj)1495 void Assembler::amswap_d(Register rd, Register rk, Register rj) {
1496   GenRegister(AMSWAP_D, rk, rj, rd);
1497 }
1498 
amadd_w(Register rd,Register rk,Register rj)1499 void Assembler::amadd_w(Register rd, Register rk, Register rj) {
1500   GenRegister(AMADD_W, rk, rj, rd);
1501 }
1502 
amadd_d(Register rd,Register rk,Register rj)1503 void Assembler::amadd_d(Register rd, Register rk, Register rj) {
1504   GenRegister(AMADD_D, rk, rj, rd);
1505 }
1506 
amand_w(Register rd,Register rk,Register rj)1507 void Assembler::amand_w(Register rd, Register rk, Register rj) {
1508   GenRegister(AMAND_W, rk, rj, rd);
1509 }
1510 
amand_d(Register rd,Register rk,Register rj)1511 void Assembler::amand_d(Register rd, Register rk, Register rj) {
1512   GenRegister(AMAND_D, rk, rj, rd);
1513 }
1514 
amor_w(Register rd,Register rk,Register rj)1515 void Assembler::amor_w(Register rd, Register rk, Register rj) {
1516   GenRegister(AMOR_W, rk, rj, rd);
1517 }
1518 
amor_d(Register rd,Register rk,Register rj)1519 void Assembler::amor_d(Register rd, Register rk, Register rj) {
1520   GenRegister(AMOR_D, rk, rj, rd);
1521 }
1522 
amxor_w(Register rd,Register rk,Register rj)1523 void Assembler::amxor_w(Register rd, Register rk, Register rj) {
1524   GenRegister(AMXOR_W, rk, rj, rd);
1525 }
1526 
amxor_d(Register rd,Register rk,Register rj)1527 void Assembler::amxor_d(Register rd, Register rk, Register rj) {
1528   GenRegister(AMXOR_D, rk, rj, rd);
1529 }
1530 
ammax_w(Register rd,Register rk,Register rj)1531 void Assembler::ammax_w(Register rd, Register rk, Register rj) {
1532   GenRegister(AMMAX_W, rk, rj, rd);
1533 }
1534 
ammax_d(Register rd,Register rk,Register rj)1535 void Assembler::ammax_d(Register rd, Register rk, Register rj) {
1536   GenRegister(AMMAX_D, rk, rj, rd);
1537 }
1538 
ammin_w(Register rd,Register rk,Register rj)1539 void Assembler::ammin_w(Register rd, Register rk, Register rj) {
1540   GenRegister(AMMIN_W, rk, rj, rd);
1541 }
1542 
ammin_d(Register rd,Register rk,Register rj)1543 void Assembler::ammin_d(Register rd, Register rk, Register rj) {
1544   GenRegister(AMMIN_D, rk, rj, rd);
1545 }
1546 
ammax_wu(Register rd,Register rk,Register rj)1547 void Assembler::ammax_wu(Register rd, Register rk, Register rj) {
1548   GenRegister(AMMAX_WU, rk, rj, rd);
1549 }
1550 
ammax_du(Register rd,Register rk,Register rj)1551 void Assembler::ammax_du(Register rd, Register rk, Register rj) {
1552   GenRegister(AMMAX_DU, rk, rj, rd);
1553 }
1554 
ammin_wu(Register rd,Register rk,Register rj)1555 void Assembler::ammin_wu(Register rd, Register rk, Register rj) {
1556   GenRegister(AMMIN_WU, rk, rj, rd);
1557 }
1558 
ammin_du(Register rd,Register rk,Register rj)1559 void Assembler::ammin_du(Register rd, Register rk, Register rj) {
1560   GenRegister(AMMIN_DU, rk, rj, rd);
1561 }
1562 
amswap_db_w(Register rd,Register rk,Register rj)1563 void Assembler::amswap_db_w(Register rd, Register rk, Register rj) {
1564   GenRegister(AMSWAP_DB_W, rk, rj, rd);
1565 }
1566 
amswap_db_d(Register rd,Register rk,Register rj)1567 void Assembler::amswap_db_d(Register rd, Register rk, Register rj) {
1568   GenRegister(AMSWAP_DB_D, rk, rj, rd);
1569 }
1570 
amadd_db_w(Register rd,Register rk,Register rj)1571 void Assembler::amadd_db_w(Register rd, Register rk, Register rj) {
1572   GenRegister(AMADD_DB_W, rk, rj, rd);
1573 }
1574 
amadd_db_d(Register rd,Register rk,Register rj)1575 void Assembler::amadd_db_d(Register rd, Register rk, Register rj) {
1576   GenRegister(AMADD_DB_D, rk, rj, rd);
1577 }
1578 
amand_db_w(Register rd,Register rk,Register rj)1579 void Assembler::amand_db_w(Register rd, Register rk, Register rj) {
1580   GenRegister(AMAND_DB_W, rk, rj, rd);
1581 }
1582 
amand_db_d(Register rd,Register rk,Register rj)1583 void Assembler::amand_db_d(Register rd, Register rk, Register rj) {
1584   GenRegister(AMAND_DB_D, rk, rj, rd);
1585 }
1586 
amor_db_w(Register rd,Register rk,Register rj)1587 void Assembler::amor_db_w(Register rd, Register rk, Register rj) {
1588   GenRegister(AMOR_DB_W, rk, rj, rd);
1589 }
1590 
amor_db_d(Register rd,Register rk,Register rj)1591 void Assembler::amor_db_d(Register rd, Register rk, Register rj) {
1592   GenRegister(AMOR_DB_D, rk, rj, rd);
1593 }
1594 
amxor_db_w(Register rd,Register rk,Register rj)1595 void Assembler::amxor_db_w(Register rd, Register rk, Register rj) {
1596   GenRegister(AMXOR_DB_W, rk, rj, rd);
1597 }
1598 
amxor_db_d(Register rd,Register rk,Register rj)1599 void Assembler::amxor_db_d(Register rd, Register rk, Register rj) {
1600   GenRegister(AMXOR_DB_D, rk, rj, rd);
1601 }
1602 
ammax_db_w(Register rd,Register rk,Register rj)1603 void Assembler::ammax_db_w(Register rd, Register rk, Register rj) {
1604   GenRegister(AMMAX_DB_W, rk, rj, rd);
1605 }
1606 
ammax_db_d(Register rd,Register rk,Register rj)1607 void Assembler::ammax_db_d(Register rd, Register rk, Register rj) {
1608   GenRegister(AMMAX_DB_D, rk, rj, rd);
1609 }
1610 
ammin_db_w(Register rd,Register rk,Register rj)1611 void Assembler::ammin_db_w(Register rd, Register rk, Register rj) {
1612   GenRegister(AMMIN_DB_W, rk, rj, rd);
1613 }
1614 
ammin_db_d(Register rd,Register rk,Register rj)1615 void Assembler::ammin_db_d(Register rd, Register rk, Register rj) {
1616   GenRegister(AMMIN_DB_D, rk, rj, rd);
1617 }
1618 
ammax_db_wu(Register rd,Register rk,Register rj)1619 void Assembler::ammax_db_wu(Register rd, Register rk, Register rj) {
1620   GenRegister(AMMAX_DB_WU, rk, rj, rd);
1621 }
1622 
ammax_db_du(Register rd,Register rk,Register rj)1623 void Assembler::ammax_db_du(Register rd, Register rk, Register rj) {
1624   GenRegister(AMMAX_DB_DU, rk, rj, rd);
1625 }
1626 
ammin_db_wu(Register rd,Register rk,Register rj)1627 void Assembler::ammin_db_wu(Register rd, Register rk, Register rj) {
1628   GenRegister(AMMIN_DB_WU, rk, rj, rd);
1629 }
1630 
ammin_db_du(Register rd,Register rk,Register rj)1631 void Assembler::ammin_db_du(Register rd, Register rk, Register rj) {
1632   GenRegister(AMMIN_DB_DU, rk, rj, rd);
1633 }
1634 
ll_w(Register rd,Register rj,int32_t si14)1635 void Assembler::ll_w(Register rd, Register rj, int32_t si14) {
1636   DCHECK(is_int16(si14) && ((si14 & 0x3) == 0));
1637   GenImm(LL_W, si14 >> 2, rj, rd, 14);
1638 }
1639 
ll_d(Register rd,Register rj,int32_t si14)1640 void Assembler::ll_d(Register rd, Register rj, int32_t si14) {
1641   DCHECK(is_int16(si14) && ((si14 & 0x3) == 0));
1642   GenImm(LL_D, si14 >> 2, rj, rd, 14);
1643 }
1644 
sc_w(Register rd,Register rj,int32_t si14)1645 void Assembler::sc_w(Register rd, Register rj, int32_t si14) {
1646   DCHECK(is_int16(si14) && ((si14 & 0x3) == 0));
1647   GenImm(SC_W, si14 >> 2, rj, rd, 14);
1648 }
1649 
sc_d(Register rd,Register rj,int32_t si14)1650 void Assembler::sc_d(Register rd, Register rj, int32_t si14) {
1651   DCHECK(is_int16(si14) && ((si14 & 0x3) == 0));
1652   GenImm(SC_D, si14 >> 2, rj, rd, 14);
1653 }
1654 
dbar(int32_t hint)1655 void Assembler::dbar(int32_t hint) { GenImm(DBAR, hint); }
1656 
ibar(int32_t hint)1657 void Assembler::ibar(int32_t hint) { GenImm(IBAR, hint); }
1658 
1659 // Break instruction.
break_(uint32_t code,bool break_as_stop)1660 void Assembler::break_(uint32_t code, bool break_as_stop) {
1661   DCHECK(
1662       (break_as_stop && code <= kMaxStopCode && code > kMaxWatchpointCode) ||
1663       (!break_as_stop && (code > kMaxStopCode || code <= kMaxWatchpointCode)));
1664   GenImm(BREAK, code);
1665 }
1666 
stop(uint32_t code)1667 void Assembler::stop(uint32_t code) {
1668   DCHECK_GT(code, kMaxWatchpointCode);
1669   DCHECK_LE(code, kMaxStopCode);
1670 #if defined(V8_HOST_ARCH_LOONG64)
1671   break_(0x4321);
1672 #else  // V8_HOST_ARCH_LOONG64
1673   break_(code, true);
1674 #endif
1675 }
1676 
fadd_s(FPURegister fd,FPURegister fj,FPURegister fk)1677 void Assembler::fadd_s(FPURegister fd, FPURegister fj, FPURegister fk) {
1678   GenRegister(FADD_S, fk, fj, fd);
1679 }
1680 
fadd_d(FPURegister fd,FPURegister fj,FPURegister fk)1681 void Assembler::fadd_d(FPURegister fd, FPURegister fj, FPURegister fk) {
1682   GenRegister(FADD_D, fk, fj, fd);
1683 }
1684 
fsub_s(FPURegister fd,FPURegister fj,FPURegister fk)1685 void Assembler::fsub_s(FPURegister fd, FPURegister fj, FPURegister fk) {
1686   GenRegister(FSUB_S, fk, fj, fd);
1687 }
1688 
fsub_d(FPURegister fd,FPURegister fj,FPURegister fk)1689 void Assembler::fsub_d(FPURegister fd, FPURegister fj, FPURegister fk) {
1690   GenRegister(FSUB_D, fk, fj, fd);
1691 }
1692 
fmul_s(FPURegister fd,FPURegister fj,FPURegister fk)1693 void Assembler::fmul_s(FPURegister fd, FPURegister fj, FPURegister fk) {
1694   GenRegister(FMUL_S, fk, fj, fd);
1695 }
1696 
fmul_d(FPURegister fd,FPURegister fj,FPURegister fk)1697 void Assembler::fmul_d(FPURegister fd, FPURegister fj, FPURegister fk) {
1698   GenRegister(FMUL_D, fk, fj, fd);
1699 }
1700 
fdiv_s(FPURegister fd,FPURegister fj,FPURegister fk)1701 void Assembler::fdiv_s(FPURegister fd, FPURegister fj, FPURegister fk) {
1702   GenRegister(FDIV_S, fk, fj, fd);
1703 }
1704 
fdiv_d(FPURegister fd,FPURegister fj,FPURegister fk)1705 void Assembler::fdiv_d(FPURegister fd, FPURegister fj, FPURegister fk) {
1706   GenRegister(FDIV_D, fk, fj, fd);
1707 }
1708 
fmadd_s(FPURegister fd,FPURegister fj,FPURegister fk,FPURegister fa)1709 void Assembler::fmadd_s(FPURegister fd, FPURegister fj, FPURegister fk,
1710                         FPURegister fa) {
1711   GenRegister(FMADD_S, fa, fk, fj, fd);
1712 }
1713 
fmadd_d(FPURegister fd,FPURegister fj,FPURegister fk,FPURegister fa)1714 void Assembler::fmadd_d(FPURegister fd, FPURegister fj, FPURegister fk,
1715                         FPURegister fa) {
1716   GenRegister(FMADD_D, fa, fk, fj, fd);
1717 }
1718 
fmsub_s(FPURegister fd,FPURegister fj,FPURegister fk,FPURegister fa)1719 void Assembler::fmsub_s(FPURegister fd, FPURegister fj, FPURegister fk,
1720                         FPURegister fa) {
1721   GenRegister(FMSUB_S, fa, fk, fj, fd);
1722 }
1723 
fmsub_d(FPURegister fd,FPURegister fj,FPURegister fk,FPURegister fa)1724 void Assembler::fmsub_d(FPURegister fd, FPURegister fj, FPURegister fk,
1725                         FPURegister fa) {
1726   GenRegister(FMSUB_D, fa, fk, fj, fd);
1727 }
1728 
fnmadd_s(FPURegister fd,FPURegister fj,FPURegister fk,FPURegister fa)1729 void Assembler::fnmadd_s(FPURegister fd, FPURegister fj, FPURegister fk,
1730                          FPURegister fa) {
1731   GenRegister(FNMADD_S, fa, fk, fj, fd);
1732 }
1733 
fnmadd_d(FPURegister fd,FPURegister fj,FPURegister fk,FPURegister fa)1734 void Assembler::fnmadd_d(FPURegister fd, FPURegister fj, FPURegister fk,
1735                          FPURegister fa) {
1736   GenRegister(FNMADD_D, fa, fk, fj, fd);
1737 }
1738 
fnmsub_s(FPURegister fd,FPURegister fj,FPURegister fk,FPURegister fa)1739 void Assembler::fnmsub_s(FPURegister fd, FPURegister fj, FPURegister fk,
1740                          FPURegister fa) {
1741   GenRegister(FNMSUB_S, fa, fk, fj, fd);
1742 }
1743 
fnmsub_d(FPURegister fd,FPURegister fj,FPURegister fk,FPURegister fa)1744 void Assembler::fnmsub_d(FPURegister fd, FPURegister fj, FPURegister fk,
1745                          FPURegister fa) {
1746   GenRegister(FNMSUB_D, fa, fk, fj, fd);
1747 }
1748 
fmax_s(FPURegister fd,FPURegister fj,FPURegister fk)1749 void Assembler::fmax_s(FPURegister fd, FPURegister fj, FPURegister fk) {
1750   GenRegister(FMAX_S, fk, fj, fd);
1751 }
1752 
fmax_d(FPURegister fd,FPURegister fj,FPURegister fk)1753 void Assembler::fmax_d(FPURegister fd, FPURegister fj, FPURegister fk) {
1754   GenRegister(FMAX_D, fk, fj, fd);
1755 }
1756 
fmin_s(FPURegister fd,FPURegister fj,FPURegister fk)1757 void Assembler::fmin_s(FPURegister fd, FPURegister fj, FPURegister fk) {
1758   GenRegister(FMIN_S, fk, fj, fd);
1759 }
1760 
fmin_d(FPURegister fd,FPURegister fj,FPURegister fk)1761 void Assembler::fmin_d(FPURegister fd, FPURegister fj, FPURegister fk) {
1762   GenRegister(FMIN_D, fk, fj, fd);
1763 }
1764 
fmaxa_s(FPURegister fd,FPURegister fj,FPURegister fk)1765 void Assembler::fmaxa_s(FPURegister fd, FPURegister fj, FPURegister fk) {
1766   GenRegister(FMAXA_S, fk, fj, fd);
1767 }
1768 
fmaxa_d(FPURegister fd,FPURegister fj,FPURegister fk)1769 void Assembler::fmaxa_d(FPURegister fd, FPURegister fj, FPURegister fk) {
1770   GenRegister(FMAXA_D, fk, fj, fd);
1771 }
1772 
fmina_s(FPURegister fd,FPURegister fj,FPURegister fk)1773 void Assembler::fmina_s(FPURegister fd, FPURegister fj, FPURegister fk) {
1774   GenRegister(FMINA_S, fk, fj, fd);
1775 }
1776 
fmina_d(FPURegister fd,FPURegister fj,FPURegister fk)1777 void Assembler::fmina_d(FPURegister fd, FPURegister fj, FPURegister fk) {
1778   GenRegister(FMINA_D, fk, fj, fd);
1779 }
1780 
fabs_s(FPURegister fd,FPURegister fj)1781 void Assembler::fabs_s(FPURegister fd, FPURegister fj) {
1782   GenRegister(FABS_S, fj, fd);
1783 }
1784 
fabs_d(FPURegister fd,FPURegister fj)1785 void Assembler::fabs_d(FPURegister fd, FPURegister fj) {
1786   GenRegister(FABS_D, fj, fd);
1787 }
1788 
fneg_s(FPURegister fd,FPURegister fj)1789 void Assembler::fneg_s(FPURegister fd, FPURegister fj) {
1790   GenRegister(FNEG_S, fj, fd);
1791 }
1792 
fneg_d(FPURegister fd,FPURegister fj)1793 void Assembler::fneg_d(FPURegister fd, FPURegister fj) {
1794   GenRegister(FNEG_D, fj, fd);
1795 }
1796 
fsqrt_s(FPURegister fd,FPURegister fj)1797 void Assembler::fsqrt_s(FPURegister fd, FPURegister fj) {
1798   GenRegister(FSQRT_S, fj, fd);
1799 }
1800 
fsqrt_d(FPURegister fd,FPURegister fj)1801 void Assembler::fsqrt_d(FPURegister fd, FPURegister fj) {
1802   GenRegister(FSQRT_D, fj, fd);
1803 }
1804 
frecip_s(FPURegister fd,FPURegister fj)1805 void Assembler::frecip_s(FPURegister fd, FPURegister fj) {
1806   GenRegister(FRECIP_S, fj, fd);
1807 }
1808 
frecip_d(FPURegister fd,FPURegister fj)1809 void Assembler::frecip_d(FPURegister fd, FPURegister fj) {
1810   GenRegister(FRECIP_D, fj, fd);
1811 }
1812 
frsqrt_s(FPURegister fd,FPURegister fj)1813 void Assembler::frsqrt_s(FPURegister fd, FPURegister fj) {
1814   GenRegister(FRSQRT_S, fj, fd);
1815 }
1816 
frsqrt_d(FPURegister fd,FPURegister fj)1817 void Assembler::frsqrt_d(FPURegister fd, FPURegister fj) {
1818   GenRegister(FRSQRT_D, fj, fd);
1819 }
1820 
fscaleb_s(FPURegister fd,FPURegister fj,FPURegister fk)1821 void Assembler::fscaleb_s(FPURegister fd, FPURegister fj, FPURegister fk) {
1822   GenRegister(FSCALEB_S, fk, fj, fd);
1823 }
1824 
fscaleb_d(FPURegister fd,FPURegister fj,FPURegister fk)1825 void Assembler::fscaleb_d(FPURegister fd, FPURegister fj, FPURegister fk) {
1826   GenRegister(FSCALEB_D, fk, fj, fd);
1827 }
1828 
flogb_s(FPURegister fd,FPURegister fj)1829 void Assembler::flogb_s(FPURegister fd, FPURegister fj) {
1830   GenRegister(FLOGB_S, fj, fd);
1831 }
1832 
flogb_d(FPURegister fd,FPURegister fj)1833 void Assembler::flogb_d(FPURegister fd, FPURegister fj) {
1834   GenRegister(FLOGB_D, fj, fd);
1835 }
1836 
fcopysign_s(FPURegister fd,FPURegister fj,FPURegister fk)1837 void Assembler::fcopysign_s(FPURegister fd, FPURegister fj, FPURegister fk) {
1838   GenRegister(FCOPYSIGN_S, fk, fj, fd);
1839 }
1840 
fcopysign_d(FPURegister fd,FPURegister fj,FPURegister fk)1841 void Assembler::fcopysign_d(FPURegister fd, FPURegister fj, FPURegister fk) {
1842   GenRegister(FCOPYSIGN_D, fk, fj, fd);
1843 }
1844 
fclass_s(FPURegister fd,FPURegister fj)1845 void Assembler::fclass_s(FPURegister fd, FPURegister fj) {
1846   GenRegister(FCLASS_S, fj, fd);
1847 }
1848 
fclass_d(FPURegister fd,FPURegister fj)1849 void Assembler::fclass_d(FPURegister fd, FPURegister fj) {
1850   GenRegister(FCLASS_D, fj, fd);
1851 }
1852 
fcmp_cond_s(FPUCondition cc,FPURegister fj,FPURegister fk,CFRegister cd)1853 void Assembler::fcmp_cond_s(FPUCondition cc, FPURegister fj, FPURegister fk,
1854                             CFRegister cd) {
1855   GenCmp(FCMP_COND_S, cc, fk, fj, cd);
1856 }
1857 
fcmp_cond_d(FPUCondition cc,FPURegister fj,FPURegister fk,CFRegister cd)1858 void Assembler::fcmp_cond_d(FPUCondition cc, FPURegister fj, FPURegister fk,
1859                             CFRegister cd) {
1860   GenCmp(FCMP_COND_D, cc, fk, fj, cd);
1861 }
1862 
fcvt_s_d(FPURegister fd,FPURegister fj)1863 void Assembler::fcvt_s_d(FPURegister fd, FPURegister fj) {
1864   GenRegister(FCVT_S_D, fj, fd);
1865 }
1866 
fcvt_d_s(FPURegister fd,FPURegister fj)1867 void Assembler::fcvt_d_s(FPURegister fd, FPURegister fj) {
1868   GenRegister(FCVT_D_S, fj, fd);
1869 }
1870 
ffint_s_w(FPURegister fd,FPURegister fj)1871 void Assembler::ffint_s_w(FPURegister fd, FPURegister fj) {
1872   GenRegister(FFINT_S_W, fj, fd);
1873 }
1874 
ffint_s_l(FPURegister fd,FPURegister fj)1875 void Assembler::ffint_s_l(FPURegister fd, FPURegister fj) {
1876   GenRegister(FFINT_S_L, fj, fd);
1877 }
1878 
ffint_d_w(FPURegister fd,FPURegister fj)1879 void Assembler::ffint_d_w(FPURegister fd, FPURegister fj) {
1880   GenRegister(FFINT_D_W, fj, fd);
1881 }
1882 
ffint_d_l(FPURegister fd,FPURegister fj)1883 void Assembler::ffint_d_l(FPURegister fd, FPURegister fj) {
1884   GenRegister(FFINT_D_L, fj, fd);
1885 }
1886 
ftint_w_s(FPURegister fd,FPURegister fj)1887 void Assembler::ftint_w_s(FPURegister fd, FPURegister fj) {
1888   GenRegister(FTINT_W_S, fj, fd);
1889 }
1890 
ftint_w_d(FPURegister fd,FPURegister fj)1891 void Assembler::ftint_w_d(FPURegister fd, FPURegister fj) {
1892   GenRegister(FTINT_W_D, fj, fd);
1893 }
1894 
ftint_l_s(FPURegister fd,FPURegister fj)1895 void Assembler::ftint_l_s(FPURegister fd, FPURegister fj) {
1896   GenRegister(FTINT_L_S, fj, fd);
1897 }
1898 
ftint_l_d(FPURegister fd,FPURegister fj)1899 void Assembler::ftint_l_d(FPURegister fd, FPURegister fj) {
1900   GenRegister(FTINT_L_D, fj, fd);
1901 }
1902 
ftintrm_w_s(FPURegister fd,FPURegister fj)1903 void Assembler::ftintrm_w_s(FPURegister fd, FPURegister fj) {
1904   GenRegister(FTINTRM_W_S, fj, fd);
1905 }
1906 
ftintrm_w_d(FPURegister fd,FPURegister fj)1907 void Assembler::ftintrm_w_d(FPURegister fd, FPURegister fj) {
1908   GenRegister(FTINTRM_W_D, fj, fd);
1909 }
1910 
ftintrm_l_s(FPURegister fd,FPURegister fj)1911 void Assembler::ftintrm_l_s(FPURegister fd, FPURegister fj) {
1912   GenRegister(FTINTRM_L_S, fj, fd);
1913 }
1914 
ftintrm_l_d(FPURegister fd,FPURegister fj)1915 void Assembler::ftintrm_l_d(FPURegister fd, FPURegister fj) {
1916   GenRegister(FTINTRM_L_D, fj, fd);
1917 }
1918 
ftintrp_w_s(FPURegister fd,FPURegister fj)1919 void Assembler::ftintrp_w_s(FPURegister fd, FPURegister fj) {
1920   GenRegister(FTINTRP_W_S, fj, fd);
1921 }
1922 
ftintrp_w_d(FPURegister fd,FPURegister fj)1923 void Assembler::ftintrp_w_d(FPURegister fd, FPURegister fj) {
1924   GenRegister(FTINTRP_W_D, fj, fd);
1925 }
1926 
ftintrp_l_s(FPURegister fd,FPURegister fj)1927 void Assembler::ftintrp_l_s(FPURegister fd, FPURegister fj) {
1928   GenRegister(FTINTRP_L_S, fj, fd);
1929 }
1930 
ftintrp_l_d(FPURegister fd,FPURegister fj)1931 void Assembler::ftintrp_l_d(FPURegister fd, FPURegister fj) {
1932   GenRegister(FTINTRP_L_D, fj, fd);
1933 }
1934 
ftintrz_w_s(FPURegister fd,FPURegister fj)1935 void Assembler::ftintrz_w_s(FPURegister fd, FPURegister fj) {
1936   GenRegister(FTINTRZ_W_S, fj, fd);
1937 }
1938 
ftintrz_w_d(FPURegister fd,FPURegister fj)1939 void Assembler::ftintrz_w_d(FPURegister fd, FPURegister fj) {
1940   GenRegister(FTINTRZ_W_D, fj, fd);
1941 }
1942 
ftintrz_l_s(FPURegister fd,FPURegister fj)1943 void Assembler::ftintrz_l_s(FPURegister fd, FPURegister fj) {
1944   GenRegister(FTINTRZ_L_S, fj, fd);
1945 }
1946 
ftintrz_l_d(FPURegister fd,FPURegister fj)1947 void Assembler::ftintrz_l_d(FPURegister fd, FPURegister fj) {
1948   GenRegister(FTINTRZ_L_D, fj, fd);
1949 }
1950 
ftintrne_w_s(FPURegister fd,FPURegister fj)1951 void Assembler::ftintrne_w_s(FPURegister fd, FPURegister fj) {
1952   GenRegister(FTINTRNE_W_S, fj, fd);
1953 }
1954 
ftintrne_w_d(FPURegister fd,FPURegister fj)1955 void Assembler::ftintrne_w_d(FPURegister fd, FPURegister fj) {
1956   GenRegister(FTINTRNE_W_D, fj, fd);
1957 }
1958 
ftintrne_l_s(FPURegister fd,FPURegister fj)1959 void Assembler::ftintrne_l_s(FPURegister fd, FPURegister fj) {
1960   GenRegister(FTINTRNE_L_S, fj, fd);
1961 }
1962 
ftintrne_l_d(FPURegister fd,FPURegister fj)1963 void Assembler::ftintrne_l_d(FPURegister fd, FPURegister fj) {
1964   GenRegister(FTINTRNE_L_D, fj, fd);
1965 }
1966 
frint_s(FPURegister fd,FPURegister fj)1967 void Assembler::frint_s(FPURegister fd, FPURegister fj) {
1968   GenRegister(FRINT_S, fj, fd);
1969 }
1970 
frint_d(FPURegister fd,FPURegister fj)1971 void Assembler::frint_d(FPURegister fd, FPURegister fj) {
1972   GenRegister(FRINT_D, fj, fd);
1973 }
1974 
fmov_s(FPURegister fd,FPURegister fj)1975 void Assembler::fmov_s(FPURegister fd, FPURegister fj) {
1976   GenRegister(FMOV_S, fj, fd);
1977 }
1978 
fmov_d(FPURegister fd,FPURegister fj)1979 void Assembler::fmov_d(FPURegister fd, FPURegister fj) {
1980   GenRegister(FMOV_D, fj, fd);
1981 }
1982 
fsel(CFRegister ca,FPURegister fd,FPURegister fj,FPURegister fk)1983 void Assembler::fsel(CFRegister ca, FPURegister fd, FPURegister fj,
1984                      FPURegister fk) {
1985   GenSel(FSEL, ca, fk, fj, fd);
1986 }
1987 
movgr2fr_w(FPURegister fd,Register rj)1988 void Assembler::movgr2fr_w(FPURegister fd, Register rj) {
1989   GenRegister(MOVGR2FR_W, rj, fd);
1990 }
1991 
movgr2fr_d(FPURegister fd,Register rj)1992 void Assembler::movgr2fr_d(FPURegister fd, Register rj) {
1993   GenRegister(MOVGR2FR_D, rj, fd);
1994 }
1995 
movgr2frh_w(FPURegister fd,Register rj)1996 void Assembler::movgr2frh_w(FPURegister fd, Register rj) {
1997   GenRegister(MOVGR2FRH_W, rj, fd);
1998 }
1999 
movfr2gr_s(Register rd,FPURegister fj)2000 void Assembler::movfr2gr_s(Register rd, FPURegister fj) {
2001   GenRegister(MOVFR2GR_S, fj, rd);
2002 }
2003 
movfr2gr_d(Register rd,FPURegister fj)2004 void Assembler::movfr2gr_d(Register rd, FPURegister fj) {
2005   GenRegister(MOVFR2GR_D, fj, rd);
2006 }
2007 
movfrh2gr_s(Register rd,FPURegister fj)2008 void Assembler::movfrh2gr_s(Register rd, FPURegister fj) {
2009   GenRegister(MOVFRH2GR_S, fj, rd);
2010 }
2011 
movgr2fcsr(Register rj,FPUControlRegister fcsr)2012 void Assembler::movgr2fcsr(Register rj, FPUControlRegister fcsr) {
2013   GenRegister(MOVGR2FCSR, rj, fcsr);
2014 }
2015 
movfcsr2gr(Register rd,FPUControlRegister fcsr)2016 void Assembler::movfcsr2gr(Register rd, FPUControlRegister fcsr) {
2017   GenRegister(MOVFCSR2GR, fcsr, rd);
2018 }
2019 
movfr2cf(CFRegister cd,FPURegister fj)2020 void Assembler::movfr2cf(CFRegister cd, FPURegister fj) {
2021   GenRegister(MOVFR2CF, fj, cd);
2022 }
2023 
movcf2fr(FPURegister fd,CFRegister cj)2024 void Assembler::movcf2fr(FPURegister fd, CFRegister cj) {
2025   GenRegister(MOVCF2FR, cj, fd);
2026 }
2027 
movgr2cf(CFRegister cd,Register rj)2028 void Assembler::movgr2cf(CFRegister cd, Register rj) {
2029   GenRegister(MOVGR2CF, rj, cd);
2030 }
2031 
movcf2gr(Register rd,CFRegister cj)2032 void Assembler::movcf2gr(Register rd, CFRegister cj) {
2033   GenRegister(MOVCF2GR, cj, rd);
2034 }
2035 
fld_s(FPURegister fd,Register rj,int32_t si12)2036 void Assembler::fld_s(FPURegister fd, Register rj, int32_t si12) {
2037   GenImm(FLD_S, si12, rj, fd);
2038 }
2039 
fld_d(FPURegister fd,Register rj,int32_t si12)2040 void Assembler::fld_d(FPURegister fd, Register rj, int32_t si12) {
2041   GenImm(FLD_D, si12, rj, fd);
2042 }
2043 
fst_s(FPURegister fd,Register rj,int32_t si12)2044 void Assembler::fst_s(FPURegister fd, Register rj, int32_t si12) {
2045   GenImm(FST_S, si12, rj, fd);
2046 }
2047 
fst_d(FPURegister fd,Register rj,int32_t si12)2048 void Assembler::fst_d(FPURegister fd, Register rj, int32_t si12) {
2049   GenImm(FST_D, si12, rj, fd);
2050 }
2051 
fldx_s(FPURegister fd,Register rj,Register rk)2052 void Assembler::fldx_s(FPURegister fd, Register rj, Register rk) {
2053   GenRegister(FLDX_S, rk, rj, fd);
2054 }
2055 
fldx_d(FPURegister fd,Register rj,Register rk)2056 void Assembler::fldx_d(FPURegister fd, Register rj, Register rk) {
2057   GenRegister(FLDX_D, rk, rj, fd);
2058 }
2059 
fstx_s(FPURegister fd,Register rj,Register rk)2060 void Assembler::fstx_s(FPURegister fd, Register rj, Register rk) {
2061   GenRegister(FSTX_S, rk, rj, fd);
2062 }
2063 
fstx_d(FPURegister fd,Register rj,Register rk)2064 void Assembler::fstx_d(FPURegister fd, Register rj, Register rk) {
2065   GenRegister(FSTX_D, rk, rj, fd);
2066 }
2067 
AdjustBaseAndOffset(MemOperand * src)2068 void Assembler::AdjustBaseAndOffset(MemOperand* src) {
2069   // is_int12 must be passed a signed value, hence the static cast below.
2070   if ((!src->hasIndexReg() && is_int12(src->offset())) || src->hasIndexReg()) {
2071     return;
2072   }
2073   UseScratchRegisterScope temps(this);
2074   Register scratch = temps.Acquire();
2075   if (is_uint12(static_cast<int32_t>(src->offset()))) {
2076     ori(scratch, zero_reg, src->offset() & kImm12Mask);
2077   } else {
2078     lu12i_w(scratch, src->offset() >> 12 & 0xfffff);
2079     if (src->offset() & kImm12Mask) {
2080       ori(scratch, scratch, src->offset() & kImm12Mask);
2081     }
2082   }
2083   src->index_ = scratch;
2084   src->offset_ = 0;
2085 }
2086 
RelocateInternalReference(RelocInfo::Mode rmode,Address pc,intptr_t pc_delta)2087 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, Address pc,
2088                                          intptr_t pc_delta) {
2089   DCHECK(RelocInfo::IsInternalReference(rmode));
2090   int64_t* p = reinterpret_cast<int64_t*>(pc);
2091   if (*p == kEndOfJumpChain) {
2092     return 0;  // Number of instructions patched.
2093   }
2094   *p += pc_delta;
2095   return 2;  // Number of instructions patched.
2096 }
2097 
RelocateRelativeReference(RelocInfo::Mode rmode,Address pc,intptr_t pc_delta)2098 void Assembler::RelocateRelativeReference(RelocInfo::Mode rmode, Address pc,
2099                                           intptr_t pc_delta) {
2100   DCHECK(RelocInfo::IsRelativeCodeTarget(rmode));
2101   Instr instr = instr_at(pc);
2102   int32_t offset = instr & kImm26Mask;
2103   offset = (((offset & 0x3ff) << 22 >> 6) | ((offset >> 10) & kImm16Mask)) << 2;
2104   offset -= pc_delta;
2105   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
2106   offset >>= 2;
2107   offset = ((offset & kImm16Mask) << kRkShift) | ((offset & kImm26Mask) >> 16);
2108   *p = (instr & ~kImm26Mask) | offset;
2109   return;
2110 }
2111 
GrowBuffer()2112 void Assembler::GrowBuffer() {
2113   // Compute new buffer size.
2114   int old_size = buffer_->size();
2115   int new_size = std::min(2 * old_size, old_size + 1 * MB);
2116 
2117   // Some internal data structures overflow for very large buffers,
2118   // they must ensure that kMaximalBufferSize is not too large.
2119   if (new_size > kMaximalBufferSize) {
2120     V8::FatalProcessOutOfMemory(nullptr, "Assembler::GrowBuffer");
2121   }
2122 
2123   // Set up new buffer.
2124   std::unique_ptr<AssemblerBuffer> new_buffer = buffer_->Grow(new_size);
2125   DCHECK_EQ(new_size, new_buffer->size());
2126   byte* new_start = new_buffer->start();
2127 
2128   // Copy the data.
2129   intptr_t pc_delta = new_start - buffer_start_;
2130   intptr_t rc_delta = (new_start + new_size) - (buffer_start_ + old_size);
2131   size_t reloc_size = (buffer_start_ + old_size) - reloc_info_writer.pos();
2132   MemMove(new_start, buffer_start_, pc_offset());
2133   MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
2134           reloc_size);
2135 
2136   // Switch buffers.
2137   buffer_ = std::move(new_buffer);
2138   buffer_start_ = new_start;
2139   pc_ += pc_delta;
2140   pc_for_safepoint_ += pc_delta;
2141   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2142                                reloc_info_writer.last_pc() + pc_delta);
2143 
2144   // None of our relocation types are pc relative pointing outside the code
2145   // buffer nor pc absolute pointing inside the code buffer, so there is no need
2146   // to relocate any emitted relocation entries.
2147 
2148   // Relocate internal references.
2149   for (auto pos : internal_reference_positions_) {
2150     Address address = reinterpret_cast<intptr_t>(buffer_start_) + pos;
2151     intptr_t internal_ref = ReadUnalignedValue<intptr_t>(address);
2152     if (internal_ref != kEndOfJumpChain) {
2153       internal_ref += pc_delta;
2154       WriteUnalignedValue<intptr_t>(address, internal_ref);
2155     }
2156   }
2157 }
2158 
db(uint8_t data)2159 void Assembler::db(uint8_t data) {
2160   if (!is_buffer_growth_blocked()) {
2161     CheckBuffer();
2162   }
2163   *reinterpret_cast<uint8_t*>(pc_) = data;
2164   pc_ += sizeof(uint8_t);
2165 }
2166 
dd(uint32_t data,RelocInfo::Mode rmode)2167 void Assembler::dd(uint32_t data, RelocInfo::Mode rmode) {
2168   if (!is_buffer_growth_blocked()) {
2169     CheckBuffer();
2170   }
2171   if (!RelocInfo::IsNoInfo(rmode)) {
2172     DCHECK(RelocInfo::IsDataEmbeddedObject(rmode) ||
2173            RelocInfo::IsLiteralConstant(rmode));
2174     RecordRelocInfo(rmode);
2175   }
2176   *reinterpret_cast<uint32_t*>(pc_) = data;
2177   pc_ += sizeof(uint32_t);
2178 }
2179 
dq(uint64_t data,RelocInfo::Mode rmode)2180 void Assembler::dq(uint64_t data, RelocInfo::Mode rmode) {
2181   if (!is_buffer_growth_blocked()) {
2182     CheckBuffer();
2183   }
2184   if (!RelocInfo::IsNoInfo(rmode)) {
2185     DCHECK(RelocInfo::IsDataEmbeddedObject(rmode) ||
2186            RelocInfo::IsLiteralConstant(rmode));
2187     RecordRelocInfo(rmode);
2188   }
2189   *reinterpret_cast<uint64_t*>(pc_) = data;
2190   pc_ += sizeof(uint64_t);
2191 }
2192 
dd(Label * label)2193 void Assembler::dd(Label* label) {
2194   if (!is_buffer_growth_blocked()) {
2195     CheckBuffer();
2196   }
2197   uint64_t data;
2198   if (label->is_bound()) {
2199     data = reinterpret_cast<uint64_t>(buffer_start_ + label->pos());
2200   } else {
2201     data = jump_address(label);
2202     unbound_labels_count_++;
2203     internal_reference_positions_.insert(label->pos());
2204   }
2205   RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
2206   EmitHelper(data);
2207 }
2208 
RecordRelocInfo(RelocInfo::Mode rmode,intptr_t data)2209 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2210   if (!ShouldRecordRelocInfo(rmode)) return;
2211   // We do not try to reuse pool constants.
2212   RelocInfo rinfo(reinterpret_cast<Address>(pc_), rmode, data, Code());
2213   DCHECK_GE(buffer_space(), kMaxRelocSize);  // Too late to grow buffer here.
2214   reloc_info_writer.Write(&rinfo);
2215 }
2216 
BlockTrampolinePoolFor(int instructions)2217 void Assembler::BlockTrampolinePoolFor(int instructions) {
2218   CheckTrampolinePoolQuick(instructions);
2219   BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
2220 }
2221 
CheckTrampolinePool()2222 void Assembler::CheckTrampolinePool() {
2223   // Some small sequences of instructions must not be broken up by the
2224   // insertion of a trampoline pool; such sequences are protected by setting
2225   // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
2226   // which are both checked here. Also, recursive calls to CheckTrampolinePool
2227   // are blocked by trampoline_pool_blocked_nesting_.
2228   if ((trampoline_pool_blocked_nesting_ > 0) ||
2229       (pc_offset() < no_trampoline_pool_before_)) {
2230     // Emission is currently blocked; make sure we try again as soon as
2231     // possible.
2232     if (trampoline_pool_blocked_nesting_ > 0) {
2233       next_buffer_check_ = pc_offset() + kInstrSize;
2234     } else {
2235       next_buffer_check_ = no_trampoline_pool_before_;
2236     }
2237     return;
2238   }
2239 
2240   DCHECK(!trampoline_emitted_);
2241   DCHECK_GE(unbound_labels_count_, 0);
2242   if (unbound_labels_count_ > 0) {
2243     // First we emit jump (2 instructions), then we emit trampoline pool.
2244     {
2245       BlockTrampolinePoolScope block_trampoline_pool(this);
2246       Label after_pool;
2247       b(&after_pool);
2248       nop();  // TODO(LOONG_dev): remove this
2249 
2250       int pool_start = pc_offset();
2251       for (int i = 0; i < unbound_labels_count_; i++) {
2252         {
2253           b(&after_pool);
2254           nop();  // TODO(LOONG_dev): remove this
2255         }
2256       }
2257       nop();
2258       trampoline_ = Trampoline(pool_start, unbound_labels_count_);
2259       bind(&after_pool);
2260 
2261       trampoline_emitted_ = true;
2262       // As we are only going to emit trampoline once, we need to prevent any
2263       // further emission.
2264       next_buffer_check_ = kMaxInt;
2265     }
2266   } else {
2267     // Number of branches to unbound label at this point is zero, so we can
2268     // move next buffer check to maximum.
2269     next_buffer_check_ =
2270         pc_offset() + kMax16BranchOffset - kTrampolineSlotsSize * 16;
2271   }
2272   return;
2273 }
2274 
target_address_at(Address pc)2275 Address Assembler::target_address_at(Address pc) {
2276   Instr instr0 = instr_at(pc);
2277   if (IsB(instr0)) {
2278     int32_t offset = instr0 & kImm26Mask;
2279     offset = (((offset & 0x3ff) << 22 >> 6) | ((offset >> 10) & kImm16Mask))
2280              << 2;
2281     return pc + offset;
2282   }
2283   Instr instr1 = instr_at(pc + 1 * kInstrSize);
2284   Instr instr2 = instr_at(pc + 2 * kInstrSize);
2285 
2286   // Interpret 4 instructions for address generated by li: See listing in
2287   // Assembler::set_target_address_at() just below.
2288   DCHECK((IsLu12i_w(instr0) && (IsOri(instr1)) && (IsLu32i_d(instr2))));
2289 
2290   // Assemble the 48 bit value.
2291   uint64_t hi20 = ((uint64_t)(instr2 >> 5) & 0xfffff) << 32;
2292   uint64_t mid20 = ((uint64_t)(instr0 >> 5) & 0xfffff) << 12;
2293   uint64_t low12 = ((uint64_t)(instr1 >> 10) & 0xfff);
2294   int64_t addr = static_cast<int64_t>(hi20 | mid20 | low12);
2295 
2296   // Sign extend to get canonical address.
2297   addr = (addr << 16) >> 16;
2298   return static_cast<Address>(addr);
2299 }
2300 
2301 // On loong64, a target address is stored in a 3-instruction sequence:
2302 //    0: lu12i_w(rd, (j.imm64_ >> 12) & kImm20Mask);
2303 //    1: ori(rd, rd, j.imm64_  & kImm12Mask);
2304 //    2: lu32i_d(rd, (j.imm64_ >> 32) & kImm20Mask);
2305 //
2306 // Patching the address must replace all the lui & ori instructions,
2307 // and flush the i-cache.
2308 //
set_target_value_at(Address pc,uint64_t target,ICacheFlushMode icache_flush_mode)2309 void Assembler::set_target_value_at(Address pc, uint64_t target,
2310                                     ICacheFlushMode icache_flush_mode) {
2311   // There is an optimization where only 3 instructions are used to load address
2312   // in code on LOONG64 because only 48-bits of address is effectively used.
2313   // It relies on fact the upper [63:48] bits are not used for virtual address
2314   // translation and they have to be set according to value of bit 47 in order
2315   // get canonical address.
2316 #ifdef DEBUG
2317   // Check we have the result from a li macro-instruction.
2318   Instr instr0 = instr_at(pc);
2319   Instr instr1 = instr_at(pc + kInstrSize);
2320   Instr instr2 = instr_at(pc + kInstrSize * 2);
2321   DCHECK(IsLu12i_w(instr0) && IsOri(instr1) && IsLu32i_d(instr2) ||
2322          IsB(instr0));
2323 #endif
2324 
2325   Instr instr = instr_at(pc);
2326   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
2327   if (IsB(instr)) {
2328     int32_t offset = (target - pc) >> 2;
2329     CHECK(is_int26(offset));
2330     offset =
2331         ((offset & kImm16Mask) << kRkShift) | ((offset & kImm26Mask) >> 16);
2332     *p = (instr & ~kImm26Mask) | offset;
2333     if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
2334       FlushInstructionCache(pc, kInstrSize);
2335     }
2336     return;
2337   }
2338   uint32_t rd_code = GetRd(instr);
2339 
2340   // Must use 3 instructions to insure patchable code.
2341   // lu12i_w rd, middle-20.
2342   // ori rd, rd, low-12.
2343   // lu32i_d rd, high-20.
2344   *p = LU12I_W | (((target >> 12) & 0xfffff) << kRjShift) | rd_code;
2345   *(p + 1) =
2346       ORI | (target & 0xfff) << kRkShift | (rd_code << kRjShift) | rd_code;
2347   *(p + 2) = LU32I_D | (((target >> 32) & 0xfffff) << kRjShift) | rd_code;
2348 
2349   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
2350     FlushInstructionCache(pc, 3 * kInstrSize);
2351   }
2352 }
2353 
UseScratchRegisterScope(Assembler * assembler)2354 UseScratchRegisterScope::UseScratchRegisterScope(Assembler* assembler)
2355     : available_(assembler->GetScratchRegisterList()),
2356       old_available_(*available_) {}
2357 
~UseScratchRegisterScope()2358 UseScratchRegisterScope::~UseScratchRegisterScope() {
2359   *available_ = old_available_;
2360 }
2361 
Acquire()2362 Register UseScratchRegisterScope::Acquire() {
2363   DCHECK_NOT_NULL(available_);
2364   return available_->PopFirst();
2365 }
2366 
hasAvailable() const2367 bool UseScratchRegisterScope::hasAvailable() const {
2368   return !available_->is_empty();
2369 }
2370 
2371 }  // namespace internal
2372 }  // namespace v8
2373 
2374 #endif  // V8_TARGET_ARCH_LOONG64
2375