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