1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "jit/loong64/Assembler-loong64.h"
8 
9 #include "mozilla/DebugOnly.h"
10 #include "mozilla/Maybe.h"
11 
12 #include "gc/Marking.h"
13 #include "jit/AutoWritableJitCode.h"
14 #include "jit/ExecutableAllocator.h"
15 #include "vm/Realm.h"
16 
17 using mozilla::DebugOnly;
18 
19 using namespace js;
20 using namespace js::jit;
21 
22 // Note this is used for inter-wasm calls and may pass arguments and results
23 // in floating point registers even if the system ABI does not.
24 
25 // TODO(loong64): Inconsistent with LoongArch's calling convention.
26 // LoongArch floating-point parameters calling convention:
27 //   The first eight floating-point parameters should be passed in f0-f7, and
28 //   the other floating point parameters will be passed like integer parameters.
29 // But we just pass the other floating-point parameters on stack here.
next(MIRType type)30 ABIArg ABIArgGenerator::next(MIRType type) {
31   switch (type) {
32     case MIRType::Int32:
33     case MIRType::Int64:
34     case MIRType::Pointer:
35     case MIRType::RefOrNull:
36     case MIRType::StackResults: {
37       if (intRegIndex_ == NumIntArgRegs) {
38         current_ = ABIArg(stackOffset_);
39         stackOffset_ += sizeof(uintptr_t);
40         break;
41       }
42       current_ = ABIArg(Register::FromCode(intRegIndex_ + a0.encoding()));
43       intRegIndex_++;
44       break;
45     }
46     case MIRType::Float32:
47     case MIRType::Double: {
48       if (floatRegIndex_ == NumFloatArgRegs) {
49         current_ = ABIArg(stackOffset_);
50         stackOffset_ += sizeof(double);
51         break;
52       }
53       current_ = ABIArg(FloatRegister(
54           FloatRegisters::Encoding(floatRegIndex_ + f0.encoding()),
55           type == MIRType::Double ? FloatRegisters::Double
56                                   : FloatRegisters::Single));
57       floatRegIndex_++;
58       break;
59     }
60     case MIRType::Simd128: {
61       MOZ_CRASH("LoongArch does not support simd yet.");
62       break;
63     }
64     default:
65       MOZ_CRASH("Unexpected argument type");
66   }
67   return current_;
68 }
69 
70 // Encode a standard register when it is being used as rd, the rj, and
71 // an extra register(rk). These should never be called with an InvalidReg.
RJ(Register r)72 uint32_t js::jit::RJ(Register r) {
73   MOZ_ASSERT(r != InvalidReg);
74   return r.encoding() << RJShift;
75 }
76 
RK(Register r)77 uint32_t js::jit::RK(Register r) {
78   MOZ_ASSERT(r != InvalidReg);
79   return r.encoding() << RKShift;
80 }
81 
RD(Register r)82 uint32_t js::jit::RD(Register r) {
83   MOZ_ASSERT(r != InvalidReg);
84   return r.encoding() << RDShift;
85 }
86 
FJ(FloatRegister r)87 uint32_t js::jit::FJ(FloatRegister r) { return r.encoding() << RJShift; }
88 
FK(FloatRegister r)89 uint32_t js::jit::FK(FloatRegister r) { return r.encoding() << RKShift; }
90 
FD(FloatRegister r)91 uint32_t js::jit::FD(FloatRegister r) { return r.encoding() << RDShift; }
92 
FA(FloatRegister r)93 uint32_t js::jit::FA(FloatRegister r) { return r.encoding() << FAShift; }
94 
SA2(uint32_t value)95 uint32_t js::jit::SA2(uint32_t value) {
96   MOZ_ASSERT(value < 4);
97   return (value & SA2Mask) << SAShift;
98 }
99 
SA3(uint32_t value)100 uint32_t js::jit::SA3(uint32_t value) {
101   MOZ_ASSERT(value < 8);
102   return (value & SA3Mask) << SAShift;
103 }
104 
toRK(Instruction & i)105 Register js::jit::toRK(Instruction& i) {
106   return Register::FromCode((i.encode() & RKMask) >> RKShift);
107 }
108 
toRJ(Instruction & i)109 Register js::jit::toRJ(Instruction& i) {
110   return Register::FromCode((i.encode() & RJMask) >> RJShift);
111 }
112 
toRD(Instruction & i)113 Register js::jit::toRD(Instruction& i) {
114   return Register::FromCode((i.encode() & RDMask) >> RDShift);
115 }
116 
toR(Instruction & i)117 Register js::jit::toR(Instruction& i) {
118   return Register::FromCode(i.encode() & RegMask);
119 }
120 
extractImm16(BOffImm16 * dest)121 void InstImm::extractImm16(BOffImm16* dest) { *dest = BOffImm16(*this); }
122 
finish()123 void AssemblerLOONG64::finish() {
124   MOZ_ASSERT(!isFinished);
125   isFinished = true;
126 }
127 
appendRawCode(const uint8_t * code,size_t numBytes)128 bool AssemblerLOONG64::appendRawCode(const uint8_t* code, size_t numBytes) {
129   return m_buffer.appendRawCode(code, numBytes);
130 }
131 
reserve(size_t size)132 bool AssemblerLOONG64::reserve(size_t size) {
133   // This buffer uses fixed-size chunks so there's no point in reserving
134   // now vs. on-demand.
135   return !oom();
136 }
137 
swapBuffer(wasm::Bytes & bytes)138 bool AssemblerLOONG64::swapBuffer(wasm::Bytes& bytes) {
139   // For now, specialize to the one use case. As long as wasm::Bytes is a
140   // Vector, not a linked-list of chunks, there's not much we can do other
141   // than copy.
142   MOZ_ASSERT(bytes.empty());
143   if (!bytes.resize(bytesNeeded())) {
144     return false;
145   }
146   m_buffer.executableCopy(bytes.begin());
147   return true;
148 }
149 
copyJumpRelocationTable(uint8_t * dest)150 void AssemblerLOONG64::copyJumpRelocationTable(uint8_t* dest) {
151   if (jumpRelocations_.length()) {
152     memcpy(dest, jumpRelocations_.buffer(), jumpRelocations_.length());
153   }
154 }
155 
copyDataRelocationTable(uint8_t * dest)156 void AssemblerLOONG64::copyDataRelocationTable(uint8_t* dest) {
157   if (dataRelocations_.length()) {
158     memcpy(dest, dataRelocations_.buffer(), dataRelocations_.length());
159   }
160 }
161 
InvertCondition(Condition cond)162 AssemblerLOONG64::Condition AssemblerLOONG64::InvertCondition(Condition cond) {
163   switch (cond) {
164     case Equal:
165       return NotEqual;
166     case NotEqual:
167       return Equal;
168     case Zero:
169       return NonZero;
170     case NonZero:
171       return Zero;
172     case LessThan:
173       return GreaterThanOrEqual;
174     case LessThanOrEqual:
175       return GreaterThan;
176     case GreaterThan:
177       return LessThanOrEqual;
178     case GreaterThanOrEqual:
179       return LessThan;
180     case Above:
181       return BelowOrEqual;
182     case AboveOrEqual:
183       return Below;
184     case Below:
185       return AboveOrEqual;
186     case BelowOrEqual:
187       return Above;
188     case Signed:
189       return NotSigned;
190     case NotSigned:
191       return Signed;
192     default:
193       MOZ_CRASH("unexpected condition");
194   }
195 }
196 
InvertCondition(DoubleCondition cond)197 AssemblerLOONG64::DoubleCondition AssemblerLOONG64::InvertCondition(
198     DoubleCondition cond) {
199   switch (cond) {
200     case DoubleOrdered:
201       return DoubleUnordered;
202     case DoubleEqual:
203       return DoubleNotEqualOrUnordered;
204     case DoubleNotEqual:
205       return DoubleEqualOrUnordered;
206     case DoubleGreaterThan:
207       return DoubleLessThanOrEqualOrUnordered;
208     case DoubleGreaterThanOrEqual:
209       return DoubleLessThanOrUnordered;
210     case DoubleLessThan:
211       return DoubleGreaterThanOrEqualOrUnordered;
212     case DoubleLessThanOrEqual:
213       return DoubleGreaterThanOrUnordered;
214     case DoubleUnordered:
215       return DoubleOrdered;
216     case DoubleEqualOrUnordered:
217       return DoubleNotEqual;
218     case DoubleNotEqualOrUnordered:
219       return DoubleEqual;
220     case DoubleGreaterThanOrUnordered:
221       return DoubleLessThanOrEqual;
222     case DoubleGreaterThanOrEqualOrUnordered:
223       return DoubleLessThan;
224     case DoubleLessThanOrUnordered:
225       return DoubleGreaterThanOrEqual;
226     case DoubleLessThanOrEqualOrUnordered:
227       return DoubleGreaterThan;
228     default:
229       MOZ_CRASH("unexpected condition");
230   }
231 }
232 
InvertCmpCondition(Condition cond)233 AssemblerLOONG64::Condition AssemblerLOONG64::InvertCmpCondition(
234     Condition cond) {
235   switch (cond) {
236     case Equal:
237     case NotEqual:
238       return cond;
239     case LessThan:
240       return GreaterThan;
241     case LessThanOrEqual:
242       return GreaterThanOrEqual;
243     case GreaterThan:
244       return LessThanOrEqual;
245     case GreaterThanOrEqual:
246       return LessThan;
247     case Above:
248       return Below;
249     case AboveOrEqual:
250       return BelowOrEqual;
251     case Below:
252       return Above;
253     case BelowOrEqual:
254       return AboveOrEqual;
255     default:
256       MOZ_CRASH("no meaningful swapped-operand condition");
257   }
258 }
259 
BOffImm16(InstImm inst)260 BOffImm16::BOffImm16(InstImm inst)
261     : data((inst.encode() >> Imm16Shift) & Imm16Mask) {}
262 
getDest(Instruction * src) const263 Instruction* BOffImm16::getDest(Instruction* src) const {
264   return &src[(((int32_t)data << 16) >> 16) + 1];
265 }
266 
oom() const267 bool AssemblerLOONG64::oom() const {
268   return AssemblerShared::oom() || m_buffer.oom() || jumpRelocations_.oom() ||
269          dataRelocations_.oom();
270 }
271 
272 // Size of the instruction stream, in bytes.
size() const273 size_t AssemblerLOONG64::size() const { return m_buffer.size(); }
274 
275 // Size of the relocation table, in bytes.
jumpRelocationTableBytes() const276 size_t AssemblerLOONG64::jumpRelocationTableBytes() const {
277   return jumpRelocations_.length();
278 }
279 
dataRelocationTableBytes() const280 size_t AssemblerLOONG64::dataRelocationTableBytes() const {
281   return dataRelocations_.length();
282 }
283 
284 // Size of the data table, in bytes.
bytesNeeded() const285 size_t AssemblerLOONG64::bytesNeeded() const {
286   return size() + jumpRelocationTableBytes() + dataRelocationTableBytes();
287 }
288 
289 // write a blob of binary into the instruction stream
writeInst(uint32_t x,uint32_t * dest)290 BufferOffset AssemblerLOONG64::writeInst(uint32_t x, uint32_t* dest) {
291   MOZ_ASSERT(hasCreator());
292   if (dest == nullptr) {
293     return m_buffer.putInt(x);
294   }
295 
296   WriteInstStatic(x, dest);
297   return BufferOffset();
298 }
299 
WriteInstStatic(uint32_t x,uint32_t * dest)300 void AssemblerLOONG64::WriteInstStatic(uint32_t x, uint32_t* dest) {
301   MOZ_ASSERT(dest != nullptr);
302   *dest = x;
303 }
304 
haltingAlign(int alignment)305 BufferOffset AssemblerLOONG64::haltingAlign(int alignment) {
306   // TODO(loong64): Implement a proper halting align.
307   return nopAlign(alignment);
308 }
309 
nopAlign(int alignment)310 BufferOffset AssemblerLOONG64::nopAlign(int alignment) {
311   BufferOffset ret;
312   MOZ_ASSERT(m_buffer.isAligned(4));
313   if (alignment == 8) {
314     if (!m_buffer.isAligned(alignment)) {
315       BufferOffset tmp = as_nop();
316       if (!ret.assigned()) {
317         ret = tmp;
318       }
319     }
320   } else {
321     MOZ_ASSERT((alignment & (alignment - 1)) == 0);
322     while (size() & (alignment - 1)) {
323       BufferOffset tmp = as_nop();
324       if (!ret.assigned()) {
325         ret = tmp;
326       }
327     }
328   }
329   return ret;
330 }
331 
332 // Logical operations.
as_and(Register rd,Register rj,Register rk)333 BufferOffset AssemblerLOONG64::as_and(Register rd, Register rj, Register rk) {
334   spew("and    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
335   return writeInst(InstReg(op_and, rk, rj, rd).encode());
336 }
337 
as_or(Register rd,Register rj,Register rk)338 BufferOffset AssemblerLOONG64::as_or(Register rd, Register rj, Register rk) {
339   spew("or     %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
340   return writeInst(InstReg(op_or, rk, rj, rd).encode());
341 }
342 
as_xor(Register rd,Register rj,Register rk)343 BufferOffset AssemblerLOONG64::as_xor(Register rd, Register rj, Register rk) {
344   spew("xor    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
345   return writeInst(InstReg(op_xor, rk, rj, rd).encode());
346 }
347 
as_nor(Register rd,Register rj,Register rk)348 BufferOffset AssemblerLOONG64::as_nor(Register rd, Register rj, Register rk) {
349   spew("nor    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
350   return writeInst(InstReg(op_nor, rk, rj, rd).encode());
351 }
352 
as_andn(Register rd,Register rj,Register rk)353 BufferOffset AssemblerLOONG64::as_andn(Register rd, Register rj, Register rk) {
354   spew("andn    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
355   return writeInst(InstReg(op_andn, rk, rj, rd).encode());
356 }
357 
as_orn(Register rd,Register rj,Register rk)358 BufferOffset AssemblerLOONG64::as_orn(Register rd, Register rj, Register rk) {
359   spew("orn     %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
360   return writeInst(InstReg(op_orn, rk, rj, rd).encode());
361 }
362 
as_andi(Register rd,Register rj,int32_t ui12)363 BufferOffset AssemblerLOONG64::as_andi(Register rd, Register rj, int32_t ui12) {
364   MOZ_ASSERT(is_uintN(ui12, 12));
365   spew("andi   %3s,%3s,0x%x", rd.name(), rj.name(), ui12);
366   return writeInst(InstImm(op_andi, ui12, rj, rd, 12).encode());
367 }
368 
as_ori(Register rd,Register rj,int32_t ui12)369 BufferOffset AssemblerLOONG64::as_ori(Register rd, Register rj, int32_t ui12) {
370   MOZ_ASSERT(is_uintN(ui12, 12));
371   spew("ori    %3s,%3s,0x%x", rd.name(), rj.name(), ui12);
372   return writeInst(InstImm(op_ori, ui12, rj, rd, 12).encode());
373 }
374 
as_xori(Register rd,Register rj,int32_t ui12)375 BufferOffset AssemblerLOONG64::as_xori(Register rd, Register rj, int32_t ui12) {
376   MOZ_ASSERT(is_uintN(ui12, 12));
377   spew("xori   %3s,%3s,0x%x", rd.name(), rj.name(), ui12);
378   return writeInst(InstImm(op_xori, ui12, rj, rd, 12).encode());
379 }
380 
381 // Branch and jump instructions
as_b(JOffImm26 off)382 BufferOffset AssemblerLOONG64::as_b(JOffImm26 off) {
383   spew("b    %d", off.decode());
384   return writeInst(InstJump(op_b, off).encode());
385 }
386 
as_bl(JOffImm26 off)387 BufferOffset AssemblerLOONG64::as_bl(JOffImm26 off) {
388   spew("bl    %d", off.decode());
389   return writeInst(InstJump(op_bl, off).encode());
390 }
391 
as_jirl(Register rd,Register rj,BOffImm16 off)392 BufferOffset AssemblerLOONG64::as_jirl(Register rd, Register rj,
393                                        BOffImm16 off) {
394   spew("jirl   %3s, %3s, %d", rd.name(), rj.name(), off.decode());
395   return writeInst(InstImm(op_jirl, off, rj, rd).encode());
396 }
397 
getBranchCode(JumpOrCall jumpOrCall)398 InstImm AssemblerLOONG64::getBranchCode(JumpOrCall jumpOrCall) {
399   // jirl or beq
400   if (jumpOrCall == BranchIsCall) {
401     return InstImm(op_jirl, BOffImm16(0), zero, ra);
402   }
403 
404   return InstImm(op_beq, BOffImm16(0), zero, zero);
405 }
406 
getBranchCode(Register rj,Register rd,Condition c)407 InstImm AssemblerLOONG64::getBranchCode(Register rj, Register rd, Condition c) {
408   // beq, bne
409   MOZ_ASSERT(c == AssemblerLOONG64::Equal || c == AssemblerLOONG64::NotEqual);
410   return InstImm(c == AssemblerLOONG64::Equal ? op_beq : op_bne, BOffImm16(0),
411                  rj, rd);
412 }
413 
getBranchCode(Register rj,Condition c)414 InstImm AssemblerLOONG64::getBranchCode(Register rj, Condition c) {
415   // beq, bne, blt, bge
416   switch (c) {
417     case AssemblerLOONG64::Equal:
418     case AssemblerLOONG64::Zero:
419     case AssemblerLOONG64::BelowOrEqual:
420       return InstImm(op_beq, BOffImm16(0), rj, zero);
421     case AssemblerLOONG64::NotEqual:
422     case AssemblerLOONG64::NonZero:
423     case AssemblerLOONG64::Above:
424       return InstImm(op_bne, BOffImm16(0), rj, zero);
425     case AssemblerLOONG64::GreaterThan:
426       return InstImm(op_blt, BOffImm16(0), zero, rj);
427     case AssemblerLOONG64::GreaterThanOrEqual:
428     case AssemblerLOONG64::NotSigned:
429       return InstImm(op_bge, BOffImm16(0), rj, zero);
430     case AssemblerLOONG64::LessThan:
431     case AssemblerLOONG64::Signed:
432       return InstImm(op_blt, BOffImm16(0), rj, zero);
433     case AssemblerLOONG64::LessThanOrEqual:
434       return InstImm(op_bge, BOffImm16(0), zero, rj);
435     default:
436       MOZ_CRASH("Condition not supported.");
437   }
438 }
439 
440 // Code semantics must conform to compareFloatingpoint
getBranchCode(FPConditionBit cj)441 InstImm AssemblerLOONG64::getBranchCode(FPConditionBit cj) {
442   return InstImm(op_bcz, 0, cj, true);  // bcnez
443 }
444 
445 // Arithmetic instructions
as_add_w(Register rd,Register rj,Register rk)446 BufferOffset AssemblerLOONG64::as_add_w(Register rd, Register rj, Register rk) {
447   spew("add_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
448   return writeInst(InstReg(op_add_w, rk, rj, rd).encode());
449 }
450 
as_add_d(Register rd,Register rj,Register rk)451 BufferOffset AssemblerLOONG64::as_add_d(Register rd, Register rj, Register rk) {
452   spew("add_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
453   return writeInst(InstReg(op_add_d, rk, rj, rd).encode());
454 }
455 
as_sub_w(Register rd,Register rj,Register rk)456 BufferOffset AssemblerLOONG64::as_sub_w(Register rd, Register rj, Register rk) {
457   spew("sub_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
458   return writeInst(InstReg(op_sub_w, rk, rj, rd).encode());
459 }
460 
as_sub_d(Register rd,Register rj,Register rk)461 BufferOffset AssemblerLOONG64::as_sub_d(Register rd, Register rj, Register rk) {
462   spew("sub_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
463   return writeInst(InstReg(op_sub_d, rk, rj, rd).encode());
464 }
465 
as_addi_w(Register rd,Register rj,int32_t si12)466 BufferOffset AssemblerLOONG64::as_addi_w(Register rd, Register rj,
467                                          int32_t si12) {
468   MOZ_ASSERT(is_intN(si12, 12));
469   spew("addi_w   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
470   return writeInst(InstImm(op_addi_w, si12, rj, rd, 12).encode());
471 }
472 
as_addi_d(Register rd,Register rj,int32_t si12)473 BufferOffset AssemblerLOONG64::as_addi_d(Register rd, Register rj,
474                                          int32_t si12) {
475   MOZ_ASSERT(is_intN(si12, 12));
476   spew("addi_d   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
477   return writeInst(InstImm(op_addi_d, si12, rj, rd, 12).encode());
478 }
479 
as_addu16i_d(Register rd,Register rj,int32_t si16)480 BufferOffset AssemblerLOONG64::as_addu16i_d(Register rd, Register rj,
481                                             int32_t si16) {
482   MOZ_ASSERT(Imm16::IsInSignedRange(si16));
483   spew("addu16i_d   %3s,%3s,0x%x", rd.name(), rj.name(), si16);
484   return writeInst(InstImm(op_addu16i_d, Imm16(si16), rj, rd).encode());
485 }
486 
as_alsl_w(Register rd,Register rj,Register rk,uint32_t sa2)487 BufferOffset AssemblerLOONG64::as_alsl_w(Register rd, Register rj, Register rk,
488                                          uint32_t sa2) {
489   MOZ_ASSERT(sa2 < 4);
490   spew("alsl_w   %3s,%3s,0x%x", rd.name(), rj.name(), sa2);
491   return writeInst(InstReg(op_alsl_w, sa2, rk, rj, rd, 2).encode());
492 }
493 
as_alsl_wu(Register rd,Register rj,Register rk,uint32_t sa2)494 BufferOffset AssemblerLOONG64::as_alsl_wu(Register rd, Register rj, Register rk,
495                                           uint32_t sa2) {
496   MOZ_ASSERT(sa2 < 4);
497   spew("alsl_wu   %3s,%3s,0x%x", rd.name(), rj.name(), sa2);
498   return writeInst(InstReg(op_alsl_wu, sa2, rk, rj, rd, 2).encode());
499 }
500 
as_alsl_d(Register rd,Register rj,Register rk,uint32_t sa2)501 BufferOffset AssemblerLOONG64::as_alsl_d(Register rd, Register rj, Register rk,
502                                          uint32_t sa2) {
503   MOZ_ASSERT(sa2 < 4);
504   spew("alsl_d   %3s,%3s,%3s,0x%x", rd.name(), rj.name(), rk.name(), sa2);
505   return writeInst(InstReg(op_alsl_d, sa2, rk, rj, rd, 2).encode());
506 }
507 
as_lu12i_w(Register rd,int32_t si20)508 BufferOffset AssemblerLOONG64::as_lu12i_w(Register rd, int32_t si20) {
509   spew("lu12i_w   %3s,0x%x", rd.name(), si20);
510   return writeInst(InstImm(op_lu12i_w, si20, rd, false).encode());
511 }
512 
as_lu32i_d(Register rd,int32_t si20)513 BufferOffset AssemblerLOONG64::as_lu32i_d(Register rd, int32_t si20) {
514   spew("lu32i_d   %3s,0x%x", rd.name(), si20);
515   return writeInst(InstImm(op_lu32i_d, si20, rd, false).encode());
516 }
517 
as_lu52i_d(Register rd,Register rj,int32_t si12)518 BufferOffset AssemblerLOONG64::as_lu52i_d(Register rd, Register rj,
519                                           int32_t si12) {
520   MOZ_ASSERT(is_uintN(si12, 12));
521   spew("lu52i_d   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
522   return writeInst(InstImm(op_lu52i_d, si12, rj, rd, 12).encode());
523 }
524 
as_slt(Register rd,Register rj,Register rk)525 BufferOffset AssemblerLOONG64::as_slt(Register rd, Register rj, Register rk) {
526   spew("slt   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
527   return writeInst(InstReg(op_slt, rk, rj, rd).encode());
528 }
529 
as_sltu(Register rd,Register rj,Register rk)530 BufferOffset AssemblerLOONG64::as_sltu(Register rd, Register rj, Register rk) {
531   spew("sltu   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
532   return writeInst(InstReg(op_sltu, rk, rj, rd).encode());
533 }
534 
as_slti(Register rd,Register rj,int32_t si12)535 BufferOffset AssemblerLOONG64::as_slti(Register rd, Register rj, int32_t si12) {
536   MOZ_ASSERT(is_intN(si12, 12));
537   spew("slti   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
538   return writeInst(InstImm(op_slti, si12, rj, rd, 12).encode());
539 }
540 
as_sltui(Register rd,Register rj,int32_t si12)541 BufferOffset AssemblerLOONG64::as_sltui(Register rd, Register rj,
542                                         int32_t si12) {
543   MOZ_ASSERT(is_intN(si12, 12));
544   spew("sltui   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
545   return writeInst(InstImm(op_sltui, si12, rj, rd, 12).encode());
546 }
547 
as_pcaddi(Register rd,int32_t si20)548 BufferOffset AssemblerLOONG64::as_pcaddi(Register rd, int32_t si20) {
549   spew("pcaddi   %3s,0x%x", rd.name(), si20);
550   return writeInst(InstImm(op_pcaddi, si20, rd, false).encode());
551 }
552 
as_pcaddu12i(Register rd,int32_t si20)553 BufferOffset AssemblerLOONG64::as_pcaddu12i(Register rd, int32_t si20) {
554   spew("pcaddu12i   %3s,0x%x", rd.name(), si20);
555   return writeInst(InstImm(op_pcaddu12i, si20, rd, false).encode());
556 }
557 
as_pcaddu18i(Register rd,int32_t si20)558 BufferOffset AssemblerLOONG64::as_pcaddu18i(Register rd, int32_t si20) {
559   spew("pcaddu18i   %3s,0x%x", rd.name(), si20);
560   return writeInst(InstImm(op_pcaddu18i, si20, rd, false).encode());
561 }
562 
as_pcalau12i(Register rd,int32_t si20)563 BufferOffset AssemblerLOONG64::as_pcalau12i(Register rd, int32_t si20) {
564   spew("pcalau12i   %3s,0x%x", rd.name(), si20);
565   return writeInst(InstImm(op_pcalau12i, si20, rd, false).encode());
566 }
567 
as_mul_w(Register rd,Register rj,Register rk)568 BufferOffset AssemblerLOONG64::as_mul_w(Register rd, Register rj, Register rk) {
569   spew("mul_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
570   return writeInst(InstReg(op_mul_w, rk, rj, rd).encode());
571 }
572 
as_mulh_w(Register rd,Register rj,Register rk)573 BufferOffset AssemblerLOONG64::as_mulh_w(Register rd, Register rj,
574                                          Register rk) {
575   spew("mulh_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
576   return writeInst(InstReg(op_mulh_w, rk, rj, rd).encode());
577 }
578 
as_mulh_wu(Register rd,Register rj,Register rk)579 BufferOffset AssemblerLOONG64::as_mulh_wu(Register rd, Register rj,
580                                           Register rk) {
581   spew("mulh_wu   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
582   return writeInst(InstReg(op_mulh_wu, rk, rj, rd).encode());
583 }
584 
as_mul_d(Register rd,Register rj,Register rk)585 BufferOffset AssemblerLOONG64::as_mul_d(Register rd, Register rj, Register rk) {
586   spew("mul_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
587   return writeInst(InstReg(op_mul_d, rk, rj, rd).encode());
588 }
589 
as_mulh_d(Register rd,Register rj,Register rk)590 BufferOffset AssemblerLOONG64::as_mulh_d(Register rd, Register rj,
591                                          Register rk) {
592   spew("mulh_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
593   return writeInst(InstReg(op_mulh_d, rk, rj, rd).encode());
594 }
595 
as_mulh_du(Register rd,Register rj,Register rk)596 BufferOffset AssemblerLOONG64::as_mulh_du(Register rd, Register rj,
597                                           Register rk) {
598   spew("mulh_du   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
599   return writeInst(InstReg(op_mulh_du, rk, rj, rd).encode());
600 }
601 
as_mulw_d_w(Register rd,Register rj,Register rk)602 BufferOffset AssemblerLOONG64::as_mulw_d_w(Register rd, Register rj,
603                                            Register rk) {
604   spew("mulw_d_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
605   return writeInst(InstReg(op_mulw_d_w, rk, rj, rd).encode());
606 }
607 
as_mulw_d_wu(Register rd,Register rj,Register rk)608 BufferOffset AssemblerLOONG64::as_mulw_d_wu(Register rd, Register rj,
609                                             Register rk) {
610   spew("mulw_d_wu   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
611   return writeInst(InstReg(op_mulw_d_wu, rk, rj, rd).encode());
612 }
613 
as_div_w(Register rd,Register rj,Register rk)614 BufferOffset AssemblerLOONG64::as_div_w(Register rd, Register rj, Register rk) {
615   spew("div_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
616   return writeInst(InstReg(op_div_w, rk, rj, rd).encode());
617 }
618 
as_mod_w(Register rd,Register rj,Register rk)619 BufferOffset AssemblerLOONG64::as_mod_w(Register rd, Register rj, Register rk) {
620   spew("mod_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
621   return writeInst(InstReg(op_mod_w, rk, rj, rd).encode());
622 }
623 
as_div_wu(Register rd,Register rj,Register rk)624 BufferOffset AssemblerLOONG64::as_div_wu(Register rd, Register rj,
625                                          Register rk) {
626   spew("div_wu   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
627   return writeInst(InstReg(op_div_wu, rk, rj, rd).encode());
628 }
629 
as_mod_wu(Register rd,Register rj,Register rk)630 BufferOffset AssemblerLOONG64::as_mod_wu(Register rd, Register rj,
631                                          Register rk) {
632   spew("mod_wu   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
633   return writeInst(InstReg(op_mod_wu, rk, rj, rd).encode());
634 }
635 
as_div_d(Register rd,Register rj,Register rk)636 BufferOffset AssemblerLOONG64::as_div_d(Register rd, Register rj, Register rk) {
637   spew("div_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
638   return writeInst(InstReg(op_div_d, rk, rj, rd).encode());
639 }
640 
as_mod_d(Register rd,Register rj,Register rk)641 BufferOffset AssemblerLOONG64::as_mod_d(Register rd, Register rj, Register rk) {
642   spew("mod_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
643   return writeInst(InstReg(op_mod_d, rk, rj, rd).encode());
644 }
645 
as_div_du(Register rd,Register rj,Register rk)646 BufferOffset AssemblerLOONG64::as_div_du(Register rd, Register rj,
647                                          Register rk) {
648   spew("div_du   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
649   return writeInst(InstReg(op_div_du, rk, rj, rd).encode());
650 }
651 
as_mod_du(Register rd,Register rj,Register rk)652 BufferOffset AssemblerLOONG64::as_mod_du(Register rd, Register rj,
653                                          Register rk) {
654   spew("mod_du   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
655   return writeInst(InstReg(op_mod_du, rk, rj, rd).encode());
656 }
657 
658 // Shift instructions
as_sll_w(Register rd,Register rj,Register rk)659 BufferOffset AssemblerLOONG64::as_sll_w(Register rd, Register rj, Register rk) {
660   spew("sll_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
661   return writeInst(InstReg(op_sll_w, rk, rj, rd).encode());
662 }
663 
as_srl_w(Register rd,Register rj,Register rk)664 BufferOffset AssemblerLOONG64::as_srl_w(Register rd, Register rj, Register rk) {
665   spew("srl_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
666   return writeInst(InstReg(op_srl_w, rk, rj, rd).encode());
667 }
668 
as_sra_w(Register rd,Register rj,Register rk)669 BufferOffset AssemblerLOONG64::as_sra_w(Register rd, Register rj, Register rk) {
670   spew("sra_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
671   return writeInst(InstReg(op_sra_w, rk, rj, rd).encode());
672 }
673 
as_rotr_w(Register rd,Register rj,Register rk)674 BufferOffset AssemblerLOONG64::as_rotr_w(Register rd, Register rj,
675                                          Register rk) {
676   spew("rotr_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
677   return writeInst(InstReg(op_rotr_w, rk, rj, rd).encode());
678 }
679 
as_slli_w(Register rd,Register rj,int32_t ui5)680 BufferOffset AssemblerLOONG64::as_slli_w(Register rd, Register rj,
681                                          int32_t ui5) {
682   MOZ_ASSERT(is_uintN(ui5, 5));
683   spew("slli_w   %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
684   return writeInst(InstImm(op_slli_w, ui5, rj, rd, 5).encode());
685 }
686 
as_srli_w(Register rd,Register rj,int32_t ui5)687 BufferOffset AssemblerLOONG64::as_srli_w(Register rd, Register rj,
688                                          int32_t ui5) {
689   MOZ_ASSERT(is_uintN(ui5, 5));
690   spew("srli_w   %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
691   return writeInst(InstImm(op_srli_w, ui5, rj, rd, 5).encode());
692 }
693 
as_srai_w(Register rd,Register rj,int32_t ui5)694 BufferOffset AssemblerLOONG64::as_srai_w(Register rd, Register rj,
695                                          int32_t ui5) {
696   MOZ_ASSERT(is_uintN(ui5, 5));
697   spew("srai_w   %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
698   return writeInst(InstImm(op_srai_w, ui5, rj, rd, 5).encode());
699 }
700 
as_rotri_w(Register rd,Register rj,int32_t ui5)701 BufferOffset AssemblerLOONG64::as_rotri_w(Register rd, Register rj,
702                                           int32_t ui5) {
703   MOZ_ASSERT(is_uintN(ui5, 5));
704   spew("rotri_w   %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
705   return writeInst(InstImm(op_rotri_w, ui5, rj, rd, 5).encode());
706 }
707 
as_sll_d(Register rd,Register rj,Register rk)708 BufferOffset AssemblerLOONG64::as_sll_d(Register rd, Register rj, Register rk) {
709   spew("sll_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
710   return writeInst(InstReg(op_sll_d, rk, rj, rd).encode());
711 }
712 
as_srl_d(Register rd,Register rj,Register rk)713 BufferOffset AssemblerLOONG64::as_srl_d(Register rd, Register rj, Register rk) {
714   spew("srl_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
715   return writeInst(InstReg(op_srl_d, rk, rj, rd).encode());
716 }
717 
as_sra_d(Register rd,Register rj,Register rk)718 BufferOffset AssemblerLOONG64::as_sra_d(Register rd, Register rj, Register rk) {
719   spew("sra_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
720   return writeInst(InstReg(op_sra_d, rk, rj, rd).encode());
721 }
722 
as_rotr_d(Register rd,Register rj,Register rk)723 BufferOffset AssemblerLOONG64::as_rotr_d(Register rd, Register rj,
724                                          Register rk) {
725   spew("rotr_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
726   return writeInst(InstReg(op_rotr_d, rk, rj, rd).encode());
727 }
728 
as_slli_d(Register rd,Register rj,int32_t ui6)729 BufferOffset AssemblerLOONG64::as_slli_d(Register rd, Register rj,
730                                          int32_t ui6) {
731   MOZ_ASSERT(is_uintN(ui6, 6));
732   spew("slli_d   %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
733   return writeInst(InstImm(op_slli_d, ui6, rj, rd, 6).encode());
734 }
735 
as_srli_d(Register rd,Register rj,int32_t ui6)736 BufferOffset AssemblerLOONG64::as_srli_d(Register rd, Register rj,
737                                          int32_t ui6) {
738   MOZ_ASSERT(is_uintN(ui6, 6));
739   spew("srli_d   %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
740   return writeInst(InstImm(op_srli_d, ui6, rj, rd, 6).encode());
741 }
742 
as_srai_d(Register rd,Register rj,int32_t ui6)743 BufferOffset AssemblerLOONG64::as_srai_d(Register rd, Register rj,
744                                          int32_t ui6) {
745   MOZ_ASSERT(is_uintN(ui6, 6));
746   spew("srai_d   %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
747   return writeInst(InstImm(op_srai_d, ui6, rj, rd, 6).encode());
748 }
749 
as_rotri_d(Register rd,Register rj,int32_t ui6)750 BufferOffset AssemblerLOONG64::as_rotri_d(Register rd, Register rj,
751                                           int32_t ui6) {
752   MOZ_ASSERT(is_uintN(ui6, 6));
753   spew("rotri_d   %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
754   return writeInst(InstImm(op_rotri_d, ui6, rj, rd, 6).encode());
755 }
756 
757 // Bit operation instrucitons
as_ext_w_b(Register rd,Register rj)758 BufferOffset AssemblerLOONG64::as_ext_w_b(Register rd, Register rj) {
759   spew("ext_w_b    %3s,%3s", rd.name(), rj.name());
760   return writeInst(InstReg(op_ext_w_b, rj, rd).encode());
761 }
762 
as_ext_w_h(Register rd,Register rj)763 BufferOffset AssemblerLOONG64::as_ext_w_h(Register rd, Register rj) {
764   spew("ext_w_h    %3s,%3s", rd.name(), rj.name());
765   return writeInst(InstReg(op_ext_w_h, rj, rd).encode());
766 }
767 
as_clo_w(Register rd,Register rj)768 BufferOffset AssemblerLOONG64::as_clo_w(Register rd, Register rj) {
769   spew("clo_w    %3s,%3s", rd.name(), rj.name());
770   return writeInst(InstReg(op_clo_w, rj, rd).encode());
771 }
772 
as_clz_w(Register rd,Register rj)773 BufferOffset AssemblerLOONG64::as_clz_w(Register rd, Register rj) {
774   spew("clz_w    %3s,%3s", rd.name(), rj.name());
775   return writeInst(InstReg(op_clz_w, rj, rd).encode());
776 }
777 
as_cto_w(Register rd,Register rj)778 BufferOffset AssemblerLOONG64::as_cto_w(Register rd, Register rj) {
779   spew("cto_w    %3s,%3s", rd.name(), rj.name());
780   return writeInst(InstReg(op_cto_w, rj, rd).encode());
781 }
782 
as_ctz_w(Register rd,Register rj)783 BufferOffset AssemblerLOONG64::as_ctz_w(Register rd, Register rj) {
784   spew("ctz_w    %3s,%3s", rd.name(), rj.name());
785   return writeInst(InstReg(op_ctz_w, rj, rd).encode());
786 }
787 
as_clo_d(Register rd,Register rj)788 BufferOffset AssemblerLOONG64::as_clo_d(Register rd, Register rj) {
789   spew("clo_d    %3s,%3s", rd.name(), rj.name());
790   return writeInst(InstReg(op_clo_d, rj, rd).encode());
791 }
792 
as_clz_d(Register rd,Register rj)793 BufferOffset AssemblerLOONG64::as_clz_d(Register rd, Register rj) {
794   spew("clz_d    %3s,%3s", rd.name(), rj.name());
795   return writeInst(InstReg(op_clz_d, rj, rd).encode());
796 }
797 
as_cto_d(Register rd,Register rj)798 BufferOffset AssemblerLOONG64::as_cto_d(Register rd, Register rj) {
799   spew("cto_d    %3s,%3s", rd.name(), rj.name());
800   return writeInst(InstReg(op_cto_d, rj, rd).encode());
801 }
802 
as_ctz_d(Register rd,Register rj)803 BufferOffset AssemblerLOONG64::as_ctz_d(Register rd, Register rj) {
804   spew("ctz_d    %3s,%3s", rd.name(), rj.name());
805   return writeInst(InstReg(op_ctz_d, rj, rd).encode());
806 }
807 
as_bytepick_w(Register rd,Register rj,Register rk,int32_t sa2)808 BufferOffset AssemblerLOONG64::as_bytepick_w(Register rd, Register rj,
809                                              Register rk, int32_t sa2) {
810   MOZ_ASSERT(sa2 < 4);
811   spew("bytepick_w    %3s,%3s,%3s, 0x%x", rd.name(), rj.name(), rk.name(), sa2);
812   return writeInst(InstReg(op_bytepick_w, sa2, rk, rj, rd, 2).encode());
813 }
814 
as_bytepick_d(Register rd,Register rj,Register rk,int32_t sa3)815 BufferOffset AssemblerLOONG64::as_bytepick_d(Register rd, Register rj,
816                                              Register rk, int32_t sa3) {
817   MOZ_ASSERT(sa3 < 8);
818   spew("bytepick_d    %3s,%3s,%3s, 0x%x", rd.name(), rj.name(), rk.name(), sa3);
819   return writeInst(InstReg(op_bytepick_d, sa3, rk, rj, rd, 3).encode());
820 }
821 
as_revb_2h(Register rd,Register rj)822 BufferOffset AssemblerLOONG64::as_revb_2h(Register rd, Register rj) {
823   spew("revb_2h    %3s,%3s", rd.name(), rj.name());
824   return writeInst(InstReg(op_revb_2h, rj, rd).encode());
825 }
826 
as_revb_4h(Register rd,Register rj)827 BufferOffset AssemblerLOONG64::as_revb_4h(Register rd, Register rj) {
828   spew("revb_4h    %3s,%3s", rd.name(), rj.name());
829   return writeInst(InstReg(op_revb_4h, rj, rd).encode());
830 }
831 
as_revb_2w(Register rd,Register rj)832 BufferOffset AssemblerLOONG64::as_revb_2w(Register rd, Register rj) {
833   spew("revb_2w    %3s,%3s", rd.name(), rj.name());
834   return writeInst(InstReg(op_revb_2w, rj, rd).encode());
835 }
836 
as_revb_d(Register rd,Register rj)837 BufferOffset AssemblerLOONG64::as_revb_d(Register rd, Register rj) {
838   spew("revb_d    %3s,%3s", rd.name(), rj.name());
839   return writeInst(InstReg(op_revb_d, rj, rd).encode());
840 }
841 
as_revh_2w(Register rd,Register rj)842 BufferOffset AssemblerLOONG64::as_revh_2w(Register rd, Register rj) {
843   spew("revh_2w    %3s,%3s", rd.name(), rj.name());
844   return writeInst(InstReg(op_revh_2w, rj, rd).encode());
845 }
846 
as_revh_d(Register rd,Register rj)847 BufferOffset AssemblerLOONG64::as_revh_d(Register rd, Register rj) {
848   spew("revh_d    %3s,%3s", rd.name(), rj.name());
849   return writeInst(InstReg(op_revh_d, rj, rd).encode());
850 }
851 
as_bitrev_4b(Register rd,Register rj)852 BufferOffset AssemblerLOONG64::as_bitrev_4b(Register rd, Register rj) {
853   spew("bitrev_4b    %3s,%3s", rd.name(), rj.name());
854   return writeInst(InstReg(op_bitrev_4b, rj, rd).encode());
855 }
856 
as_bitrev_8b(Register rd,Register rj)857 BufferOffset AssemblerLOONG64::as_bitrev_8b(Register rd, Register rj) {
858   spew("bitrev_8b    %3s,%3s", rd.name(), rj.name());
859   return writeInst(InstReg(op_bitrev_8b, rj, rd).encode());
860 }
861 
as_bitrev_w(Register rd,Register rj)862 BufferOffset AssemblerLOONG64::as_bitrev_w(Register rd, Register rj) {
863   spew("bitrev_w    %3s,%3s", rd.name(), rj.name());
864   return writeInst(InstReg(op_bitrev_w, rj, rd).encode());
865 }
866 
as_bitrev_d(Register rd,Register rj)867 BufferOffset AssemblerLOONG64::as_bitrev_d(Register rd, Register rj) {
868   spew("bitrev_d    %3s,%3s", rd.name(), rj.name());
869   return writeInst(InstReg(op_bitrev_d, rj, rd).encode());
870 }
871 
as_bstrins_w(Register rd,Register rj,int32_t msbw,int32_t lsbw)872 BufferOffset AssemblerLOONG64::as_bstrins_w(Register rd, Register rj,
873                                             int32_t msbw, int32_t lsbw) {
874   MOZ_ASSERT(lsbw <= msbw);
875   spew("bstrins_w   %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbw, lsbw);
876   return writeInst(InstImm(op_bstr_w, msbw, lsbw, rj, rd, 5).encode());
877 }
878 
as_bstrins_d(Register rd,Register rj,int32_t msbd,int32_t lsbd)879 BufferOffset AssemblerLOONG64::as_bstrins_d(Register rd, Register rj,
880                                             int32_t msbd, int32_t lsbd) {
881   MOZ_ASSERT(lsbd <= msbd);
882   spew("bstrins_d   %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbd, lsbd);
883   return writeInst(InstImm(op_bstrins_d, msbd, lsbd, rj, rd, 6).encode());
884 }
885 
as_bstrpick_w(Register rd,Register rj,int32_t msbw,int32_t lsbw)886 BufferOffset AssemblerLOONG64::as_bstrpick_w(Register rd, Register rj,
887                                              int32_t msbw, int32_t lsbw) {
888   MOZ_ASSERT(lsbw <= msbw);
889   spew("bstrpick_w   %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbw, lsbw);
890   return writeInst(InstImm(op_bstr_w, msbw, lsbw, rj, rd).encode());
891 }
892 
as_bstrpick_d(Register rd,Register rj,int32_t msbd,int32_t lsbd)893 BufferOffset AssemblerLOONG64::as_bstrpick_d(Register rd, Register rj,
894                                              int32_t msbd, int32_t lsbd) {
895   MOZ_ASSERT(lsbd <= msbd);
896   spew("bstrpick_d   %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbd, lsbd);
897   return writeInst(InstImm(op_bstrpick_d, msbd, lsbd, rj, rd, 6).encode());
898 }
899 
as_maskeqz(Register rd,Register rj,Register rk)900 BufferOffset AssemblerLOONG64::as_maskeqz(Register rd, Register rj,
901                                           Register rk) {
902   spew("maskeqz    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
903   return writeInst(InstReg(op_maskeqz, rk, rj, rd).encode());
904 }
905 
as_masknez(Register rd,Register rj,Register rk)906 BufferOffset AssemblerLOONG64::as_masknez(Register rd, Register rj,
907                                           Register rk) {
908   spew("masknez    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
909   return writeInst(InstReg(op_masknez, rk, rj, rd).encode());
910 }
911 
912 // Load and store instructions
as_ld_b(Register rd,Register rj,int32_t si12)913 BufferOffset AssemblerLOONG64::as_ld_b(Register rd, Register rj, int32_t si12) {
914   MOZ_ASSERT(is_intN(si12, 12));
915   spew("ld_b   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
916   return writeInst(InstImm(op_ld_b, si12, rj, rd, 12).encode());
917 }
918 
as_ld_h(Register rd,Register rj,int32_t si12)919 BufferOffset AssemblerLOONG64::as_ld_h(Register rd, Register rj, int32_t si12) {
920   MOZ_ASSERT(is_intN(si12, 12));
921   spew("ld_h   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
922   return writeInst(InstImm(op_ld_h, si12, rj, rd, 12).encode());
923 }
924 
as_ld_w(Register rd,Register rj,int32_t si12)925 BufferOffset AssemblerLOONG64::as_ld_w(Register rd, Register rj, int32_t si12) {
926   MOZ_ASSERT(is_intN(si12, 12));
927   spew("ld_w   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
928   return writeInst(InstImm(op_ld_w, si12, rj, rd, 12).encode());
929 }
930 
as_ld_d(Register rd,Register rj,int32_t si12)931 BufferOffset AssemblerLOONG64::as_ld_d(Register rd, Register rj, int32_t si12) {
932   MOZ_ASSERT(is_intN(si12, 12));
933   spew("ld_d   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
934   return writeInst(InstImm(op_ld_d, si12, rj, rd, 12).encode());
935 }
936 
as_ld_bu(Register rd,Register rj,int32_t si12)937 BufferOffset AssemblerLOONG64::as_ld_bu(Register rd, Register rj,
938                                         int32_t si12) {
939   MOZ_ASSERT(is_intN(si12, 12));
940   spew("ld_bu   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
941   return writeInst(InstImm(op_ld_bu, si12, rj, rd, 12).encode());
942 }
943 
as_ld_hu(Register rd,Register rj,int32_t si12)944 BufferOffset AssemblerLOONG64::as_ld_hu(Register rd, Register rj,
945                                         int32_t si12) {
946   MOZ_ASSERT(is_intN(si12, 12));
947   spew("ld_hu   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
948   return writeInst(InstImm(op_ld_hu, si12, rj, rd, 12).encode());
949 }
950 
as_ld_wu(Register rd,Register rj,int32_t si12)951 BufferOffset AssemblerLOONG64::as_ld_wu(Register rd, Register rj,
952                                         int32_t si12) {
953   MOZ_ASSERT(is_intN(si12, 12));
954   spew("ld_wu   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
955   return writeInst(InstImm(op_ld_wu, si12, rj, rd, 12).encode());
956 }
957 
as_st_b(Register rd,Register rj,int32_t si12)958 BufferOffset AssemblerLOONG64::as_st_b(Register rd, Register rj, int32_t si12) {
959   MOZ_ASSERT(is_intN(si12, 12));
960   spew("st_b   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
961   return writeInst(InstImm(op_st_b, si12, rj, rd, 12).encode());
962 }
963 
as_st_h(Register rd,Register rj,int32_t si12)964 BufferOffset AssemblerLOONG64::as_st_h(Register rd, Register rj, int32_t si12) {
965   MOZ_ASSERT(is_intN(si12, 12));
966   spew("st_h   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
967   return writeInst(InstImm(op_st_h, si12, rj, rd, 12).encode());
968 }
969 
as_st_w(Register rd,Register rj,int32_t si12)970 BufferOffset AssemblerLOONG64::as_st_w(Register rd, Register rj, int32_t si12) {
971   MOZ_ASSERT(is_intN(si12, 12));
972   spew("st_w   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
973   return writeInst(InstImm(op_st_w, si12, rj, rd, 12).encode());
974 }
975 
as_st_d(Register rd,Register rj,int32_t si12)976 BufferOffset AssemblerLOONG64::as_st_d(Register rd, Register rj, int32_t si12) {
977   MOZ_ASSERT(is_intN(si12, 12));
978   spew("st_d   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
979   return writeInst(InstImm(op_st_d, si12, rj, rd, 12).encode());
980 }
981 
as_ldx_b(Register rd,Register rj,Register rk)982 BufferOffset AssemblerLOONG64::as_ldx_b(Register rd, Register rj, Register rk) {
983   spew("ldx_b    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
984   return writeInst(InstReg(op_ldx_b, rk, rj, rd).encode());
985 }
986 
as_ldx_h(Register rd,Register rj,Register rk)987 BufferOffset AssemblerLOONG64::as_ldx_h(Register rd, Register rj, Register rk) {
988   spew("ldx_h    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
989   return writeInst(InstReg(op_ldx_h, rk, rj, rd).encode());
990 }
991 
as_ldx_w(Register rd,Register rj,Register rk)992 BufferOffset AssemblerLOONG64::as_ldx_w(Register rd, Register rj, Register rk) {
993   spew("ldx_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
994   return writeInst(InstReg(op_ldx_w, rk, rj, rd).encode());
995 }
996 
as_ldx_d(Register rd,Register rj,Register rk)997 BufferOffset AssemblerLOONG64::as_ldx_d(Register rd, Register rj, Register rk) {
998   spew("ldx_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
999   return writeInst(InstReg(op_ldx_d, rk, rj, rd).encode());
1000 }
1001 
as_ldx_bu(Register rd,Register rj,Register rk)1002 BufferOffset AssemblerLOONG64::as_ldx_bu(Register rd, Register rj,
1003                                          Register rk) {
1004   spew("ldx_bu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1005   return writeInst(InstReg(op_ldx_bu, rk, rj, rd).encode());
1006 }
1007 
as_ldx_hu(Register rd,Register rj,Register rk)1008 BufferOffset AssemblerLOONG64::as_ldx_hu(Register rd, Register rj,
1009                                          Register rk) {
1010   spew("ldx_hu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1011   return writeInst(InstReg(op_ldx_hu, rk, rj, rd).encode());
1012 }
1013 
as_ldx_wu(Register rd,Register rj,Register rk)1014 BufferOffset AssemblerLOONG64::as_ldx_wu(Register rd, Register rj,
1015                                          Register rk) {
1016   spew("ldx_wu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1017   return writeInst(InstReg(op_ldx_wu, rk, rj, rd).encode());
1018 }
1019 
as_stx_b(Register rd,Register rj,Register rk)1020 BufferOffset AssemblerLOONG64::as_stx_b(Register rd, Register rj, Register rk) {
1021   spew("stx_b    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1022   return writeInst(InstReg(op_stx_b, rk, rj, rd).encode());
1023 }
1024 
as_stx_h(Register rd,Register rj,Register rk)1025 BufferOffset AssemblerLOONG64::as_stx_h(Register rd, Register rj, Register rk) {
1026   spew("stx_h    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1027   return writeInst(InstReg(op_stx_h, rk, rj, rd).encode());
1028 }
1029 
as_stx_w(Register rd,Register rj,Register rk)1030 BufferOffset AssemblerLOONG64::as_stx_w(Register rd, Register rj, Register rk) {
1031   spew("stx_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1032   return writeInst(InstReg(op_stx_w, rk, rj, rd).encode());
1033 }
1034 
as_stx_d(Register rd,Register rj,Register rk)1035 BufferOffset AssemblerLOONG64::as_stx_d(Register rd, Register rj, Register rk) {
1036   spew("stx_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1037   return writeInst(InstReg(op_stx_d, rk, rj, rd).encode());
1038 }
1039 
as_ldptr_w(Register rd,Register rj,int32_t si14)1040 BufferOffset AssemblerLOONG64::as_ldptr_w(Register rd, Register rj,
1041                                           int32_t si14) {
1042   MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
1043   spew("ldptr_w   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
1044   return writeInst(InstImm(op_ldptr_w, si14 >> 2, rj, rd, 14).encode());
1045 }
1046 
as_ldptr_d(Register rd,Register rj,int32_t si14)1047 BufferOffset AssemblerLOONG64::as_ldptr_d(Register rd, Register rj,
1048                                           int32_t si14) {
1049   MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
1050   spew("ldptr_d   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
1051   return writeInst(InstImm(op_ldptr_d, si14 >> 2, rj, rd, 14).encode());
1052 }
1053 
as_stptr_w(Register rd,Register rj,int32_t si14)1054 BufferOffset AssemblerLOONG64::as_stptr_w(Register rd, Register rj,
1055                                           int32_t si14) {
1056   MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
1057   spew("stptr_w   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
1058   return writeInst(InstImm(op_stptr_w, si14 >> 2, rj, rd, 14).encode());
1059 }
1060 
as_stptr_d(Register rd,Register rj,int32_t si14)1061 BufferOffset AssemblerLOONG64::as_stptr_d(Register rd, Register rj,
1062                                           int32_t si14) {
1063   MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
1064   spew("stptr_d   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
1065   return writeInst(InstImm(op_stptr_d, si14 >> 2, rj, rd, 14).encode());
1066 }
1067 
as_preld(int32_t hint,Register rj,int32_t si12)1068 BufferOffset AssemblerLOONG64::as_preld(int32_t hint, Register rj,
1069                                         int32_t si12) {
1070   MOZ_ASSERT(is_intN(si12, 12));
1071   spew("preld   0x%x,%3s,0x%x", hint, rj.name(), si12);
1072   return writeInst(InstImm(op_preld, si12, rj, hint).encode());
1073 }
1074 
1075 // Atomic instructions
as_amswap_w(Register rd,Register rj,Register rk)1076 BufferOffset AssemblerLOONG64::as_amswap_w(Register rd, Register rj,
1077                                            Register rk) {
1078   spew("amswap_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1079   return writeInst(InstReg(op_amswap_w, rk, rj, rd).encode());
1080 }
1081 
as_amswap_d(Register rd,Register rj,Register rk)1082 BufferOffset AssemblerLOONG64::as_amswap_d(Register rd, Register rj,
1083                                            Register rk) {
1084   spew("amswap_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1085   return writeInst(InstReg(op_amswap_d, rk, rj, rd).encode());
1086 }
1087 
as_amadd_w(Register rd,Register rj,Register rk)1088 BufferOffset AssemblerLOONG64::as_amadd_w(Register rd, Register rj,
1089                                           Register rk) {
1090   spew("amadd_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1091   return writeInst(InstReg(op_amadd_w, rk, rj, rd).encode());
1092 }
1093 
as_amadd_d(Register rd,Register rj,Register rk)1094 BufferOffset AssemblerLOONG64::as_amadd_d(Register rd, Register rj,
1095                                           Register rk) {
1096   spew("amadd_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1097   return writeInst(InstReg(op_amadd_d, rk, rj, rd).encode());
1098 }
1099 
as_amand_w(Register rd,Register rj,Register rk)1100 BufferOffset AssemblerLOONG64::as_amand_w(Register rd, Register rj,
1101                                           Register rk) {
1102   spew("amand_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1103   return writeInst(InstReg(op_amand_w, rk, rj, rd).encode());
1104 }
1105 
as_amand_d(Register rd,Register rj,Register rk)1106 BufferOffset AssemblerLOONG64::as_amand_d(Register rd, Register rj,
1107                                           Register rk) {
1108   spew("amand_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1109   return writeInst(InstReg(op_amand_d, rk, rj, rd).encode());
1110 }
1111 
as_amor_w(Register rd,Register rj,Register rk)1112 BufferOffset AssemblerLOONG64::as_amor_w(Register rd, Register rj,
1113                                          Register rk) {
1114   spew("amor_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1115   return writeInst(InstReg(op_amor_w, rk, rj, rd).encode());
1116 }
1117 
as_amor_d(Register rd,Register rj,Register rk)1118 BufferOffset AssemblerLOONG64::as_amor_d(Register rd, Register rj,
1119                                          Register rk) {
1120   spew("amor_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1121   return writeInst(InstReg(op_amor_d, rk, rj, rd).encode());
1122 }
1123 
as_amxor_w(Register rd,Register rj,Register rk)1124 BufferOffset AssemblerLOONG64::as_amxor_w(Register rd, Register rj,
1125                                           Register rk) {
1126   spew("amxor_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1127   return writeInst(InstReg(op_amxor_w, rk, rj, rd).encode());
1128 }
1129 
as_amxor_d(Register rd,Register rj,Register rk)1130 BufferOffset AssemblerLOONG64::as_amxor_d(Register rd, Register rj,
1131                                           Register rk) {
1132   spew("amxor_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1133   return writeInst(InstReg(op_amxor_d, rk, rj, rd).encode());
1134 }
1135 
as_ammax_w(Register rd,Register rj,Register rk)1136 BufferOffset AssemblerLOONG64::as_ammax_w(Register rd, Register rj,
1137                                           Register rk) {
1138   spew("ammax_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1139   return writeInst(InstReg(op_ammax_w, rk, rj, rd).encode());
1140 }
1141 
as_ammax_d(Register rd,Register rj,Register rk)1142 BufferOffset AssemblerLOONG64::as_ammax_d(Register rd, Register rj,
1143                                           Register rk) {
1144   spew("ammax_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1145   return writeInst(InstReg(op_ammax_d, rk, rj, rd).encode());
1146 }
1147 
as_ammin_w(Register rd,Register rj,Register rk)1148 BufferOffset AssemblerLOONG64::as_ammin_w(Register rd, Register rj,
1149                                           Register rk) {
1150   spew("ammin_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1151   return writeInst(InstReg(op_ammin_w, rk, rj, rd).encode());
1152 }
1153 
as_ammin_d(Register rd,Register rj,Register rk)1154 BufferOffset AssemblerLOONG64::as_ammin_d(Register rd, Register rj,
1155                                           Register rk) {
1156   spew("ammin_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1157   return writeInst(InstReg(op_ammin_d, rk, rj, rd).encode());
1158 }
1159 
as_ammax_wu(Register rd,Register rj,Register rk)1160 BufferOffset AssemblerLOONG64::as_ammax_wu(Register rd, Register rj,
1161                                            Register rk) {
1162   spew("ammax_wu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1163   return writeInst(InstReg(op_ammax_wu, rk, rj, rd).encode());
1164 }
1165 
as_ammax_du(Register rd,Register rj,Register rk)1166 BufferOffset AssemblerLOONG64::as_ammax_du(Register rd, Register rj,
1167                                            Register rk) {
1168   spew("ammax_du    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1169   return writeInst(InstReg(op_ammax_du, rk, rj, rd).encode());
1170 }
1171 
as_ammin_wu(Register rd,Register rj,Register rk)1172 BufferOffset AssemblerLOONG64::as_ammin_wu(Register rd, Register rj,
1173                                            Register rk) {
1174   spew("ammin_wu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1175   return writeInst(InstReg(op_ammin_wu, rk, rj, rd).encode());
1176 }
1177 
as_ammin_du(Register rd,Register rj,Register rk)1178 BufferOffset AssemblerLOONG64::as_ammin_du(Register rd, Register rj,
1179                                            Register rk) {
1180   spew("ammin_du    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1181   return writeInst(InstReg(op_ammin_du, rk, rj, rd).encode());
1182 }
1183 
as_amswap_db_w(Register rd,Register rj,Register rk)1184 BufferOffset AssemblerLOONG64::as_amswap_db_w(Register rd, Register rj,
1185                                               Register rk) {
1186   spew("amswap_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1187   return writeInst(InstReg(op_amswap_db_w, rk, rj, rd).encode());
1188 }
1189 
as_amswap_db_d(Register rd,Register rj,Register rk)1190 BufferOffset AssemblerLOONG64::as_amswap_db_d(Register rd, Register rj,
1191                                               Register rk) {
1192   spew("amswap_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1193   return writeInst(InstReg(op_amswap_db_d, rk, rj, rd).encode());
1194 }
1195 
as_amadd_db_w(Register rd,Register rj,Register rk)1196 BufferOffset AssemblerLOONG64::as_amadd_db_w(Register rd, Register rj,
1197                                              Register rk) {
1198   spew("amadd_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1199   return writeInst(InstReg(op_amadd_db_w, rk, rj, rd).encode());
1200 }
1201 
as_amadd_db_d(Register rd,Register rj,Register rk)1202 BufferOffset AssemblerLOONG64::as_amadd_db_d(Register rd, Register rj,
1203                                              Register rk) {
1204   spew("amadd_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1205   return writeInst(InstReg(op_amadd_db_d, rk, rj, rd).encode());
1206 }
1207 
as_amand_db_w(Register rd,Register rj,Register rk)1208 BufferOffset AssemblerLOONG64::as_amand_db_w(Register rd, Register rj,
1209                                              Register rk) {
1210   spew("amand_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1211   return writeInst(InstReg(op_amand_db_w, rk, rj, rd).encode());
1212 }
1213 
as_amand_db_d(Register rd,Register rj,Register rk)1214 BufferOffset AssemblerLOONG64::as_amand_db_d(Register rd, Register rj,
1215                                              Register rk) {
1216   spew("amand_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1217   return writeInst(InstReg(op_amand_db_d, rk, rj, rd).encode());
1218 }
1219 
as_amor_db_w(Register rd,Register rj,Register rk)1220 BufferOffset AssemblerLOONG64::as_amor_db_w(Register rd, Register rj,
1221                                             Register rk) {
1222   spew("amor_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1223   return writeInst(InstReg(op_amor_db_w, rk, rj, rd).encode());
1224 }
1225 
as_amor_db_d(Register rd,Register rj,Register rk)1226 BufferOffset AssemblerLOONG64::as_amor_db_d(Register rd, Register rj,
1227                                             Register rk) {
1228   spew("amor_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1229   return writeInst(InstReg(op_amor_db_d, rk, rj, rd).encode());
1230 }
1231 
as_amxor_db_w(Register rd,Register rj,Register rk)1232 BufferOffset AssemblerLOONG64::as_amxor_db_w(Register rd, Register rj,
1233                                              Register rk) {
1234   spew("amxor_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1235   return writeInst(InstReg(op_amxor_db_w, rk, rj, rd).encode());
1236 }
1237 
as_amxor_db_d(Register rd,Register rj,Register rk)1238 BufferOffset AssemblerLOONG64::as_amxor_db_d(Register rd, Register rj,
1239                                              Register rk) {
1240   spew("amxor_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1241   return writeInst(InstReg(op_amxor_db_d, rk, rj, rd).encode());
1242 }
1243 
as_ammax_db_w(Register rd,Register rj,Register rk)1244 BufferOffset AssemblerLOONG64::as_ammax_db_w(Register rd, Register rj,
1245                                              Register rk) {
1246   spew("ammax_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1247   return writeInst(InstReg(op_ammax_db_w, rk, rj, rd).encode());
1248 }
1249 
as_ammax_db_d(Register rd,Register rj,Register rk)1250 BufferOffset AssemblerLOONG64::as_ammax_db_d(Register rd, Register rj,
1251                                              Register rk) {
1252   spew("ammax_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1253   return writeInst(InstReg(op_ammax_db_d, rk, rj, rd).encode());
1254 }
1255 
as_ammin_db_w(Register rd,Register rj,Register rk)1256 BufferOffset AssemblerLOONG64::as_ammin_db_w(Register rd, Register rj,
1257                                              Register rk) {
1258   spew("ammin_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1259   return writeInst(InstReg(op_ammin_db_w, rk, rj, rd).encode());
1260 }
1261 
as_ammin_db_d(Register rd,Register rj,Register rk)1262 BufferOffset AssemblerLOONG64::as_ammin_db_d(Register rd, Register rj,
1263                                              Register rk) {
1264   spew("ammin_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1265   return writeInst(InstReg(op_ammin_db_d, rk, rj, rd).encode());
1266 }
1267 
as_ammax_db_wu(Register rd,Register rj,Register rk)1268 BufferOffset AssemblerLOONG64::as_ammax_db_wu(Register rd, Register rj,
1269                                               Register rk) {
1270   spew("ammax_db_wu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1271   return writeInst(InstReg(op_ammax_db_wu, rk, rj, rd).encode());
1272 }
1273 
as_ammax_db_du(Register rd,Register rj,Register rk)1274 BufferOffset AssemblerLOONG64::as_ammax_db_du(Register rd, Register rj,
1275                                               Register rk) {
1276   spew("ammax_db_du    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1277   return writeInst(InstReg(op_ammax_db_du, rk, rj, rd).encode());
1278 }
1279 
as_ammin_db_wu(Register rd,Register rj,Register rk)1280 BufferOffset AssemblerLOONG64::as_ammin_db_wu(Register rd, Register rj,
1281                                               Register rk) {
1282   spew("ammin_db_wu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1283   return writeInst(InstReg(op_ammin_db_wu, rk, rj, rd).encode());
1284 }
1285 
as_ammin_db_du(Register rd,Register rj,Register rk)1286 BufferOffset AssemblerLOONG64::as_ammin_db_du(Register rd, Register rj,
1287                                               Register rk) {
1288   spew("ammin_db_du    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
1289   return writeInst(InstReg(op_ammin_db_du, rk, rj, rd).encode());
1290 }
1291 
as_ll_w(Register rd,Register rj,int32_t si14)1292 BufferOffset AssemblerLOONG64::as_ll_w(Register rd, Register rj, int32_t si14) {
1293   spew("ll_w   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
1294   MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
1295   return writeInst(InstImm(op_ll_w, si14 >> 2, rj, rd, 14).encode());
1296 }
1297 
as_ll_d(Register rd,Register rj,int32_t si14)1298 BufferOffset AssemblerLOONG64::as_ll_d(Register rd, Register rj, int32_t si14) {
1299   spew("ll_d   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
1300   MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
1301   return writeInst(InstImm(op_ll_d, si14 >> 2, rj, rd, 14).encode());
1302 }
1303 
as_sc_w(Register rd,Register rj,int32_t si14)1304 BufferOffset AssemblerLOONG64::as_sc_w(Register rd, Register rj, int32_t si14) {
1305   spew("sc_w   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
1306   MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
1307   return writeInst(InstImm(op_sc_w, si14 >> 2, rj, rd, 14).encode());
1308 }
1309 
as_sc_d(Register rd,Register rj,int32_t si14)1310 BufferOffset AssemblerLOONG64::as_sc_d(Register rd, Register rj, int32_t si14) {
1311   spew("sc_d   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
1312   MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
1313   return writeInst(InstImm(op_sc_d, si14 >> 2, rj, rd, 14).encode());
1314 }
1315 
1316 // Barrier instructions
as_dbar(int32_t hint)1317 BufferOffset AssemblerLOONG64::as_dbar(int32_t hint) {
1318   MOZ_ASSERT(is_uintN(hint, 15));
1319   spew("dbar   0x%x", hint);
1320   return writeInst(InstImm(op_dbar, hint).encode());
1321 }
1322 
as_ibar(int32_t hint)1323 BufferOffset AssemblerLOONG64::as_ibar(int32_t hint) {
1324   MOZ_ASSERT(is_uintN(hint, 15));
1325   spew("ibar   0x%x", hint);
1326   return writeInst(InstImm(op_ibar, hint).encode());
1327 }
1328 
1329 /* =============================================================== */
1330 
1331 // FP Arithmetic instructions
as_fadd_s(FloatRegister fd,FloatRegister fj,FloatRegister fk)1332 BufferOffset AssemblerLOONG64::as_fadd_s(FloatRegister fd, FloatRegister fj,
1333                                          FloatRegister fk) {
1334   spew("fadd_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1335   return writeInst(InstReg(op_fadd_s, fk, fj, fd).encode());
1336 }
1337 
as_fadd_d(FloatRegister fd,FloatRegister fj,FloatRegister fk)1338 BufferOffset AssemblerLOONG64::as_fadd_d(FloatRegister fd, FloatRegister fj,
1339                                          FloatRegister fk) {
1340   spew("fadd_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1341   return writeInst(InstReg(op_fadd_d, fk, fj, fd).encode());
1342 }
1343 
as_fsub_s(FloatRegister fd,FloatRegister fj,FloatRegister fk)1344 BufferOffset AssemblerLOONG64::as_fsub_s(FloatRegister fd, FloatRegister fj,
1345                                          FloatRegister fk) {
1346   spew("fsub_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1347   return writeInst(InstReg(op_fsub_s, fk, fj, fd).encode());
1348 }
1349 
as_fsub_d(FloatRegister fd,FloatRegister fj,FloatRegister fk)1350 BufferOffset AssemblerLOONG64::as_fsub_d(FloatRegister fd, FloatRegister fj,
1351                                          FloatRegister fk) {
1352   spew("fsub_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1353   return writeInst(InstReg(op_fsub_d, fk, fj, fd).encode());
1354 }
1355 
as_fmul_s(FloatRegister fd,FloatRegister fj,FloatRegister fk)1356 BufferOffset AssemblerLOONG64::as_fmul_s(FloatRegister fd, FloatRegister fj,
1357                                          FloatRegister fk) {
1358   spew("fmul_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1359   return writeInst(InstReg(op_fmul_s, fk, fj, fd).encode());
1360 }
1361 
as_fmul_d(FloatRegister fd,FloatRegister fj,FloatRegister fk)1362 BufferOffset AssemblerLOONG64::as_fmul_d(FloatRegister fd, FloatRegister fj,
1363                                          FloatRegister fk) {
1364   spew("fmul_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1365   return writeInst(InstReg(op_fmul_d, fk, fj, fd).encode());
1366 }
1367 
as_fdiv_s(FloatRegister fd,FloatRegister fj,FloatRegister fk)1368 BufferOffset AssemblerLOONG64::as_fdiv_s(FloatRegister fd, FloatRegister fj,
1369                                          FloatRegister fk) {
1370   spew("fdiv_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1371   return writeInst(InstReg(op_fdiv_s, fk, fj, fd).encode());
1372 }
1373 
as_fdiv_d(FloatRegister fd,FloatRegister fj,FloatRegister fk)1374 BufferOffset AssemblerLOONG64::as_fdiv_d(FloatRegister fd, FloatRegister fj,
1375                                          FloatRegister fk) {
1376   spew("fdiv_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1377   return writeInst(InstReg(op_fdiv_d, fk, fj, fd).encode());
1378 }
1379 
as_fmadd_s(FloatRegister fd,FloatRegister fj,FloatRegister fk,FloatRegister fa)1380 BufferOffset AssemblerLOONG64::as_fmadd_s(FloatRegister fd, FloatRegister fj,
1381                                           FloatRegister fk, FloatRegister fa) {
1382   spew("fmadd_s    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
1383        fa.name());
1384   return writeInst(InstReg(op_fmadd_s, fa, fk, fj, fd).encode());
1385 }
1386 
as_fmadd_d(FloatRegister fd,FloatRegister fj,FloatRegister fk,FloatRegister fa)1387 BufferOffset AssemblerLOONG64::as_fmadd_d(FloatRegister fd, FloatRegister fj,
1388                                           FloatRegister fk, FloatRegister fa) {
1389   spew("fmadd_d    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
1390        fa.name());
1391   return writeInst(InstReg(op_fmadd_d, fa, fk, fj, fd).encode());
1392 }
1393 
as_fmsub_s(FloatRegister fd,FloatRegister fj,FloatRegister fk,FloatRegister fa)1394 BufferOffset AssemblerLOONG64::as_fmsub_s(FloatRegister fd, FloatRegister fj,
1395                                           FloatRegister fk, FloatRegister fa) {
1396   spew("fmsub_s    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
1397        fa.name());
1398   return writeInst(InstReg(op_fmsub_s, fa, fk, fj, fd).encode());
1399 }
1400 
as_fmsub_d(FloatRegister fd,FloatRegister fj,FloatRegister fk,FloatRegister fa)1401 BufferOffset AssemblerLOONG64::as_fmsub_d(FloatRegister fd, FloatRegister fj,
1402                                           FloatRegister fk, FloatRegister fa) {
1403   spew("fmsub_d    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
1404        fa.name());
1405   return writeInst(InstReg(op_fmsub_d, fa, fk, fj, fd).encode());
1406 }
1407 
as_fnmadd_s(FloatRegister fd,FloatRegister fj,FloatRegister fk,FloatRegister fa)1408 BufferOffset AssemblerLOONG64::as_fnmadd_s(FloatRegister fd, FloatRegister fj,
1409                                            FloatRegister fk, FloatRegister fa) {
1410   spew("fnmadd_s    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
1411        fa.name());
1412   return writeInst(InstReg(op_fnmadd_s, fa, fk, fj, fd).encode());
1413 }
1414 
as_fnmadd_d(FloatRegister fd,FloatRegister fj,FloatRegister fk,FloatRegister fa)1415 BufferOffset AssemblerLOONG64::as_fnmadd_d(FloatRegister fd, FloatRegister fj,
1416                                            FloatRegister fk, FloatRegister fa) {
1417   spew("fnmadd_d    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
1418        fa.name());
1419   return writeInst(InstReg(op_fnmadd_d, fa, fk, fj, fd).encode());
1420 }
1421 
as_fnmsub_s(FloatRegister fd,FloatRegister fj,FloatRegister fk,FloatRegister fa)1422 BufferOffset AssemblerLOONG64::as_fnmsub_s(FloatRegister fd, FloatRegister fj,
1423                                            FloatRegister fk, FloatRegister fa) {
1424   spew("fnmsub_s    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
1425        fa.name());
1426   return writeInst(InstReg(op_fnmsub_s, fa, fk, fj, fd).encode());
1427 }
1428 
as_fnmsub_d(FloatRegister fd,FloatRegister fj,FloatRegister fk,FloatRegister fa)1429 BufferOffset AssemblerLOONG64::as_fnmsub_d(FloatRegister fd, FloatRegister fj,
1430                                            FloatRegister fk, FloatRegister fa) {
1431   spew("fnmsub_d    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
1432        fa.name());
1433   return writeInst(InstReg(op_fnmsub_d, fa, fk, fj, fd).encode());
1434 }
1435 
as_fmax_s(FloatRegister fd,FloatRegister fj,FloatRegister fk)1436 BufferOffset AssemblerLOONG64::as_fmax_s(FloatRegister fd, FloatRegister fj,
1437                                          FloatRegister fk) {
1438   spew("fmax_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1439   return writeInst(InstReg(op_fmax_s, fk, fj, fd).encode());
1440 }
1441 
as_fmax_d(FloatRegister fd,FloatRegister fj,FloatRegister fk)1442 BufferOffset AssemblerLOONG64::as_fmax_d(FloatRegister fd, FloatRegister fj,
1443                                          FloatRegister fk) {
1444   spew("fmax_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1445   return writeInst(InstReg(op_fmax_d, fk, fj, fd).encode());
1446 }
1447 
as_fmin_s(FloatRegister fd,FloatRegister fj,FloatRegister fk)1448 BufferOffset AssemblerLOONG64::as_fmin_s(FloatRegister fd, FloatRegister fj,
1449                                          FloatRegister fk) {
1450   spew("fmin_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1451   return writeInst(InstReg(op_fmin_s, fk, fj, fd).encode());
1452 }
1453 
as_fmin_d(FloatRegister fd,FloatRegister fj,FloatRegister fk)1454 BufferOffset AssemblerLOONG64::as_fmin_d(FloatRegister fd, FloatRegister fj,
1455                                          FloatRegister fk) {
1456   spew("fmin_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1457   return writeInst(InstReg(op_fmin_d, fk, fj, fd).encode());
1458 }
1459 
as_fmaxa_s(FloatRegister fd,FloatRegister fj,FloatRegister fk)1460 BufferOffset AssemblerLOONG64::as_fmaxa_s(FloatRegister fd, FloatRegister fj,
1461                                           FloatRegister fk) {
1462   spew("fmaxa_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1463   return writeInst(InstReg(op_fmaxa_s, fk, fj, fd).encode());
1464 }
1465 
as_fmaxa_d(FloatRegister fd,FloatRegister fj,FloatRegister fk)1466 BufferOffset AssemblerLOONG64::as_fmaxa_d(FloatRegister fd, FloatRegister fj,
1467                                           FloatRegister fk) {
1468   spew("fmaxa_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1469   return writeInst(InstReg(op_fmaxa_d, fk, fj, fd).encode());
1470 }
1471 
as_fmina_s(FloatRegister fd,FloatRegister fj,FloatRegister fk)1472 BufferOffset AssemblerLOONG64::as_fmina_s(FloatRegister fd, FloatRegister fj,
1473                                           FloatRegister fk) {
1474   spew("fmina_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1475   return writeInst(InstReg(op_fmina_s, fk, fj, fd).encode());
1476 }
1477 
as_fmina_d(FloatRegister fd,FloatRegister fj,FloatRegister fk)1478 BufferOffset AssemblerLOONG64::as_fmina_d(FloatRegister fd, FloatRegister fj,
1479                                           FloatRegister fk) {
1480   spew("fmina_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1481   return writeInst(InstReg(op_fmina_d, fk, fj, fd).encode());
1482 }
1483 
as_fabs_s(FloatRegister fd,FloatRegister fj)1484 BufferOffset AssemblerLOONG64::as_fabs_s(FloatRegister fd, FloatRegister fj) {
1485   spew("fabs_s    %3s,%3s", fd.name(), fj.name());
1486   return writeInst(InstReg(op_fabs_s, fj, fd).encode());
1487 }
1488 
as_fabs_d(FloatRegister fd,FloatRegister fj)1489 BufferOffset AssemblerLOONG64::as_fabs_d(FloatRegister fd, FloatRegister fj) {
1490   spew("fabs_d    %3s,%3s", fd.name(), fj.name());
1491   return writeInst(InstReg(op_fabs_d, fj, fd).encode());
1492 }
1493 
as_fneg_s(FloatRegister fd,FloatRegister fj)1494 BufferOffset AssemblerLOONG64::as_fneg_s(FloatRegister fd, FloatRegister fj) {
1495   spew("fneg_s    %3s,%3s", fd.name(), fj.name());
1496   return writeInst(InstReg(op_fneg_s, fj, fd).encode());
1497 }
1498 
as_fneg_d(FloatRegister fd,FloatRegister fj)1499 BufferOffset AssemblerLOONG64::as_fneg_d(FloatRegister fd, FloatRegister fj) {
1500   spew("fneg_d    %3s,%3s", fd.name(), fj.name());
1501   return writeInst(InstReg(op_fneg_d, fj, fd).encode());
1502 }
1503 
as_fsqrt_s(FloatRegister fd,FloatRegister fj)1504 BufferOffset AssemblerLOONG64::as_fsqrt_s(FloatRegister fd, FloatRegister fj) {
1505   spew("fsqrt_s    %3s,%3s", fd.name(), fj.name());
1506   return writeInst(InstReg(op_fsqrt_s, fj, fd).encode());
1507 }
1508 
as_fsqrt_d(FloatRegister fd,FloatRegister fj)1509 BufferOffset AssemblerLOONG64::as_fsqrt_d(FloatRegister fd, FloatRegister fj) {
1510   spew("fsqrt_d    %3s,%3s", fd.name(), fj.name());
1511   return writeInst(InstReg(op_fsqrt_d, fj, fd).encode());
1512 }
1513 
as_fcopysign_s(FloatRegister fd,FloatRegister fj,FloatRegister fk)1514 BufferOffset AssemblerLOONG64::as_fcopysign_s(FloatRegister fd,
1515                                               FloatRegister fj,
1516                                               FloatRegister fk) {
1517   spew("fcopysign_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1518   return writeInst(InstReg(op_fcopysign_s, fk, fj, fd).encode());
1519 }
1520 
as_fcopysign_d(FloatRegister fd,FloatRegister fj,FloatRegister fk)1521 BufferOffset AssemblerLOONG64::as_fcopysign_d(FloatRegister fd,
1522                                               FloatRegister fj,
1523                                               FloatRegister fk) {
1524   spew("fcopysign_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
1525   return writeInst(InstReg(op_fcopysign_d, fk, fj, fd).encode());
1526 }
1527 
1528 // FP compare instructions
1529 // fcmp.cond.s and fcmp.cond.d instructions
as_fcmp_cor(FloatFormat fmt,FloatRegister fj,FloatRegister fk,FPConditionBit cd)1530 BufferOffset AssemblerLOONG64::as_fcmp_cor(FloatFormat fmt, FloatRegister fj,
1531                                            FloatRegister fk,
1532                                            FPConditionBit cd) {
1533   if (fmt == DoubleFloat) {
1534     spew("fcmp_cor_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1535     return writeInst(InstReg(op_fcmp_cond_d, COR, fk, fj, cd).encode());
1536   } else {
1537     spew("fcmp_cor_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1538     return writeInst(InstReg(op_fcmp_cond_s, COR, fk, fj, cd).encode());
1539   }
1540 }
1541 
as_fcmp_ceq(FloatFormat fmt,FloatRegister fj,FloatRegister fk,FPConditionBit cd)1542 BufferOffset AssemblerLOONG64::as_fcmp_ceq(FloatFormat fmt, FloatRegister fj,
1543                                            FloatRegister fk,
1544                                            FPConditionBit cd) {
1545   if (fmt == DoubleFloat) {
1546     spew("fcmp_ceq_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1547     return writeInst(InstReg(op_fcmp_cond_d, CEQ, fk, fj, cd).encode());
1548   } else {
1549     spew("fcmp_ceq_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1550     return writeInst(InstReg(op_fcmp_cond_s, CEQ, fk, fj, cd).encode());
1551   }
1552 }
1553 
as_fcmp_cne(FloatFormat fmt,FloatRegister fj,FloatRegister fk,FPConditionBit cd)1554 BufferOffset AssemblerLOONG64::as_fcmp_cne(FloatFormat fmt, FloatRegister fj,
1555                                            FloatRegister fk,
1556                                            FPConditionBit cd) {
1557   if (fmt == DoubleFloat) {
1558     spew("fcmp_cne_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1559     return writeInst(InstReg(op_fcmp_cond_d, CNE, fk, fj, cd).encode());
1560   } else {
1561     spew("fcmp_cne_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1562     return writeInst(InstReg(op_fcmp_cond_s, CNE, fk, fj, cd).encode());
1563   }
1564 }
1565 
as_fcmp_cle(FloatFormat fmt,FloatRegister fj,FloatRegister fk,FPConditionBit cd)1566 BufferOffset AssemblerLOONG64::as_fcmp_cle(FloatFormat fmt, FloatRegister fj,
1567                                            FloatRegister fk,
1568                                            FPConditionBit cd) {
1569   if (fmt == DoubleFloat) {
1570     spew("fcmp_cle_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1571     return writeInst(InstReg(op_fcmp_cond_d, CLE, fk, fj, cd).encode());
1572   } else {
1573     spew("fcmp_cle_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1574     return writeInst(InstReg(op_fcmp_cond_s, CLE, fk, fj, cd).encode());
1575   }
1576 }
1577 
as_fcmp_clt(FloatFormat fmt,FloatRegister fj,FloatRegister fk,FPConditionBit cd)1578 BufferOffset AssemblerLOONG64::as_fcmp_clt(FloatFormat fmt, FloatRegister fj,
1579                                            FloatRegister fk,
1580                                            FPConditionBit cd) {
1581   if (fmt == DoubleFloat) {
1582     spew("fcmp_clt_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1583     return writeInst(InstReg(op_fcmp_cond_d, CLT, fk, fj, cd).encode());
1584   } else {
1585     spew("fcmp_clt_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1586     return writeInst(InstReg(op_fcmp_cond_s, CLT, fk, fj, cd).encode());
1587   }
1588 }
1589 
as_fcmp_cun(FloatFormat fmt,FloatRegister fj,FloatRegister fk,FPConditionBit cd)1590 BufferOffset AssemblerLOONG64::as_fcmp_cun(FloatFormat fmt, FloatRegister fj,
1591                                            FloatRegister fk,
1592                                            FPConditionBit cd) {
1593   if (fmt == DoubleFloat) {
1594     spew("fcmp_cun_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1595     return writeInst(InstReg(op_fcmp_cond_d, CUN, fk, fj, cd).encode());
1596   } else {
1597     spew("fcmp_cun_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1598     return writeInst(InstReg(op_fcmp_cond_s, CUN, fk, fj, cd).encode());
1599   }
1600 }
1601 
as_fcmp_cueq(FloatFormat fmt,FloatRegister fj,FloatRegister fk,FPConditionBit cd)1602 BufferOffset AssemblerLOONG64::as_fcmp_cueq(FloatFormat fmt, FloatRegister fj,
1603                                             FloatRegister fk,
1604                                             FPConditionBit cd) {
1605   if (fmt == DoubleFloat) {
1606     spew("fcmp_cueq_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1607     return writeInst(InstReg(op_fcmp_cond_d, CUEQ, fk, fj, cd).encode());
1608   } else {
1609     spew("fcmp_cueq_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1610     return writeInst(InstReg(op_fcmp_cond_s, CUEQ, fk, fj, cd).encode());
1611   }
1612 }
1613 
as_fcmp_cune(FloatFormat fmt,FloatRegister fj,FloatRegister fk,FPConditionBit cd)1614 BufferOffset AssemblerLOONG64::as_fcmp_cune(FloatFormat fmt, FloatRegister fj,
1615                                             FloatRegister fk,
1616                                             FPConditionBit cd) {
1617   if (fmt == DoubleFloat) {
1618     spew("fcmp_cune_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1619     return writeInst(InstReg(op_fcmp_cond_d, CUNE, fk, fj, cd).encode());
1620   } else {
1621     spew("fcmp_cune_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1622     return writeInst(InstReg(op_fcmp_cond_s, CUNE, fk, fj, cd).encode());
1623   }
1624 }
1625 
as_fcmp_cule(FloatFormat fmt,FloatRegister fj,FloatRegister fk,FPConditionBit cd)1626 BufferOffset AssemblerLOONG64::as_fcmp_cule(FloatFormat fmt, FloatRegister fj,
1627                                             FloatRegister fk,
1628                                             FPConditionBit cd) {
1629   if (fmt == DoubleFloat) {
1630     spew("fcmp_cule_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1631     return writeInst(InstReg(op_fcmp_cond_d, CULE, fk, fj, cd).encode());
1632   } else {
1633     spew("fcmp_cule_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1634     return writeInst(InstReg(op_fcmp_cond_s, CULE, fk, fj, cd).encode());
1635   }
1636 }
1637 
as_fcmp_cult(FloatFormat fmt,FloatRegister fj,FloatRegister fk,FPConditionBit cd)1638 BufferOffset AssemblerLOONG64::as_fcmp_cult(FloatFormat fmt, FloatRegister fj,
1639                                             FloatRegister fk,
1640                                             FPConditionBit cd) {
1641   if (fmt == DoubleFloat) {
1642     spew("fcmp_cult_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1643     return writeInst(InstReg(op_fcmp_cond_d, CULT, fk, fj, cd).encode());
1644   } else {
1645     spew("fcmp_cult_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
1646     return writeInst(InstReg(op_fcmp_cond_s, CULT, fk, fj, cd).encode());
1647   }
1648 }
1649 
1650 // FP conversion instructions
as_fcvt_s_d(FloatRegister fd,FloatRegister fj)1651 BufferOffset AssemblerLOONG64::as_fcvt_s_d(FloatRegister fd, FloatRegister fj) {
1652   spew("fcvt_s_d    %3s,%3s", fd.name(), fj.name());
1653   return writeInst(InstReg(op_fcvt_s_d, fj, fd).encode());
1654 }
1655 
as_fcvt_d_s(FloatRegister fd,FloatRegister fj)1656 BufferOffset AssemblerLOONG64::as_fcvt_d_s(FloatRegister fd, FloatRegister fj) {
1657   spew("fcvt_d_s    %3s,%3s", fd.name(), fj.name());
1658   return writeInst(InstReg(op_fcvt_d_s, fj, fd).encode());
1659 }
1660 
as_ffint_s_w(FloatRegister fd,FloatRegister fj)1661 BufferOffset AssemblerLOONG64::as_ffint_s_w(FloatRegister fd,
1662                                             FloatRegister fj) {
1663   spew("ffint_s_w    %3s,%3s", fd.name(), fj.name());
1664   return writeInst(InstReg(op_ffint_s_w, fj, fd).encode());
1665 }
1666 
as_ffint_s_l(FloatRegister fd,FloatRegister fj)1667 BufferOffset AssemblerLOONG64::as_ffint_s_l(FloatRegister fd,
1668                                             FloatRegister fj) {
1669   spew("ffint_s_l    %3s,%3s", fd.name(), fj.name());
1670   return writeInst(InstReg(op_ffint_s_l, fj, fd).encode());
1671 }
1672 
as_ffint_d_w(FloatRegister fd,FloatRegister fj)1673 BufferOffset AssemblerLOONG64::as_ffint_d_w(FloatRegister fd,
1674                                             FloatRegister fj) {
1675   spew("ffint_d_w    %3s,%3s", fd.name(), fj.name());
1676   return writeInst(InstReg(op_ffint_d_w, fj, fd).encode());
1677 }
1678 
as_ffint_d_l(FloatRegister fd,FloatRegister fj)1679 BufferOffset AssemblerLOONG64::as_ffint_d_l(FloatRegister fd,
1680                                             FloatRegister fj) {
1681   spew("ffint_d_l    %3s,%3s", fd.name(), fj.name());
1682   return writeInst(InstReg(op_ffint_d_l, fj, fd).encode());
1683 }
1684 
as_ftint_w_s(FloatRegister fd,FloatRegister fj)1685 BufferOffset AssemblerLOONG64::as_ftint_w_s(FloatRegister fd,
1686                                             FloatRegister fj) {
1687   spew("ftint_w_s    %3s,%3s", fd.name(), fj.name());
1688   return writeInst(InstReg(op_ftint_w_s, fj, fd).encode());
1689 }
1690 
as_ftint_w_d(FloatRegister fd,FloatRegister fj)1691 BufferOffset AssemblerLOONG64::as_ftint_w_d(FloatRegister fd,
1692                                             FloatRegister fj) {
1693   spew("ftint_w_d    %3s,%3s", fd.name(), fj.name());
1694   return writeInst(InstReg(op_ftint_w_d, fj, fd).encode());
1695 }
1696 
as_ftint_l_s(FloatRegister fd,FloatRegister fj)1697 BufferOffset AssemblerLOONG64::as_ftint_l_s(FloatRegister fd,
1698                                             FloatRegister fj) {
1699   spew("ftint_l_s    %3s,%3s", fd.name(), fj.name());
1700   return writeInst(InstReg(op_ftint_l_s, fj, fd).encode());
1701 }
1702 
as_ftint_l_d(FloatRegister fd,FloatRegister fj)1703 BufferOffset AssemblerLOONG64::as_ftint_l_d(FloatRegister fd,
1704                                             FloatRegister fj) {
1705   spew("ftint_l_d    %3s,%3s", fd.name(), fj.name());
1706   return writeInst(InstReg(op_ftint_l_d, fj, fd).encode());
1707 }
1708 
as_ftintrm_w_s(FloatRegister fd,FloatRegister fj)1709 BufferOffset AssemblerLOONG64::as_ftintrm_w_s(FloatRegister fd,
1710                                               FloatRegister fj) {
1711   spew("ftintrm_w_s    %3s,%3s", fd.name(), fj.name());
1712   return writeInst(InstReg(op_ftintrm_w_s, fj, fd).encode());
1713 }
1714 
as_ftintrm_w_d(FloatRegister fd,FloatRegister fj)1715 BufferOffset AssemblerLOONG64::as_ftintrm_w_d(FloatRegister fd,
1716                                               FloatRegister fj) {
1717   spew("ftintrm_w_d    %3s,%3s", fd.name(), fj.name());
1718   return writeInst(InstReg(op_ftintrm_w_d, fj, fd).encode());
1719 }
1720 
as_ftintrm_l_s(FloatRegister fd,FloatRegister fj)1721 BufferOffset AssemblerLOONG64::as_ftintrm_l_s(FloatRegister fd,
1722                                               FloatRegister fj) {
1723   spew("ftintrm_l_s    %3s,%3s", fd.name(), fj.name());
1724   return writeInst(InstReg(op_ftintrm_l_s, fj, fd).encode());
1725 }
1726 
as_ftintrm_l_d(FloatRegister fd,FloatRegister fj)1727 BufferOffset AssemblerLOONG64::as_ftintrm_l_d(FloatRegister fd,
1728                                               FloatRegister fj) {
1729   spew("ftintrm_l_d    %3s,%3s", fd.name(), fj.name());
1730   return writeInst(InstReg(op_ftintrm_l_d, fj, fd).encode());
1731 }
1732 
as_ftintrp_w_s(FloatRegister fd,FloatRegister fj)1733 BufferOffset AssemblerLOONG64::as_ftintrp_w_s(FloatRegister fd,
1734                                               FloatRegister fj) {
1735   spew("ftintrp_w_s    %3s,%3s", fd.name(), fj.name());
1736   return writeInst(InstReg(op_ftintrp_w_s, fj, fd).encode());
1737 }
1738 
as_ftintrp_w_d(FloatRegister fd,FloatRegister fj)1739 BufferOffset AssemblerLOONG64::as_ftintrp_w_d(FloatRegister fd,
1740                                               FloatRegister fj) {
1741   spew("ftintrp_w_d    %3s,%3s", fd.name(), fj.name());
1742   return writeInst(InstReg(op_ftintrp_w_d, fj, fd).encode());
1743 }
1744 
as_ftintrp_l_s(FloatRegister fd,FloatRegister fj)1745 BufferOffset AssemblerLOONG64::as_ftintrp_l_s(FloatRegister fd,
1746                                               FloatRegister fj) {
1747   spew("ftintrp_l_s    %3s,%3s", fd.name(), fj.name());
1748   return writeInst(InstReg(op_ftintrp_l_s, fj, fd).encode());
1749 }
1750 
as_ftintrp_l_d(FloatRegister fd,FloatRegister fj)1751 BufferOffset AssemblerLOONG64::as_ftintrp_l_d(FloatRegister fd,
1752                                               FloatRegister fj) {
1753   spew("ftintrp_l_d    %3s,%3s", fd.name(), fj.name());
1754   return writeInst(InstReg(op_ftintrp_l_d, fj, fd).encode());
1755 }
1756 
as_ftintrz_w_s(FloatRegister fd,FloatRegister fj)1757 BufferOffset AssemblerLOONG64::as_ftintrz_w_s(FloatRegister fd,
1758                                               FloatRegister fj) {
1759   spew("ftintrz_w_s    %3s,%3s", fd.name(), fj.name());
1760   return writeInst(InstReg(op_ftintrz_w_s, fj, fd).encode());
1761 }
1762 
as_ftintrz_w_d(FloatRegister fd,FloatRegister fj)1763 BufferOffset AssemblerLOONG64::as_ftintrz_w_d(FloatRegister fd,
1764                                               FloatRegister fj) {
1765   spew("ftintrz_w_d    %3s,%3s", fd.name(), fj.name());
1766   return writeInst(InstReg(op_ftintrz_w_d, fj, fd).encode());
1767 }
1768 
as_ftintrz_l_s(FloatRegister fd,FloatRegister fj)1769 BufferOffset AssemblerLOONG64::as_ftintrz_l_s(FloatRegister fd,
1770                                               FloatRegister fj) {
1771   spew("ftintrz_l_s    %3s,%3s", fd.name(), fj.name());
1772   return writeInst(InstReg(op_ftintrz_l_s, fj, fd).encode());
1773 }
1774 
as_ftintrz_l_d(FloatRegister fd,FloatRegister fj)1775 BufferOffset AssemblerLOONG64::as_ftintrz_l_d(FloatRegister fd,
1776                                               FloatRegister fj) {
1777   spew("ftintrz_l_d    %3s,%3s", fd.name(), fj.name());
1778   return writeInst(InstReg(op_ftintrz_l_d, fj, fd).encode());
1779 }
as_ftintrne_w_s(FloatRegister fd,FloatRegister fj)1780 BufferOffset AssemblerLOONG64::as_ftintrne_w_s(FloatRegister fd,
1781                                                FloatRegister fj) {
1782   spew("ftintrne_w_s    %3s,%3s", fd.name(), fj.name());
1783   return writeInst(InstReg(op_ftintrne_w_s, fj, fd).encode());
1784 }
1785 
as_ftintrne_w_d(FloatRegister fd,FloatRegister fj)1786 BufferOffset AssemblerLOONG64::as_ftintrne_w_d(FloatRegister fd,
1787                                                FloatRegister fj) {
1788   spew("ftintrne_w_d    %3s,%3s", fd.name(), fj.name());
1789   return writeInst(InstReg(op_ftintrne_w_d, fj, fd).encode());
1790 }
1791 
as_ftintrne_l_s(FloatRegister fd,FloatRegister fj)1792 BufferOffset AssemblerLOONG64::as_ftintrne_l_s(FloatRegister fd,
1793                                                FloatRegister fj) {
1794   spew("ftintrne_l_s    %3s,%3s", fd.name(), fj.name());
1795   return writeInst(InstReg(op_ftintrne_l_s, fj, fd).encode());
1796 }
1797 
as_ftintrne_l_d(FloatRegister fd,FloatRegister fj)1798 BufferOffset AssemblerLOONG64::as_ftintrne_l_d(FloatRegister fd,
1799                                                FloatRegister fj) {
1800   spew("ftintrne_l_d    %3s,%3s", fd.name(), fj.name());
1801   return writeInst(InstReg(op_ftintrne_l_d, fj, fd).encode());
1802 }
1803 
as_frint_s(FloatRegister fd,FloatRegister fj)1804 BufferOffset AssemblerLOONG64::as_frint_s(FloatRegister fd, FloatRegister fj) {
1805   spew("frint_s    %3s,%3s", fd.name(), fj.name());
1806   return writeInst(InstReg(op_frint_s, fj, fd).encode());
1807 }
1808 
as_frint_d(FloatRegister fd,FloatRegister fj)1809 BufferOffset AssemblerLOONG64::as_frint_d(FloatRegister fd, FloatRegister fj) {
1810   spew("frint_d    %3s,%3s", fd.name(), fj.name());
1811   return writeInst(InstReg(op_frint_d, fj, fd).encode());
1812 }
1813 
1814 // FP mov instructions
as_fmov_s(FloatRegister fd,FloatRegister fj)1815 BufferOffset AssemblerLOONG64::as_fmov_s(FloatRegister fd, FloatRegister fj) {
1816   spew("fmov_s    %3s,%3s", fd.name(), fj.name());
1817   return writeInst(InstReg(op_fmov_s, fj, fd).encode());
1818 }
1819 
as_fmov_d(FloatRegister fd,FloatRegister fj)1820 BufferOffset AssemblerLOONG64::as_fmov_d(FloatRegister fd, FloatRegister fj) {
1821   spew("fmov_d    %3s,%3s", fd.name(), fj.name());
1822   return writeInst(InstReg(op_fmov_d, fj, fd).encode());
1823 }
1824 
as_fsel(FloatRegister fd,FloatRegister fj,FloatRegister fk,FPConditionBit ca)1825 BufferOffset AssemblerLOONG64::as_fsel(FloatRegister fd, FloatRegister fj,
1826                                        FloatRegister fk, FPConditionBit ca) {
1827   spew("fsel      %3s,%3s,%3s,%d", fd.name(), fj.name(), fk.name(), ca);
1828   return writeInst(InstReg(op_fsel, ca, fk, fj, fd).encode());
1829 }
1830 
as_movgr2fr_w(FloatRegister fd,Register rj)1831 BufferOffset AssemblerLOONG64::as_movgr2fr_w(FloatRegister fd, Register rj) {
1832   spew("movgr2fr_w    %3s,%3s", fd.name(), rj.name());
1833   return writeInst(InstReg(op_movgr2fr_w, rj, fd).encode());
1834 }
1835 
as_movgr2fr_d(FloatRegister fd,Register rj)1836 BufferOffset AssemblerLOONG64::as_movgr2fr_d(FloatRegister fd, Register rj) {
1837   spew("movgr2fr_d    %3s,%3s", fd.name(), rj.name());
1838   return writeInst(InstReg(op_movgr2fr_d, rj, fd).encode());
1839 }
1840 
as_movgr2frh_w(FloatRegister fd,Register rj)1841 BufferOffset AssemblerLOONG64::as_movgr2frh_w(FloatRegister fd, Register rj) {
1842   spew("movgr2frh_w    %3s,%3s", fd.name(), rj.name());
1843   return writeInst(InstReg(op_movgr2frh_w, rj, fd).encode());
1844 }
1845 
as_movfr2gr_s(Register rd,FloatRegister fj)1846 BufferOffset AssemblerLOONG64::as_movfr2gr_s(Register rd, FloatRegister fj) {
1847   spew("movfr2gr_s    %3s,%3s", rd.name(), fj.name());
1848   return writeInst(InstReg(op_movfr2gr_s, fj, rd).encode());
1849 }
1850 
as_movfr2gr_d(Register rd,FloatRegister fj)1851 BufferOffset AssemblerLOONG64::as_movfr2gr_d(Register rd, FloatRegister fj) {
1852   spew("movfr2gr_d    %3s,%3s", rd.name(), fj.name());
1853   return writeInst(InstReg(op_movfr2gr_d, fj, rd).encode());
1854 }
1855 
as_movfrh2gr_s(Register rd,FloatRegister fj)1856 BufferOffset AssemblerLOONG64::as_movfrh2gr_s(Register rd, FloatRegister fj) {
1857   spew("movfrh2gr_s    %3s,%3s", rd.name(), fj.name());
1858   return writeInst(InstReg(op_movfrh2gr_s, fj, rd).encode());
1859 }
1860 
as_movgr2fcsr(Register rj)1861 BufferOffset AssemblerLOONG64::as_movgr2fcsr(Register rj) {
1862   spew("movgr2fcsr    %3s", rj.name());
1863   return writeInst(InstReg(op_movgr2fcsr, rj, FCSR).encode());
1864 }
1865 
as_movfcsr2gr(Register rd)1866 BufferOffset AssemblerLOONG64::as_movfcsr2gr(Register rd) {
1867   spew("movfcsr2gr    %3s", rd.name());
1868   return writeInst(InstReg(op_movfcsr2gr, FCSR, rd).encode());
1869 }
1870 
as_movfr2cf(FPConditionBit cd,FloatRegister fj)1871 BufferOffset AssemblerLOONG64::as_movfr2cf(FPConditionBit cd,
1872                                            FloatRegister fj) {
1873   spew("movfr2cf    %d,%3s", cd, fj.name());
1874   return writeInst(InstReg(op_movfr2cf, fj, cd).encode());
1875 }
1876 
as_movcf2fr(FloatRegister fd,FPConditionBit cj)1877 BufferOffset AssemblerLOONG64::as_movcf2fr(FloatRegister fd,
1878                                            FPConditionBit cj) {
1879   spew("movcf2fr    %3s,%d", fd.name(), cj);
1880   return writeInst(InstReg(op_movcf2fr, cj, fd).encode());
1881 }
1882 
as_movgr2cf(FPConditionBit cd,Register rj)1883 BufferOffset AssemblerLOONG64::as_movgr2cf(FPConditionBit cd, Register rj) {
1884   spew("movgr2cf    %d,%3s", cd, rj.name());
1885   return writeInst(InstReg(op_movgr2cf, rj, cd).encode());
1886 }
1887 
as_movcf2gr(Register rd,FPConditionBit cj)1888 BufferOffset AssemblerLOONG64::as_movcf2gr(Register rd, FPConditionBit cj) {
1889   spew("movcf2gr    %3s,%d", rd.name(), cj);
1890   return writeInst(InstReg(op_movcf2gr, cj, rd).encode());
1891 }
1892 
1893 // FP load/store instructions
as_fld_s(FloatRegister fd,Register rj,int32_t si12)1894 BufferOffset AssemblerLOONG64::as_fld_s(FloatRegister fd, Register rj,
1895                                         int32_t si12) {
1896   MOZ_ASSERT(is_intN(si12, 12));
1897   spew("fld_s   %3s,%3s,0x%x", fd.name(), rj.name(), si12);
1898   return writeInst(InstImm(op_fld_s, si12, rj, fd).encode());
1899 }
1900 
as_fld_d(FloatRegister fd,Register rj,int32_t si12)1901 BufferOffset AssemblerLOONG64::as_fld_d(FloatRegister fd, Register rj,
1902                                         int32_t si12) {
1903   MOZ_ASSERT(is_intN(si12, 12));
1904   spew("fld_d   %3s,%3s,0x%x", fd.name(), rj.name(), si12);
1905   return writeInst(InstImm(op_fld_d, si12, rj, fd).encode());
1906 }
1907 
as_fst_s(FloatRegister fd,Register rj,int32_t si12)1908 BufferOffset AssemblerLOONG64::as_fst_s(FloatRegister fd, Register rj,
1909                                         int32_t si12) {
1910   MOZ_ASSERT(is_intN(si12, 12));
1911   spew("fst_s   %3s,%3s,0x%x", fd.name(), rj.name(), si12);
1912   return writeInst(InstImm(op_fst_s, si12, rj, fd).encode());
1913 }
1914 
as_fst_d(FloatRegister fd,Register rj,int32_t si12)1915 BufferOffset AssemblerLOONG64::as_fst_d(FloatRegister fd, Register rj,
1916                                         int32_t si12) {
1917   MOZ_ASSERT(is_intN(si12, 12));
1918   spew("fst_d   %3s,%3s,0x%x", fd.name(), rj.name(), si12);
1919   return writeInst(InstImm(op_fst_d, si12, rj, fd).encode());
1920 }
1921 
as_fldx_s(FloatRegister fd,Register rj,Register rk)1922 BufferOffset AssemblerLOONG64::as_fldx_s(FloatRegister fd, Register rj,
1923                                          Register rk) {
1924   spew("fldx_s    %3s,%3s,%3s", fd.name(), rj.name(), rk.name());
1925   return writeInst(InstReg(op_fldx_s, rk, rj, fd).encode());
1926 }
1927 
as_fldx_d(FloatRegister fd,Register rj,Register rk)1928 BufferOffset AssemblerLOONG64::as_fldx_d(FloatRegister fd, Register rj,
1929                                          Register rk) {
1930   spew("fldx_d    %3s,%3s,%3s", fd.name(), rj.name(), rk.name());
1931   return writeInst(InstReg(op_fldx_d, rk, rj, fd).encode());
1932 }
1933 
as_fstx_s(FloatRegister fd,Register rj,Register rk)1934 BufferOffset AssemblerLOONG64::as_fstx_s(FloatRegister fd, Register rj,
1935                                          Register rk) {
1936   spew("fstx_s    %3s,%3s,%3s", fd.name(), rj.name(), rk.name());
1937   return writeInst(InstReg(op_fstx_s, rk, rj, fd).encode());
1938 }
1939 
as_fstx_d(FloatRegister fd,Register rj,Register rk)1940 BufferOffset AssemblerLOONG64::as_fstx_d(FloatRegister fd, Register rj,
1941                                          Register rk) {
1942   spew("fstx_d    %3s,%3s,%3s", fd.name(), rj.name(), rk.name());
1943   return writeInst(InstReg(op_fstx_d, rk, rj, fd).encode());
1944 }
1945 
1946 /* ========================================================================= */
1947 
bind(Label * label,BufferOffset boff)1948 void AssemblerLOONG64::bind(Label* label, BufferOffset boff) {
1949   spew(".set Llabel %p", label);
1950   // If our caller didn't give us an explicit target to bind to
1951   // then we want to bind to the location of the next instruction
1952   BufferOffset dest = boff.assigned() ? boff : nextOffset();
1953   if (label->used()) {
1954     int32_t next;
1955 
1956     // A used label holds a link to branch that uses it.
1957     BufferOffset b(label);
1958     do {
1959       // Even a 0 offset may be invalid if we're out of memory.
1960       if (oom()) {
1961         return;
1962       }
1963 
1964       Instruction* inst = editSrc(b);
1965 
1966       // Second word holds a pointer to the next branch in label's chain.
1967       next = inst[1].encode();
1968       bind(reinterpret_cast<InstImm*>(inst), b.getOffset(), dest.getOffset());
1969 
1970       b = BufferOffset(next);
1971     } while (next != LabelBase::INVALID_OFFSET);
1972   }
1973   label->bind(dest.getOffset());
1974 }
1975 
retarget(Label * label,Label * target)1976 void AssemblerLOONG64::retarget(Label* label, Label* target) {
1977   spew("retarget %p -> %p", label, target);
1978   if (label->used() && !oom()) {
1979     if (target->bound()) {
1980       bind(label, BufferOffset(target));
1981     } else if (target->used()) {
1982       // The target is not bound but used. Prepend label's branch list
1983       // onto target's.
1984       int32_t next;
1985       BufferOffset labelBranchOffset(label);
1986 
1987       // Find the head of the use chain for label.
1988       do {
1989         Instruction* inst = editSrc(labelBranchOffset);
1990 
1991         // Second word holds a pointer to the next branch in chain.
1992         next = inst[1].encode();
1993         labelBranchOffset = BufferOffset(next);
1994       } while (next != LabelBase::INVALID_OFFSET);
1995 
1996       // Then patch the head of label's use chain to the tail of
1997       // target's use chain, prepending the entire use chain of target.
1998       Instruction* inst = editSrc(labelBranchOffset);
1999       int32_t prev = target->offset();
2000       target->use(label->offset());
2001       inst[1].setData(prev);
2002     } else {
2003       // The target is unbound and unused.  We can just take the head of
2004       // the list hanging off of label, and dump that into target.
2005       target->use(label->offset());
2006     }
2007   }
2008   label->reset();
2009 }
2010 
dbg_break()2011 void dbg_break() {}
2012 
as_break(uint32_t code)2013 void AssemblerLOONG64::as_break(uint32_t code) {
2014   MOZ_ASSERT(code <= MAX_BREAK_CODE);
2015   spew("break %d", code);
2016   writeInst(InstImm(op_break, code).encode());
2017 }
2018 
2019 // This just stomps over memory with 32 bits of raw data. Its purpose is to
2020 // overwrite the call of JITed code with 32 bits worth of an offset. This will
2021 // is only meant to function on code that has been invalidated, so it should
2022 // be totally safe. Since that instruction will never be executed again, a
2023 // ICache flush should not be necessary
PatchWrite_Imm32(CodeLocationLabel label,Imm32 imm)2024 void AssemblerLOONG64::PatchWrite_Imm32(CodeLocationLabel label, Imm32 imm) {
2025   // Raw is going to be the return address.
2026   uint32_t* raw = (uint32_t*)label.raw();
2027   // Overwrite the 4 bytes before the return address, which will
2028   // end up being the call instruction.
2029   *(raw - 1) = imm.value;
2030 }
2031 
NextInstruction(uint8_t * inst_,uint32_t * count)2032 uint8_t* AssemblerLOONG64::NextInstruction(uint8_t* inst_, uint32_t* count) {
2033   Instruction* inst = reinterpret_cast<Instruction*>(inst_);
2034   if (count != nullptr) {
2035     *count += sizeof(Instruction);
2036   }
2037   return reinterpret_cast<uint8_t*>(inst->next());
2038 }
2039 
ToggleToJmp(CodeLocationLabel inst_)2040 void AssemblerLOONG64::ToggleToJmp(CodeLocationLabel inst_) {
2041   InstImm* inst = (InstImm*)inst_.raw();
2042 
2043   MOZ_ASSERT(inst->extractBitField(31, 26) == (uint32_t)op_addu16i_d >> 26);
2044   // We converted beq to addu16i_d, so now we restore it.
2045   inst->setOpcode(op_beq, 6);
2046 }
2047 
ToggleToCmp(CodeLocationLabel inst_)2048 void AssemblerLOONG64::ToggleToCmp(CodeLocationLabel inst_) {
2049   InstImm* inst = (InstImm*)inst_.raw();
2050 
2051   // toggledJump is allways used for short jumps.
2052   MOZ_ASSERT(inst->extractBitField(31, 26) == (uint32_t)op_beq >> 26);
2053   // Replace "beq $zero, $zero, offset" with "addu16i_d $zero, $zero, offset"
2054   inst->setOpcode(op_addu16i_d, 6);
2055 }
2056 
2057 // Since there are no pools in LoongArch64 implementation, this should be
2058 // simple.
next()2059 Instruction* Instruction::next() { return this + 1; }
2060 
invertBranch(InstImm branch,BOffImm16 skipOffset)2061 InstImm AssemblerLOONG64::invertBranch(InstImm branch, BOffImm16 skipOffset) {
2062   uint32_t rj = 0;
2063   OpcodeField opcode = (OpcodeField)((branch.extractBitField(31, 26)) << 26);
2064   switch (opcode) {
2065     case op_beq:
2066       branch.setBOffImm16(skipOffset);
2067       branch.setOpcode(op_bne, 6);
2068       return branch;
2069     case op_bne:
2070       branch.setBOffImm16(skipOffset);
2071       branch.setOpcode(op_beq, 6);
2072       return branch;
2073     case op_bge:
2074       branch.setBOffImm16(skipOffset);
2075       branch.setOpcode(op_blt, 6);
2076       return branch;
2077     case op_bgeu:
2078       branch.setBOffImm16(skipOffset);
2079       branch.setOpcode(op_bltu, 6);
2080       return branch;
2081     case op_blt:
2082       branch.setBOffImm16(skipOffset);
2083       branch.setOpcode(op_bge, 6);
2084       return branch;
2085     case op_bltu:
2086       branch.setBOffImm16(skipOffset);
2087       branch.setOpcode(op_bgeu, 6);
2088       return branch;
2089     case op_beqz:
2090       branch.setBOffImm16(skipOffset);
2091       branch.setOpcode(op_bnez, 6);
2092       return branch;
2093     case op_bnez:
2094       branch.setBOffImm16(skipOffset);
2095       branch.setOpcode(op_beqz, 6);
2096       return branch;
2097     case op_bcz:
2098       branch.setBOffImm16(skipOffset);
2099       rj = branch.extractRJ();
2100       if (rj & 0x8) {
2101         branch.setRJ(rj & 0x17);
2102       } else {
2103         branch.setRJ(rj | 0x8);
2104       }
2105       return branch;
2106     default:
2107       MOZ_CRASH("Error creating long branch.");
2108   }
2109 }
2110 
2111 #ifdef JS_JITSPEW
decodeBranchInstAndSpew(InstImm branch)2112 void AssemblerLOONG64::decodeBranchInstAndSpew(InstImm branch) {
2113   OpcodeField opcode = (OpcodeField)((branch.extractBitField(31, 26)) << 26);
2114   uint32_t rd_id;
2115   uint32_t rj_id;
2116   uint32_t cj_id;
2117   uint32_t immi = branch.extractImm16Value();
2118   switch (opcode) {
2119     case op_beq:
2120       rd_id = branch.extractRD();
2121       rj_id = branch.extractRJ();
2122       spew("beq    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
2123            Registers::GetName(rj_id), Registers::GetName(rd_id));
2124       break;
2125     case op_bne:
2126       rd_id = branch.extractRD();
2127       rj_id = branch.extractRJ();
2128       spew("bne    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
2129            Registers::GetName(rj_id), Registers::GetName(rd_id));
2130       break;
2131     case op_bge:
2132       rd_id = branch.extractRD();
2133       rj_id = branch.extractRJ();
2134       spew("bge    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
2135            Registers::GetName(rj_id), Registers::GetName(rd_id));
2136       break;
2137     case op_bgeu:
2138       rd_id = branch.extractRD();
2139       rj_id = branch.extractRJ();
2140       spew("bgeu    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
2141            Registers::GetName(rj_id), Registers::GetName(rd_id));
2142       break;
2143     case op_blt:
2144       rd_id = branch.extractRD();
2145       rj_id = branch.extractRJ();
2146       spew("blt    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
2147            Registers::GetName(rj_id), Registers::GetName(rd_id));
2148       break;
2149     case op_bltu:
2150       rd_id = branch.extractRD();
2151       rj_id = branch.extractRJ();
2152       spew("bltu    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
2153            Registers::GetName(rj_id), Registers::GetName(rd_id));
2154       break;
2155     case op_beqz:
2156       rd_id = branch.extractRD();
2157       rj_id = branch.extractRJ();
2158       spew("beqz    0x%x,%3s,0x%x", (int32_t(immi << 18) >> 16) + 4,
2159            Registers::GetName(rj_id), rd_id);
2160       break;
2161     case op_bnez:
2162       rd_id = branch.extractRD();
2163       rj_id = branch.extractRJ();
2164       spew("bnez    0x%x,%3s,0x%x", (int32_t(immi << 18) >> 16) + 4,
2165            Registers::GetName(rj_id), rd_id);
2166       break;
2167     case op_bcz:
2168       rd_id = branch.extractRD();
2169       rj_id = branch.extractRJ();
2170       cj_id = branch.extractBitField(CJShift + CJBits - 1, CJShift);
2171       if (rj_id & 0x8) {
2172         spew("bcnez    0x%x,FCC%d,0x%x", (int32_t(immi << 18) >> 16) + 4, cj_id,
2173              rd_id);
2174       } else {
2175         spew("bceqz    0x%x,FCC%d,0x%x", (int32_t(immi << 18) >> 16) + 4, cj_id,
2176              rd_id);
2177       }
2178       break;
2179     case op_jirl:
2180       rd_id = branch.extractRD();
2181       rj_id = branch.extractRJ();
2182       spew("beqz    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
2183            Registers::GetName(rj_id), Registers::GetName(rd_id));
2184       break;
2185     default:
2186       MOZ_CRASH("Error disassemble branch.");
2187   }
2188 }
2189 #endif
2190 
executableCopy(uint8_t * buffer)2191 void Assembler::executableCopy(uint8_t* buffer) {
2192   MOZ_ASSERT(isFinished);
2193   m_buffer.executableCopy(buffer);
2194 }
2195 
GetPointer(uint8_t * instPtr)2196 uintptr_t Assembler::GetPointer(uint8_t* instPtr) {
2197   Instruction* inst = (Instruction*)instPtr;
2198   return Assembler::ExtractLoad64Value(inst);
2199 }
2200 
CodeFromJump(Instruction * jump)2201 static JitCode* CodeFromJump(Instruction* jump) {
2202   uint8_t* target = (uint8_t*)Assembler::ExtractLoad64Value(jump);
2203   return JitCode::FromExecutable(target);
2204 }
2205 
TraceJumpRelocations(JSTracer * trc,JitCode * code,CompactBufferReader & reader)2206 void Assembler::TraceJumpRelocations(JSTracer* trc, JitCode* code,
2207                                      CompactBufferReader& reader) {
2208   while (reader.more()) {
2209     JitCode* child =
2210         CodeFromJump((Instruction*)(code->raw() + reader.readUnsigned()));
2211     TraceManuallyBarrieredEdge(trc, &child, "rel32");
2212   }
2213 }
2214 
TraceOneDataRelocation(JSTracer * trc,mozilla::Maybe<AutoWritableJitCode> & awjc,JitCode * code,Instruction * inst)2215 static void TraceOneDataRelocation(JSTracer* trc,
2216                                    mozilla::Maybe<AutoWritableJitCode>& awjc,
2217                                    JitCode* code, Instruction* inst) {
2218   void* ptr = (void*)Assembler::ExtractLoad64Value(inst);
2219   void* prior = ptr;
2220 
2221   // Data relocations can be for Values or for raw pointers. If a Value is
2222   // zero-tagged, we can trace it as if it were a raw pointer. If a Value
2223   // is not zero-tagged, we have to interpret it as a Value to ensure that the
2224   // tag bits are masked off to recover the actual pointer.
2225   uintptr_t word = reinterpret_cast<uintptr_t>(ptr);
2226   if (word >> JSVAL_TAG_SHIFT) {
2227     // This relocation is a Value with a non-zero tag.
2228     Value v = Value::fromRawBits(word);
2229     TraceManuallyBarrieredEdge(trc, &v, "jit-masm-value");
2230     ptr = (void*)v.bitsAsPunboxPointer();
2231   } else {
2232     // This relocation is a raw pointer or a Value with a zero tag.
2233     // No barrier needed since these are constants.
2234     TraceManuallyBarrieredGenericPointerEdge(
2235         trc, reinterpret_cast<gc::Cell**>(&ptr), "jit-masm-ptr");
2236   }
2237 
2238   if (ptr != prior) {
2239     if (awjc.isNothing()) {
2240       awjc.emplace(code);
2241     }
2242     Assembler::UpdateLoad64Value(inst, uint64_t(ptr));
2243   }
2244 }
2245 
2246 /* static */
TraceDataRelocations(JSTracer * trc,JitCode * code,CompactBufferReader & reader)2247 void Assembler::TraceDataRelocations(JSTracer* trc, JitCode* code,
2248                                      CompactBufferReader& reader) {
2249   mozilla::Maybe<AutoWritableJitCode> awjc;
2250   while (reader.more()) {
2251     size_t offset = reader.readUnsigned();
2252     Instruction* inst = (Instruction*)(code->raw() + offset);
2253     TraceOneDataRelocation(trc, awjc, code, inst);
2254   }
2255 }
2256 
Bind(uint8_t * rawCode,const CodeLabel & label)2257 void Assembler::Bind(uint8_t* rawCode, const CodeLabel& label) {
2258   if (label.patchAt().bound()) {
2259     auto mode = label.linkMode();
2260     intptr_t offset = label.patchAt().offset();
2261     intptr_t target = label.target().offset();
2262 
2263     if (mode == CodeLabel::RawPointer) {
2264       *reinterpret_cast<const void**>(rawCode + offset) = rawCode + target;
2265     } else {
2266       MOZ_ASSERT(mode == CodeLabel::MoveImmediate ||
2267                  mode == CodeLabel::JumpImmediate);
2268       Instruction* inst = (Instruction*)(rawCode + offset);
2269       Assembler::UpdateLoad64Value(inst, (uint64_t)(rawCode + target));
2270     }
2271   }
2272 }
2273 
bind(InstImm * inst,uintptr_t branch,uintptr_t target)2274 void Assembler::bind(InstImm* inst, uintptr_t branch, uintptr_t target) {
2275   int64_t offset = target - branch;
2276   InstImm inst_jirl = InstImm(op_jirl, BOffImm16(0), zero, ra);
2277   InstImm inst_beq = InstImm(op_beq, BOffImm16(0), zero, zero);
2278 
2279   // If encoded offset is 4, then the jump must be short
2280   if (BOffImm16(inst[0]).decode() == 4) {
2281     MOZ_ASSERT(BOffImm16::IsInRange(offset));
2282     inst[0].setBOffImm16(BOffImm16(offset));
2283     inst[1].makeNop();  // because before set INVALID_OFFSET
2284     return;
2285   }
2286 
2287   // Generate the long jump for calls because return address has to be the
2288   // address after the reserved block.
2289   if (inst[0].encode() == inst_jirl.encode()) {
2290     addLongJump(BufferOffset(branch), BufferOffset(target));
2291     Assembler::WriteLoad64Instructions(inst, ScratchRegister,
2292                                        LabelBase::INVALID_OFFSET);
2293     inst[3].makeNop();  // There are 1 nop.
2294     inst[4] = InstImm(op_jirl, BOffImm16(0), ScratchRegister, ra);
2295     return;
2296   }
2297 
2298   if (BOffImm16::IsInRange(offset)) {
2299     // Skip trailing nops .
2300     bool skipNops = (inst[0].encode() != inst_jirl.encode() &&
2301                      inst[0].encode() != inst_beq.encode());
2302 
2303     inst[0].setBOffImm16(BOffImm16(offset));
2304     inst[1].makeNop();
2305 
2306     if (skipNops) {
2307       inst[2] = InstImm(op_bge, BOffImm16(3 * sizeof(uint32_t)), zero, zero);
2308       // There are 2 nops after this
2309     }
2310     return;
2311   }
2312 
2313   if (inst[0].encode() == inst_beq.encode()) {
2314     // Handle long unconditional jump. Only four 4 instruction.
2315     addLongJump(BufferOffset(branch), BufferOffset(target));
2316     Assembler::WriteLoad64Instructions(inst, ScratchRegister,
2317                                        LabelBase::INVALID_OFFSET);
2318     inst[3] = InstImm(op_jirl, BOffImm16(0), ScratchRegister, zero);
2319   } else {
2320     // Handle long conditional jump.
2321     inst[0] = invertBranch(inst[0], BOffImm16(5 * sizeof(uint32_t)));
2322     // No need for a "nop" here because we can clobber scratch.
2323     addLongJump(BufferOffset(branch + sizeof(uint32_t)), BufferOffset(target));
2324     Assembler::WriteLoad64Instructions(&inst[1], ScratchRegister,
2325                                        LabelBase::INVALID_OFFSET);
2326     inst[4] = InstImm(op_jirl, BOffImm16(0), ScratchRegister, zero);
2327   }
2328 }
2329 
processCodeLabels(uint8_t * rawCode)2330 void Assembler::processCodeLabels(uint8_t* rawCode) {
2331   for (const CodeLabel& label : codeLabels_) {
2332     Bind(rawCode, label);
2333   }
2334 }
2335 
PatchWrite_NearCallSize()2336 uint32_t Assembler::PatchWrite_NearCallSize() {
2337   // Load an address needs 3 instructions, and a jump.
2338   return (3 + 1) * sizeof(uint32_t);
2339 }
2340 
PatchWrite_NearCall(CodeLocationLabel start,CodeLocationLabel toCall)2341 void Assembler::PatchWrite_NearCall(CodeLocationLabel start,
2342                                     CodeLocationLabel toCall) {
2343   Instruction* inst = (Instruction*)start.raw();
2344   uint8_t* dest = toCall.raw();
2345 
2346   // Overwrite whatever instruction used to be here with a call.
2347   // Always use long jump for two reasons:
2348   // - Jump has to be the same size because of PatchWrite_NearCallSize.
2349   // - Return address has to be at the end of replaced block.
2350   // Short jump wouldn't be more efficient.
2351   Assembler::WriteLoad64Instructions(inst, ScratchRegister, (uint64_t)dest);
2352   inst[3] = InstImm(op_jirl, BOffImm16(0), ScratchRegister, ra);
2353 }
2354 
ExtractLoad64Value(Instruction * inst0)2355 uint64_t Assembler::ExtractLoad64Value(Instruction* inst0) {
2356   InstImm* i0 = (InstImm*)inst0;
2357   InstImm* i1 = (InstImm*)i0->next();
2358   InstImm* i2 = (InstImm*)i1->next();
2359   InstImm* i3 = (InstImm*)i2->next();
2360 
2361   MOZ_ASSERT((i0->extractBitField(31, 25)) == ((uint32_t)op_lu12i_w >> 25));
2362   MOZ_ASSERT((i1->extractBitField(31, 22)) == ((uint32_t)op_ori >> 22));
2363   MOZ_ASSERT((i2->extractBitField(31, 25)) == ((uint32_t)op_lu32i_d >> 25));
2364 
2365   if ((i3->extractBitField(31, 22)) == ((uint32_t)op_lu52i_d >> 22)) {
2366     // Li64
2367     uint64_t value =
2368         (uint64_t(i0->extractBitField(Imm20Bits + Imm20Shift - 1, Imm20Shift))
2369          << 12) |
2370         (uint64_t(
2371             i1->extractBitField(Imm12Bits + Imm12Shift - 1, Imm12Shift))) |
2372         (uint64_t(i2->extractBitField(Imm20Bits + Imm20Shift - 1, Imm20Shift))
2373          << 32) |
2374         (uint64_t(i3->extractBitField(Imm12Bits + Imm12Shift - 1, Imm12Shift))
2375          << 52);
2376     return value;
2377   } else {
2378     // Li48
2379     uint64_t value =
2380         (uint64_t(i0->extractBitField(Imm20Bits + Imm20Shift - 1, Imm20Shift))
2381          << 12) |
2382         (uint64_t(
2383             i1->extractBitField(Imm12Bits + Imm12Shift - 1, Imm12Shift))) |
2384         (uint64_t(i2->extractBitField(Imm20Bits + Imm20Shift - 1, Imm20Shift))
2385          << 32);
2386 
2387     return uint64_t((int64_t(value) << 16) >> 16);
2388   }
2389 }
2390 
UpdateLoad64Value(Instruction * inst0,uint64_t value)2391 void Assembler::UpdateLoad64Value(Instruction* inst0, uint64_t value) {
2392   // Todo: with ma_liPatchable
2393   InstImm* i0 = (InstImm*)inst0;
2394   InstImm* i1 = (InstImm*)i0->next();
2395   InstImm* i2 = (InstImm*)i1->next();
2396   InstImm* i3 = (InstImm*)i2->next();
2397 
2398   MOZ_ASSERT((i0->extractBitField(31, 25)) == ((uint32_t)op_lu12i_w >> 25));
2399   MOZ_ASSERT((i1->extractBitField(31, 22)) == ((uint32_t)op_ori >> 22));
2400   MOZ_ASSERT((i2->extractBitField(31, 25)) == ((uint32_t)op_lu32i_d >> 25));
2401 
2402   if ((i3->extractBitField(31, 22)) == ((uint32_t)op_lu52i_d >> 22)) {
2403     // Li64
2404     *i0 = InstImm(op_lu12i_w, (int32_t)((value >> 12) & 0xfffff),
2405                   Register::FromCode(i0->extractRD()), false);
2406     *i1 = InstImm(op_ori, (int32_t)(value & 0xfff),
2407                   Register::FromCode(i1->extractRJ()),
2408                   Register::FromCode(i1->extractRD()), 12);
2409     *i2 = InstImm(op_lu32i_d, (int32_t)((value >> 32) & 0xfffff),
2410                   Register::FromCode(i2->extractRD()), false);
2411     *i3 = InstImm(op_lu52i_d, (int32_t)((value >> 52) & 0xfff),
2412                   Register::FromCode(i3->extractRJ()),
2413                   Register::FromCode(i3->extractRD()), 12);
2414   } else {
2415     // Li48
2416     *i0 = InstImm(op_lu12i_w, (int32_t)((value >> 12) & 0xfffff),
2417                   Register::FromCode(i0->extractRD()), false);
2418     *i1 = InstImm(op_ori, (int32_t)(value & 0xfff),
2419                   Register::FromCode(i1->extractRJ()),
2420                   Register::FromCode(i1->extractRD()), 12);
2421     *i2 = InstImm(op_lu32i_d, (int32_t)((value >> 32) & 0xfffff),
2422                   Register::FromCode(i2->extractRD()), false);
2423   }
2424 }
2425 
WriteLoad64Instructions(Instruction * inst0,Register reg,uint64_t value)2426 void Assembler::WriteLoad64Instructions(Instruction* inst0, Register reg,
2427                                         uint64_t value) {
2428   Instruction* inst1 = inst0->next();
2429   Instruction* inst2 = inst1->next();
2430   *inst0 = InstImm(op_lu12i_w, (int32_t)((value >> 12) & 0xfffff), reg, false);
2431   *inst1 = InstImm(op_ori, (int32_t)(value & 0xfff), reg, reg, 12);
2432   *inst2 = InstImm(op_lu32i_d, (int32_t)((value >> 32) & 0xfffff), reg, false);
2433 }
2434 
PatchDataWithValueCheck(CodeLocationLabel label,ImmPtr newValue,ImmPtr expectedValue)2435 void Assembler::PatchDataWithValueCheck(CodeLocationLabel label,
2436                                         ImmPtr newValue, ImmPtr expectedValue) {
2437   PatchDataWithValueCheck(label, PatchedImmPtr(newValue.value),
2438                           PatchedImmPtr(expectedValue.value));
2439 }
2440 
PatchDataWithValueCheck(CodeLocationLabel label,PatchedImmPtr newValue,PatchedImmPtr expectedValue)2441 void Assembler::PatchDataWithValueCheck(CodeLocationLabel label,
2442                                         PatchedImmPtr newValue,
2443                                         PatchedImmPtr expectedValue) {
2444   Instruction* inst = (Instruction*)label.raw();
2445 
2446   // Extract old Value
2447   DebugOnly<uint64_t> value = Assembler::ExtractLoad64Value(inst);
2448   MOZ_ASSERT(value == uint64_t(expectedValue.value));
2449 
2450   // Replace with new value
2451   Assembler::UpdateLoad64Value(inst, uint64_t(newValue.value));
2452 }
2453 
ExtractInstructionImmediate(uint8_t * code)2454 uint64_t Assembler::ExtractInstructionImmediate(uint8_t* code) {
2455   InstImm* inst = (InstImm*)code;
2456   return Assembler::ExtractLoad64Value(inst);
2457 }
2458 
ToggleCall(CodeLocationLabel inst_,bool enabled)2459 void Assembler::ToggleCall(CodeLocationLabel inst_, bool enabled) {
2460   Instruction* inst = (Instruction*)inst_.raw();
2461   InstImm* i0 = (InstImm*)inst;
2462   InstImm* i1 = (InstImm*)i0->next();
2463   InstImm* i2 = (InstImm*)i1->next();
2464   Instruction* i3 = (Instruction*)i2->next();
2465 
2466   MOZ_ASSERT((i0->extractBitField(31, 25)) == ((uint32_t)op_lu12i_w >> 25));
2467   MOZ_ASSERT((i1->extractBitField(31, 22)) == ((uint32_t)op_ori >> 22));
2468   MOZ_ASSERT((i2->extractBitField(31, 25)) == ((uint32_t)op_lu32i_d >> 25));
2469 
2470   if (enabled) {
2471     MOZ_ASSERT((i3->extractBitField(31, 25)) != ((uint32_t)op_lu12i_w >> 25));
2472     InstImm jirl = InstImm(op_jirl, BOffImm16(0), ScratchRegister, ra);
2473     *i3 = jirl;
2474   } else {
2475     InstNOP nop;
2476     *i3 = nop;
2477   }
2478 }
2479