1// Copyright 2017 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_WASM_BASELINE_MIPS_LIFTOFF_ASSEMBLER_MIPS_H_
6#define V8_WASM_BASELINE_MIPS_LIFTOFF_ASSEMBLER_MIPS_H_
7
8#include "src/base/platform/wrappers.h"
9#include "src/heap/memory-chunk.h"
10#include "src/wasm/baseline/liftoff-assembler.h"
11#include "src/wasm/wasm-objects.h"
12
13namespace v8 {
14namespace internal {
15namespace wasm {
16
17namespace liftoff {
18
19inline constexpr Condition ToCondition(LiftoffCondition liftoff_cond) {
20  switch (liftoff_cond) {
21    case kEqual:
22      return eq;
23    case kUnequal:
24      return ne;
25    case kSignedLessThan:
26      return lt;
27    case kSignedLessEqual:
28      return le;
29    case kSignedGreaterThan:
30      return gt;
31    case kSignedGreaterEqual:
32      return ge;
33    case kUnsignedLessThan:
34      return ult;
35    case kUnsignedLessEqual:
36      return ule;
37    case kUnsignedGreaterThan:
38      return ugt;
39    case kUnsignedGreaterEqual:
40      return uge;
41  }
42}
43
44//  half
45//  slot        Frame
46//  -----+--------------------+---------------------------
47//  n+3  |   parameter n      |
48//  ...  |       ...          |
49//   4   |   parameter 1      | or parameter 2
50//   3   |   parameter 0      | or parameter 1
51//   2   |  (result address)  | or parameter 0
52//  -----+--------------------+---------------------------
53//   1   | return addr (ra)   |
54//   0   | previous frame (fp)|
55//  -----+--------------------+  <-- frame ptr (fp)
56//  -1   | StackFrame::WASM   |
57//  -2   |    instance        |
58//  -3   |    feedback vector |
59//  -4   |    tiering budget  |
60//  -----+--------------------+---------------------------
61//  -5   |    slot 0 (high)   |   ^
62//  -6   |    slot 0 (low)    |   |
63//  -7   |    slot 1 (high)   | Frame slots
64//  -8   |    slot 1 (low)    |   |
65//       |                    |   v
66//  -----+--------------------+  <-- stack ptr (sp)
67//
68#if defined(V8_TARGET_BIG_ENDIAN)
69constexpr int32_t kLowWordOffset = 4;
70constexpr int32_t kHighWordOffset = 0;
71#else
72constexpr int32_t kLowWordOffset = 0;
73constexpr int32_t kHighWordOffset = 4;
74#endif
75
76constexpr int kInstanceOffset = 2 * kSystemPointerSize;
77constexpr int kFeedbackVectorOffset = 3 * kSystemPointerSize;
78constexpr int kTierupBudgetOffset = 4 * kSystemPointerSize;
79
80inline MemOperand GetStackSlot(int offset) { return MemOperand(fp, -offset); }
81
82inline MemOperand GetHalfStackSlot(int offset, RegPairHalf half) {
83  int32_t half_offset =
84      half == kLowWord ? 0 : LiftoffAssembler::kStackSlotSize / 2;
85  return MemOperand(offset > 0 ? fp : sp, -offset + half_offset);
86}
87
88inline MemOperand GetInstanceOperand() { return GetStackSlot(kInstanceOffset); }
89
90inline void Load(LiftoffAssembler* assm, LiftoffRegister dst, Register base,
91                 int32_t offset, ValueKind kind) {
92  MemOperand src(base, offset);
93  switch (kind) {
94    case kI32:
95    case kRef:
96    case kOptRef:
97    case kRtt:
98      assm->lw(dst.gp(), src);
99      break;
100    case kI64:
101      assm->lw(dst.low_gp(),
102               MemOperand(base, offset + liftoff::kLowWordOffset));
103      assm->lw(dst.high_gp(),
104               MemOperand(base, offset + liftoff::kHighWordOffset));
105      break;
106    case kF32:
107      assm->lwc1(dst.fp(), src);
108      break;
109    case kF64:
110      assm->Ldc1(dst.fp(), src);
111      break;
112    default:
113      UNREACHABLE();
114  }
115}
116
117inline void Store(LiftoffAssembler* assm, Register base, int32_t offset,
118                  LiftoffRegister src, ValueKind kind) {
119  MemOperand dst(base, offset);
120  switch (kind) {
121    case kI32:
122    case kOptRef:
123    case kRef:
124    case kRtt:
125      assm->Usw(src.gp(), dst);
126      break;
127    case kI64:
128      assm->Usw(src.low_gp(),
129                MemOperand(base, offset + liftoff::kLowWordOffset));
130      assm->Usw(src.high_gp(),
131                MemOperand(base, offset + liftoff::kHighWordOffset));
132      break;
133    case kF32:
134      assm->Uswc1(src.fp(), dst, t8);
135      break;
136    case kF64:
137      assm->Usdc1(src.fp(), dst, t8);
138      break;
139    default:
140      UNREACHABLE();
141  }
142}
143
144inline void push(LiftoffAssembler* assm, LiftoffRegister reg, ValueKind kind) {
145  switch (kind) {
146    case kI32:
147    case kOptRef:
148    case kRef:
149    case kRtt:
150      assm->push(reg.gp());
151      break;
152    case kI64:
153      assm->Push(reg.high_gp(), reg.low_gp());
154      break;
155    case kF32:
156      assm->addiu(sp, sp, -sizeof(float));
157      assm->swc1(reg.fp(), MemOperand(sp, 0));
158      break;
159    case kF64:
160      assm->addiu(sp, sp, -sizeof(double));
161      assm->Sdc1(reg.fp(), MemOperand(sp, 0));
162      break;
163    default:
164      UNREACHABLE();
165  }
166}
167
168inline Register EnsureNoAlias(Assembler* assm, Register reg,
169                              LiftoffRegister must_not_alias,
170                              UseScratchRegisterScope* temps) {
171  if (reg != must_not_alias.low_gp() && reg != must_not_alias.high_gp())
172    return reg;
173  Register tmp = temps->Acquire();
174  DCHECK_NE(must_not_alias.low_gp(), tmp);
175  DCHECK_NE(must_not_alias.high_gp(), tmp);
176  assm->movz(tmp, reg, zero_reg);
177  return tmp;
178}
179
180#if defined(V8_TARGET_BIG_ENDIAN)
181inline void ChangeEndiannessLoad(LiftoffAssembler* assm, LiftoffRegister dst,
182                                 LoadType type, LiftoffRegList pinned) {
183  bool is_float = false;
184  LiftoffRegister tmp = dst;
185  switch (type.value()) {
186    case LoadType::kI64Load8U:
187    case LoadType::kI64Load8S:
188    case LoadType::kI32Load8U:
189    case LoadType::kI32Load8S:
190      // No need to change endianness for byte size.
191      return;
192    case LoadType::kF32Load:
193      is_float = true;
194      tmp = assm->GetUnusedRegister(kGpReg, pinned);
195      assm->emit_type_conversion(kExprI32ReinterpretF32, tmp, dst);
196      V8_FALLTHROUGH;
197    case LoadType::kI32Load:
198      assm->TurboAssembler::ByteSwapSigned(tmp.gp(), tmp.gp(), 4);
199      break;
200    case LoadType::kI32Load16S:
201      assm->TurboAssembler::ByteSwapSigned(tmp.gp(), tmp.gp(), 2);
202      break;
203    case LoadType::kI32Load16U:
204      assm->TurboAssembler::ByteSwapUnsigned(tmp.gp(), tmp.gp(), 2);
205      break;
206    case LoadType::kF64Load:
207      is_float = true;
208      tmp = assm->GetUnusedRegister(kGpRegPair, pinned);
209      assm->emit_type_conversion(kExprI64ReinterpretF64, tmp, dst);
210      V8_FALLTHROUGH;
211    case LoadType::kI64Load:
212      assm->TurboAssembler::Move(kScratchReg, tmp.low_gp());
213      assm->TurboAssembler::ByteSwapSigned(tmp.low_gp(), tmp.high_gp(), 4);
214      assm->TurboAssembler::ByteSwapSigned(tmp.high_gp(), kScratchReg, 4);
215      break;
216    case LoadType::kI64Load16U:
217      assm->TurboAssembler::ByteSwapUnsigned(tmp.low_gp(), tmp.low_gp(), 2);
218      assm->TurboAssembler::Move(tmp.high_gp(), zero_reg);
219      break;
220    case LoadType::kI64Load16S:
221      assm->TurboAssembler::ByteSwapSigned(tmp.low_gp(), tmp.low_gp(), 2);
222      assm->sra(tmp.high_gp(), tmp.low_gp(), 31);
223      break;
224    case LoadType::kI64Load32U:
225      assm->TurboAssembler::ByteSwapSigned(tmp.low_gp(), tmp.low_gp(), 4);
226      assm->TurboAssembler::Move(tmp.high_gp(), zero_reg);
227      break;
228    case LoadType::kI64Load32S:
229      assm->TurboAssembler::ByteSwapSigned(tmp.low_gp(), tmp.low_gp(), 4);
230      assm->sra(tmp.high_gp(), tmp.low_gp(), 31);
231      break;
232    default:
233      UNREACHABLE();
234  }
235
236  if (is_float) {
237    switch (type.value()) {
238      case LoadType::kF32Load:
239        assm->emit_type_conversion(kExprF32ReinterpretI32, dst, tmp);
240        break;
241      case LoadType::kF64Load:
242        assm->emit_type_conversion(kExprF64ReinterpretI64, dst, tmp);
243        break;
244      default:
245        UNREACHABLE();
246    }
247  }
248}
249
250inline void ChangeEndiannessStore(LiftoffAssembler* assm, LiftoffRegister src,
251                                  StoreType type, LiftoffRegList pinned) {
252  bool is_float = false;
253  LiftoffRegister tmp = src;
254  switch (type.value()) {
255    case StoreType::kI64Store8:
256    case StoreType::kI32Store8:
257      // No need to change endianness for byte size.
258      return;
259    case StoreType::kF32Store:
260      is_float = true;
261      tmp = assm->GetUnusedRegister(kGpReg, pinned);
262      assm->emit_type_conversion(kExprI32ReinterpretF32, tmp, src);
263      V8_FALLTHROUGH;
264    case StoreType::kI32Store:
265      assm->TurboAssembler::ByteSwapSigned(tmp.gp(), tmp.gp(), 4);
266      break;
267    case StoreType::kI32Store16:
268      assm->TurboAssembler::ByteSwapSigned(tmp.gp(), tmp.gp(), 2);
269      break;
270    case StoreType::kF64Store:
271      is_float = true;
272      tmp = assm->GetUnusedRegister(kGpRegPair, pinned);
273      assm->emit_type_conversion(kExprI64ReinterpretF64, tmp, src);
274      V8_FALLTHROUGH;
275    case StoreType::kI64Store:
276      assm->TurboAssembler::Move(kScratchReg, tmp.low_gp());
277      assm->TurboAssembler::ByteSwapSigned(tmp.low_gp(), tmp.high_gp(), 4);
278      assm->TurboAssembler::ByteSwapSigned(tmp.high_gp(), kScratchReg, 4);
279      break;
280    case StoreType::kI64Store32:
281      assm->TurboAssembler::ByteSwapSigned(tmp.low_gp(), tmp.low_gp(), 4);
282      break;
283    case StoreType::kI64Store16:
284      assm->TurboAssembler::ByteSwapSigned(tmp.low_gp(), tmp.low_gp(), 2);
285      break;
286    default:
287      UNREACHABLE();
288  }
289
290  if (is_float) {
291    switch (type.value()) {
292      case StoreType::kF32Store:
293        assm->emit_type_conversion(kExprF32ReinterpretI32, src, tmp);
294        break;
295      case StoreType::kF64Store:
296        assm->emit_type_conversion(kExprF64ReinterpretI64, src, tmp);
297        break;
298      default:
299        UNREACHABLE();
300    }
301  }
302}
303#endif  // V8_TARGET_BIG_ENDIAN
304
305}  // namespace liftoff
306
307int LiftoffAssembler::PrepareStackFrame() {
308  int offset = pc_offset();
309  // When the frame size is bigger than 4KB, we need seven instructions for
310  // stack checking, so we reserve space for this case.
311  addiu(sp, sp, 0);
312  nop();
313  nop();
314  nop();
315  nop();
316  nop();
317  nop();
318  return offset;
319}
320
321void LiftoffAssembler::PrepareTailCall(int num_callee_stack_params,
322                                       int stack_param_delta) {
323  UseScratchRegisterScope temps(this);
324  Register scratch = temps.Acquire();
325
326  // Push the return address and frame pointer to complete the stack frame.
327  Lw(scratch, MemOperand(fp, 4));
328  Push(scratch);
329  Lw(scratch, MemOperand(fp, 0));
330  Push(scratch);
331
332  // Shift the whole frame upwards.
333  int slot_count = num_callee_stack_params + 2;
334  for (int i = slot_count - 1; i >= 0; --i) {
335    Lw(scratch, MemOperand(sp, i * 4));
336    Sw(scratch, MemOperand(fp, (i - stack_param_delta) * 4));
337  }
338
339  // Set the new stack and frame pointer.
340  addiu(sp, fp, -stack_param_delta * 4);
341  Pop(ra, fp);
342}
343
344void LiftoffAssembler::AlignFrameSize() {}
345
346void LiftoffAssembler::PatchPrepareStackFrame(
347    int offset, SafepointTableBuilder* safepoint_table_builder) {
348  // The frame_size includes the frame marker and the instance slot. Both are
349  // pushed as part of frame construction, so we don't need to allocate memory
350  // for them anymore.
351  int frame_size = GetTotalFrameSize() - 2 * kSystemPointerSize;
352
353  // We can't run out of space, just pass anything big enough to not cause the
354  // assembler to try to grow the buffer.
355  constexpr int kAvailableSpace = 256;
356  TurboAssembler patching_assembler(
357      nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
358      ExternalAssemblerBuffer(buffer_start_ + offset, kAvailableSpace));
359
360  if (V8_LIKELY(frame_size < 4 * KB)) {
361    // This is the standard case for small frames: just subtract from SP and be
362    // done with it.
363    patching_assembler.Addu(sp, sp, Operand(-frame_size));
364    return;
365  }
366
367  // The frame size is bigger than 4KB, so we might overflow the available stack
368  // space if we first allocate the frame and then do the stack check (we will
369  // need some remaining stack space for throwing the exception). That's why we
370  // check the available stack space before we allocate the frame. To do this we
371  // replace the {__ Addu(sp, sp, -framesize)} with a jump to OOL code that does
372  // this "extended stack check".
373  //
374  // The OOL code can simply be generated here with the normal assembler,
375  // because all other code generation, including OOL code, has already finished
376  // when {PatchPrepareStackFrame} is called. The function prologue then jumps
377  // to the current {pc_offset()} to execute the OOL code for allocating the
378  // large frame.
379  // Emit the unconditional branch in the function prologue (from {offset} to
380  // {pc_offset()}).
381
382  int imm32 = pc_offset() - offset - 3 * kInstrSize;
383  patching_assembler.BranchLong(imm32);
384
385  // If the frame is bigger than the stack, we throw the stack overflow
386  // exception unconditionally. Thereby we can avoid the integer overflow
387  // check in the condition code.
388  RecordComment("OOL: stack check for large frame");
389  Label continuation;
390  if (frame_size < FLAG_stack_size * 1024) {
391    Register stack_limit = kScratchReg;
392    Lw(stack_limit,
393       FieldMemOperand(kWasmInstanceRegister,
394                       WasmInstanceObject::kRealStackLimitAddressOffset));
395    Lw(stack_limit, MemOperand(stack_limit));
396    Addu(stack_limit, stack_limit, Operand(frame_size));
397    Branch(&continuation, uge, sp, Operand(stack_limit));
398  }
399
400  Call(wasm::WasmCode::kWasmStackOverflow, RelocInfo::WASM_STUB_CALL);
401  // The call will not return; just define an empty safepoint.
402  safepoint_table_builder->DefineSafepoint(this);
403  if (FLAG_debug_code) stop();
404
405  bind(&continuation);
406
407  // Now allocate the stack space. Note that this might do more than just
408  // decrementing the SP;
409  Addu(sp, sp, Operand(-frame_size));
410
411  // Jump back to the start of the function, from {pc_offset()} to
412  // right after the reserved space for the {__ Addu(sp, sp, -framesize)} (which
413  // is a jump now).
414  int func_start_offset = offset + 7 * kInstrSize;
415  imm32 = func_start_offset - pc_offset() - 3 * kInstrSize;
416  BranchLong(imm32);
417}
418
419void LiftoffAssembler::FinishCode() {}
420
421void LiftoffAssembler::AbortCompilation() {}
422
423// static
424constexpr int LiftoffAssembler::StaticStackFrameSize() {
425  return liftoff::kTierupBudgetOffset;
426}
427
428int LiftoffAssembler::SlotSizeForType(ValueKind kind) {
429  switch (kind) {
430    case kS128:
431      return value_kind_size(kind);
432    default:
433      return kStackSlotSize;
434  }
435}
436
437bool LiftoffAssembler::NeedsAlignment(ValueKind kind) {
438  return kind == kS128 || is_reference(kind);
439}
440
441void LiftoffAssembler::LoadConstant(LiftoffRegister reg, WasmValue value,
442                                    RelocInfo::Mode rmode) {
443  switch (value.type().kind()) {
444    case kI32:
445      TurboAssembler::li(reg.gp(), Operand(value.to_i32(), rmode));
446      break;
447    case kI64: {
448      DCHECK(RelocInfo::IsNoInfo(rmode));
449      int32_t low_word = value.to_i64();
450      int32_t high_word = value.to_i64() >> 32;
451      TurboAssembler::li(reg.low_gp(), Operand(low_word));
452      TurboAssembler::li(reg.high_gp(), Operand(high_word));
453      break;
454    }
455    case kF32:
456      TurboAssembler::Move(reg.fp(), value.to_f32_boxed().get_bits());
457      break;
458    case kF64:
459      TurboAssembler::Move(reg.fp(), value.to_f64_boxed().get_bits());
460      break;
461    default:
462      UNREACHABLE();
463  }
464}
465
466void LiftoffAssembler::LoadInstanceFromFrame(Register dst) {
467  lw(dst, liftoff::GetInstanceOperand());
468}
469
470void LiftoffAssembler::LoadFromInstance(Register dst, Register instance,
471                                        int32_t offset, int size) {
472  DCHECK_LE(0, offset);
473  switch (size) {
474    case 1:
475      lb(dst, MemOperand(instance, offset));
476      break;
477    case 4:
478      lw(dst, MemOperand(instance, offset));
479      break;
480    default:
481      UNIMPLEMENTED();
482  }
483}
484
485void LiftoffAssembler::LoadTaggedPointerFromInstance(Register dst,
486                                                     Register instance,
487                                                     int32_t offset) {
488  STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
489  lw(dst, MemOperand(instance, offset));
490}
491
492void LiftoffAssembler::SpillInstance(Register instance) {
493  sw(instance, liftoff::GetInstanceOperand());
494}
495
496void LiftoffAssembler::ResetOSRTarget() {}
497
498void LiftoffAssembler::LoadTaggedPointer(Register dst, Register src_addr,
499                                         Register offset_reg,
500                                         int32_t offset_imm,
501                                         LiftoffRegList pinned) {
502  STATIC_ASSERT(kTaggedSize == kInt32Size);
503  Load(LiftoffRegister(dst), src_addr, offset_reg,
504       static_cast<uint32_t>(offset_imm), LoadType::kI32Load, pinned);
505}
506
507void LiftoffAssembler::LoadFullPointer(Register dst, Register src_addr,
508                                       int32_t offset_imm) {
509  MemOperand src_op = MemOperand(src_addr, offset_imm);
510  lw(dst, src_op);
511}
512
513void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
514                                          Register offset_reg,
515                                          int32_t offset_imm,
516                                          LiftoffRegister src,
517                                          LiftoffRegList pinned,
518                                          SkipWriteBarrier skip_write_barrier) {
519  STATIC_ASSERT(kTaggedSize == kInt32Size);
520  Register dst = no_reg;
521  if (offset_reg != no_reg) {
522    dst = pinned.set(GetUnusedRegister(kGpReg, pinned)).gp();
523    emit_ptrsize_add(dst, dst_addr, offset_reg);
524  }
525  MemOperand dst_op = (offset_reg != no_reg) ? MemOperand(dst, offset_imm)
526                                             : MemOperand(dst_addr, offset_imm);
527  Sw(src.gp(), dst_op);
528
529  if (skip_write_barrier || FLAG_disable_write_barriers) return;
530
531  // The write barrier.
532  Label write_barrier;
533  Label exit;
534  Register scratch = pinned.set(GetUnusedRegister(kGpReg, pinned)).gp();
535  CheckPageFlag(dst_addr, scratch,
536                MemoryChunk::kPointersFromHereAreInterestingMask, ne,
537                &write_barrier);
538  Branch(&exit);
539  bind(&write_barrier);
540  JumpIfSmi(src.gp(), &exit);
541  CheckPageFlag(src.gp(), scratch,
542                MemoryChunk::kPointersToHereAreInterestingMask, eq, &exit);
543  Addu(scratch, dst_op.rm(), dst_op.offset());
544  CallRecordWriteStubSaveRegisters(
545      dst_addr, scratch, RememberedSetAction::kEmit, SaveFPRegsMode::kSave,
546      StubCallMode::kCallWasmRuntimeStub);
547  bind(&exit);
548}
549
550void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
551                            Register offset_reg, uint32_t offset_imm,
552                            LoadType type, LiftoffRegList pinned,
553                            uint32_t* protected_load_pc, bool is_load_mem,
554                            bool i64_offset) {
555  Register src = no_reg;
556  if (offset_reg != no_reg) {
557    src = GetUnusedRegister(kGpReg, pinned).gp();
558    emit_ptrsize_add(src, src_addr, offset_reg);
559  }
560  MemOperand src_op = (offset_reg != no_reg) ? MemOperand(src, offset_imm)
561                                             : MemOperand(src_addr, offset_imm);
562
563  if (protected_load_pc) *protected_load_pc = pc_offset();
564  switch (type.value()) {
565    case LoadType::kI32Load8U:
566      lbu(dst.gp(), src_op);
567      break;
568    case LoadType::kI64Load8U:
569      lbu(dst.low_gp(), src_op);
570      xor_(dst.high_gp(), dst.high_gp(), dst.high_gp());
571      break;
572    case LoadType::kI32Load8S:
573      lb(dst.gp(), src_op);
574      break;
575    case LoadType::kI64Load8S:
576      lb(dst.low_gp(), src_op);
577      TurboAssembler::Move(dst.high_gp(), dst.low_gp());
578      sra(dst.high_gp(), dst.high_gp(), 31);
579      break;
580    case LoadType::kI32Load16U:
581      TurboAssembler::Ulhu(dst.gp(), src_op);
582      break;
583    case LoadType::kI64Load16U:
584      TurboAssembler::Ulhu(dst.low_gp(), src_op);
585      xor_(dst.high_gp(), dst.high_gp(), dst.high_gp());
586      break;
587    case LoadType::kI32Load16S:
588      TurboAssembler::Ulh(dst.gp(), src_op);
589      break;
590    case LoadType::kI64Load16S:
591      TurboAssembler::Ulh(dst.low_gp(), src_op);
592      TurboAssembler::Move(dst.high_gp(), dst.low_gp());
593      sra(dst.high_gp(), dst.high_gp(), 31);
594      break;
595    case LoadType::kI32Load:
596      TurboAssembler::Ulw(dst.gp(), src_op);
597      break;
598    case LoadType::kI64Load32U:
599      TurboAssembler::Ulw(dst.low_gp(), src_op);
600      xor_(dst.high_gp(), dst.high_gp(), dst.high_gp());
601      break;
602    case LoadType::kI64Load32S:
603      TurboAssembler::Ulw(dst.low_gp(), src_op);
604      TurboAssembler::Move(dst.high_gp(), dst.low_gp());
605      sra(dst.high_gp(), dst.high_gp(), 31);
606      break;
607    case LoadType::kI64Load: {
608      MemOperand src_op =
609          (offset_reg != no_reg)
610              ? MemOperand(src, offset_imm + liftoff::kLowWordOffset)
611              : MemOperand(src_addr, offset_imm + liftoff::kLowWordOffset);
612      MemOperand src_op_upper =
613          (offset_reg != no_reg)
614              ? MemOperand(src, offset_imm + liftoff::kHighWordOffset)
615              : MemOperand(src_addr, offset_imm + liftoff::kHighWordOffset);
616      {
617        UseScratchRegisterScope temps(this);
618        Register temp = dst.low_gp();
619        if (dst.low_gp() == src_op_upper.rm()) temp = temps.Acquire();
620        TurboAssembler::Ulw(temp, src_op);
621        TurboAssembler::Ulw(dst.high_gp(), src_op_upper);
622        if (dst.low_gp() == src_op_upper.rm()) mov(dst.low_gp(), temp);
623      }
624      break;
625    }
626    case LoadType::kF32Load:
627      TurboAssembler::Ulwc1(dst.fp(), src_op, t8);
628      break;
629    case LoadType::kF64Load:
630      TurboAssembler::Uldc1(dst.fp(), src_op, t8);
631      break;
632    default:
633      UNREACHABLE();
634  }
635
636#if defined(V8_TARGET_BIG_ENDIAN)
637  if (is_load_mem) {
638    pinned.set(src_op.rm());
639    liftoff::ChangeEndiannessLoad(this, dst, type, pinned);
640  }
641#endif
642}
643
644void LiftoffAssembler::Store(Register dst_addr, Register offset_reg,
645                             uint32_t offset_imm, LiftoffRegister src,
646                             StoreType type, LiftoffRegList pinned,
647                             uint32_t* protected_store_pc, bool is_store_mem) {
648  Register dst = no_reg;
649  MemOperand dst_op = MemOperand(dst_addr, offset_imm);
650  if (offset_reg != no_reg) {
651    if (is_store_mem) {
652      pinned.set(src);
653    }
654    dst = GetUnusedRegister(kGpReg, pinned).gp();
655    emit_ptrsize_add(dst, dst_addr, offset_reg);
656    dst_op = MemOperand(dst, offset_imm);
657  }
658
659#if defined(V8_TARGET_BIG_ENDIAN)
660  if (is_store_mem) {
661    pinned = pinned | LiftoffRegList{dst_op.rm(), src};
662    LiftoffRegister tmp = GetUnusedRegister(src.reg_class(), pinned);
663    // Save original value.
664    Move(tmp, src, type.value_type());
665
666    src = tmp;
667    pinned.set(tmp);
668    liftoff::ChangeEndiannessStore(this, src, type, pinned);
669  }
670#endif
671
672  if (protected_store_pc) *protected_store_pc = pc_offset();
673  switch (type.value()) {
674    case StoreType::kI64Store8:
675      src = src.low();
676      V8_FALLTHROUGH;
677    case StoreType::kI32Store8:
678      sb(src.gp(), dst_op);
679      break;
680    case StoreType::kI64Store16:
681      src = src.low();
682      V8_FALLTHROUGH;
683    case StoreType::kI32Store16:
684      TurboAssembler::Ush(src.gp(), dst_op, t8);
685      break;
686    case StoreType::kI64Store32:
687      src = src.low();
688      V8_FALLTHROUGH;
689    case StoreType::kI32Store:
690      TurboAssembler::Usw(src.gp(), dst_op);
691      break;
692    case StoreType::kI64Store: {
693      MemOperand dst_op_lower(dst_op.rm(),
694                              offset_imm + liftoff::kLowWordOffset);
695      MemOperand dst_op_upper(dst_op.rm(),
696                              offset_imm + liftoff::kHighWordOffset);
697      TurboAssembler::Usw(src.low_gp(), dst_op_lower);
698      TurboAssembler::Usw(src.high_gp(), dst_op_upper);
699      break;
700    }
701    case StoreType::kF32Store:
702      TurboAssembler::Uswc1(src.fp(), dst_op, t8);
703      break;
704    case StoreType::kF64Store:
705      TurboAssembler::Usdc1(src.fp(), dst_op, t8);
706      break;
707    default:
708      UNREACHABLE();
709  }
710}
711
712void LiftoffAssembler::AtomicLoad(LiftoffRegister dst, Register src_addr,
713                                  Register offset_reg, uint32_t offset_imm,
714                                  LoadType type, LiftoffRegList pinned) {
715  bailout(kAtomics, "AtomicLoad");
716}
717
718void LiftoffAssembler::AtomicStore(Register dst_addr, Register offset_reg,
719                                   uint32_t offset_imm, LiftoffRegister src,
720                                   StoreType type, LiftoffRegList pinned) {
721  bailout(kAtomics, "AtomicStore");
722}
723
724void LiftoffAssembler::AtomicAdd(Register dst_addr, Register offset_reg,
725                                 uint32_t offset_imm, LiftoffRegister value,
726                                 LiftoffRegister result, StoreType type) {
727  bailout(kAtomics, "AtomicAdd");
728}
729
730void LiftoffAssembler::AtomicSub(Register dst_addr, Register offset_reg,
731                                 uint32_t offset_imm, LiftoffRegister value,
732                                 LiftoffRegister result, StoreType type) {
733  bailout(kAtomics, "AtomicSub");
734}
735
736void LiftoffAssembler::AtomicAnd(Register dst_addr, Register offset_reg,
737                                 uint32_t offset_imm, LiftoffRegister value,
738                                 LiftoffRegister result, StoreType type) {
739  bailout(kAtomics, "AtomicAnd");
740}
741
742void LiftoffAssembler::AtomicOr(Register dst_addr, Register offset_reg,
743                                uint32_t offset_imm, LiftoffRegister value,
744                                LiftoffRegister result, StoreType type) {
745  bailout(kAtomics, "AtomicOr");
746}
747
748void LiftoffAssembler::AtomicXor(Register dst_addr, Register offset_reg,
749                                 uint32_t offset_imm, LiftoffRegister value,
750                                 LiftoffRegister result, StoreType type) {
751  bailout(kAtomics, "AtomicXor");
752}
753
754void LiftoffAssembler::AtomicExchange(Register dst_addr, Register offset_reg,
755                                      uint32_t offset_imm,
756                                      LiftoffRegister value,
757                                      LiftoffRegister result, StoreType type) {
758  bailout(kAtomics, "AtomicExchange");
759}
760
761void LiftoffAssembler::AtomicCompareExchange(
762    Register dst_addr, Register offset_reg, uint32_t offset_imm,
763    LiftoffRegister expected, LiftoffRegister new_value, LiftoffRegister result,
764    StoreType type) {
765  bailout(kAtomics, "AtomicCompareExchange");
766}
767
768void LiftoffAssembler::AtomicFence() { sync(); }
769
770void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst,
771                                           uint32_t caller_slot_idx,
772                                           ValueKind kind) {
773  int32_t offset = kSystemPointerSize * (caller_slot_idx + 1);
774  liftoff::Load(this, dst, fp, offset, kind);
775}
776
777void LiftoffAssembler::StoreCallerFrameSlot(LiftoffRegister src,
778                                            uint32_t caller_slot_idx,
779                                            ValueKind kind) {
780  int32_t offset = kSystemPointerSize * (caller_slot_idx + 1);
781  liftoff::Store(this, fp, offset, src, kind);
782}
783
784void LiftoffAssembler::LoadReturnStackSlot(LiftoffRegister dst, int offset,
785                                           ValueKind kind) {
786  liftoff::Load(this, dst, sp, offset, kind);
787}
788
789void LiftoffAssembler::MoveStackValue(uint32_t dst_offset, uint32_t src_offset,
790                                      ValueKind kind) {
791  DCHECK_NE(dst_offset, src_offset);
792  LiftoffRegister reg = GetUnusedRegister(reg_class_for(kind), {});
793  Fill(reg, src_offset, kind);
794  Spill(dst_offset, reg, kind);
795}
796
797void LiftoffAssembler::Move(Register dst, Register src, ValueKind kind) {
798  DCHECK_NE(dst, src);
799  TurboAssembler::mov(dst, src);
800}
801
802void LiftoffAssembler::Move(DoubleRegister dst, DoubleRegister src,
803                            ValueKind kind) {
804  DCHECK_NE(dst, src);
805  TurboAssembler::Move(dst, src);
806}
807
808void LiftoffAssembler::Spill(int offset, LiftoffRegister reg, ValueKind kind) {
809  RecordUsedSpillOffset(offset);
810  MemOperand dst = liftoff::GetStackSlot(offset);
811  switch (kind) {
812    case kI32:
813    case kRef:
814    case kOptRef:
815    case kRtt:
816      sw(reg.gp(), dst);
817      break;
818    case kI64:
819      sw(reg.low_gp(), liftoff::GetHalfStackSlot(offset, kLowWord));
820      sw(reg.high_gp(), liftoff::GetHalfStackSlot(offset, kHighWord));
821      break;
822    case kF32:
823      swc1(reg.fp(), dst);
824      break;
825    case kF64:
826      TurboAssembler::Sdc1(reg.fp(), dst);
827      break;
828    default:
829      UNREACHABLE();
830  }
831}
832
833void LiftoffAssembler::Spill(int offset, WasmValue value) {
834  RecordUsedSpillOffset(offset);
835  MemOperand dst = liftoff::GetStackSlot(offset);
836  switch (value.type().kind()) {
837    case kI32:
838    case kRef:
839    case kOptRef: {
840      LiftoffRegister tmp = GetUnusedRegister(kGpReg, {});
841      TurboAssembler::li(tmp.gp(), Operand(value.to_i32()));
842      sw(tmp.gp(), dst);
843      break;
844    }
845    case kI64: {
846      LiftoffRegister tmp = GetUnusedRegister(kGpRegPair, {});
847
848      int32_t low_word = value.to_i64();
849      int32_t high_word = value.to_i64() >> 32;
850      TurboAssembler::li(tmp.low_gp(), Operand(low_word));
851      TurboAssembler::li(tmp.high_gp(), Operand(high_word));
852
853      sw(tmp.low_gp(), liftoff::GetHalfStackSlot(offset, kLowWord));
854      sw(tmp.high_gp(), liftoff::GetHalfStackSlot(offset, kHighWord));
855      break;
856    }
857    default:
858      // kWasmF32 and kWasmF64 are unreachable, since those
859      // constants are not tracked.
860      UNREACHABLE();
861  }
862}
863
864void LiftoffAssembler::Fill(LiftoffRegister reg, int offset, ValueKind kind) {
865  MemOperand src = liftoff::GetStackSlot(offset);
866  switch (kind) {
867    case kI32:
868    case kRef:
869    case kOptRef:
870      lw(reg.gp(), src);
871      break;
872    case kI64:
873      lw(reg.low_gp(), liftoff::GetHalfStackSlot(offset, kLowWord));
874      lw(reg.high_gp(), liftoff::GetHalfStackSlot(offset, kHighWord));
875      break;
876    case kF32:
877      lwc1(reg.fp(), src);
878      break;
879    case kF64:
880      TurboAssembler::Ldc1(reg.fp(), src);
881      break;
882    default:
883      UNREACHABLE();
884  }
885}
886
887void LiftoffAssembler::FillI64Half(Register reg, int offset, RegPairHalf half) {
888  lw(reg, liftoff::GetHalfStackSlot(offset, half));
889}
890
891void LiftoffAssembler::FillStackSlotsWithZero(int start, int size) {
892  DCHECK_LT(0, size);
893  DCHECK_EQ(0, size % 4);
894  RecordUsedSpillOffset(start + size);
895
896  if (size <= 48) {
897    // Special straight-line code for up to 12 words. Generates one
898    // instruction per word (<=12 instructions total).
899    for (int offset = 4; offset <= size; offset += 4) {
900      Sw(zero_reg, liftoff::GetStackSlot(start + offset));
901    }
902  } else {
903    // General case for bigger counts (12 instructions).
904    // Use a0 for start address (inclusive), a1 for end address (exclusive).
905    Push(a1, a0);
906    Addu(a0, fp, Operand(-start - size));
907    Addu(a1, fp, Operand(-start));
908
909    Label loop;
910    bind(&loop);
911    Sw(zero_reg, MemOperand(a0));
912    addiu(a0, a0, kSystemPointerSize);
913    BranchShort(&loop, ne, a0, Operand(a1));
914
915    Pop(a1, a0);
916  }
917}
918
919void LiftoffAssembler::emit_i32_mul(Register dst, Register lhs, Register rhs) {
920  TurboAssembler::Mul(dst, lhs, rhs);
921}
922
923void LiftoffAssembler::emit_i32_divs(Register dst, Register lhs, Register rhs,
924                                     Label* trap_div_by_zero,
925                                     Label* trap_div_unrepresentable) {
926  TurboAssembler::Branch(trap_div_by_zero, eq, rhs, Operand(zero_reg));
927
928  // Check if lhs == kMinInt and rhs == -1, since this case is unrepresentable.
929  TurboAssembler::li(kScratchReg, 1);
930  TurboAssembler::li(kScratchReg2, 1);
931  TurboAssembler::LoadZeroOnCondition(kScratchReg, lhs, Operand(kMinInt), eq);
932  TurboAssembler::LoadZeroOnCondition(kScratchReg2, rhs, Operand(-1), eq);
933  addu(kScratchReg, kScratchReg, kScratchReg2);
934  TurboAssembler::Branch(trap_div_unrepresentable, eq, kScratchReg,
935                         Operand(zero_reg));
936
937  TurboAssembler::Div(dst, lhs, rhs);
938}
939
940void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs,
941                                     Label* trap_div_by_zero) {
942  TurboAssembler::Branch(trap_div_by_zero, eq, rhs, Operand(zero_reg));
943  TurboAssembler::Divu(dst, lhs, rhs);
944}
945
946void LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs,
947                                     Label* trap_div_by_zero) {
948  TurboAssembler::Branch(trap_div_by_zero, eq, rhs, Operand(zero_reg));
949  TurboAssembler::Mod(dst, lhs, rhs);
950}
951
952void LiftoffAssembler::emit_i32_remu(Register dst, Register lhs, Register rhs,
953                                     Label* trap_div_by_zero) {
954  TurboAssembler::Branch(trap_div_by_zero, eq, rhs, Operand(zero_reg));
955  TurboAssembler::Modu(dst, lhs, rhs);
956}
957
958#define I32_BINOP(name, instruction)                                 \
959  void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
960                                         Register rhs) {             \
961    instruction(dst, lhs, rhs);                                      \
962  }
963
964// clang-format off
965I32_BINOP(add, addu)
966I32_BINOP(sub, subu)
967I32_BINOP(and, and_)
968I32_BINOP(or, or_)
969I32_BINOP(xor, xor_)
970// clang-format on
971
972#undef I32_BINOP
973
974#define I32_BINOP_I(name, instruction)                                  \
975  void LiftoffAssembler::emit_i32_##name##i(Register dst, Register lhs, \
976                                            int32_t imm) {              \
977    instruction(dst, lhs, Operand(imm));                                \
978  }
979
980// clang-format off
981I32_BINOP_I(add, Addu)
982I32_BINOP_I(sub, Subu)
983I32_BINOP_I(and, And)
984I32_BINOP_I(or, Or)
985I32_BINOP_I(xor, Xor)
986// clang-format on
987
988#undef I32_BINOP_I
989
990void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
991  TurboAssembler::Clz(dst, src);
992}
993
994void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
995  TurboAssembler::Ctz(dst, src);
996}
997
998bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) {
999  TurboAssembler::Popcnt(dst, src);
1000  return true;
1001}
1002
1003#define I32_SHIFTOP(name, instruction)                               \
1004  void LiftoffAssembler::emit_i32_##name(Register dst, Register src, \
1005                                         Register amount) {          \
1006    instruction(dst, src, amount);                                   \
1007  }
1008#define I32_SHIFTOP_I(name, instruction)                                \
1009  I32_SHIFTOP(name, instruction##v)                                     \
1010  void LiftoffAssembler::emit_i32_##name##i(Register dst, Register src, \
1011                                            int amount) {               \
1012    DCHECK(is_uint5(amount));                                           \
1013    instruction(dst, src, amount);                                      \
1014  }
1015
1016I32_SHIFTOP_I(shl, sll)
1017I32_SHIFTOP_I(sar, sra)
1018I32_SHIFTOP_I(shr, srl)
1019
1020#undef I32_SHIFTOP
1021#undef I32_SHIFTOP_I
1022
1023void LiftoffAssembler::emit_i64_addi(LiftoffRegister dst, LiftoffRegister lhs,
1024                                     int64_t imm) {
1025  LiftoffRegister imm_reg =
1026      GetUnusedRegister(kGpRegPair, LiftoffRegList{dst, lhs});
1027  int32_t imm_low_word = static_cast<int32_t>(imm);
1028  int32_t imm_high_word = static_cast<int32_t>(imm >> 32);
1029  TurboAssembler::li(imm_reg.low_gp(), imm_low_word);
1030  TurboAssembler::li(imm_reg.high_gp(), imm_high_word);
1031  TurboAssembler::AddPair(dst.low_gp(), dst.high_gp(), lhs.low_gp(),
1032                          lhs.high_gp(), imm_reg.low_gp(), imm_reg.high_gp(),
1033                          kScratchReg, kScratchReg2);
1034}
1035
1036void LiftoffAssembler::emit_i64_mul(LiftoffRegister dst, LiftoffRegister lhs,
1037                                    LiftoffRegister rhs) {
1038  TurboAssembler::MulPair(dst.low_gp(), dst.high_gp(), lhs.low_gp(),
1039                          lhs.high_gp(), rhs.low_gp(), rhs.high_gp(),
1040                          kScratchReg, kScratchReg2);
1041}
1042
1043bool LiftoffAssembler::emit_i64_divs(LiftoffRegister dst, LiftoffRegister lhs,
1044                                     LiftoffRegister rhs,
1045                                     Label* trap_div_by_zero,
1046                                     Label* trap_div_unrepresentable) {
1047  return false;
1048}
1049
1050bool LiftoffAssembler::emit_i64_divu(LiftoffRegister dst, LiftoffRegister lhs,
1051                                     LiftoffRegister rhs,
1052                                     Label* trap_div_by_zero) {
1053  return false;
1054}
1055
1056bool LiftoffAssembler::emit_i64_rems(LiftoffRegister dst, LiftoffRegister lhs,
1057                                     LiftoffRegister rhs,
1058                                     Label* trap_div_by_zero) {
1059  return false;
1060}
1061
1062bool LiftoffAssembler::emit_i64_remu(LiftoffRegister dst, LiftoffRegister lhs,
1063                                     LiftoffRegister rhs,
1064                                     Label* trap_div_by_zero) {
1065  return false;
1066}
1067
1068void LiftoffAssembler::emit_i64_add(LiftoffRegister dst, LiftoffRegister lhs,
1069                                    LiftoffRegister rhs) {
1070  TurboAssembler::AddPair(dst.low_gp(), dst.high_gp(), lhs.low_gp(),
1071                          lhs.high_gp(), rhs.low_gp(), rhs.high_gp(),
1072                          kScratchReg, kScratchReg2);
1073}
1074
1075void LiftoffAssembler::emit_i64_sub(LiftoffRegister dst, LiftoffRegister lhs,
1076                                    LiftoffRegister rhs) {
1077  TurboAssembler::SubPair(dst.low_gp(), dst.high_gp(), lhs.low_gp(),
1078                          lhs.high_gp(), rhs.low_gp(), rhs.high_gp(),
1079                          kScratchReg, kScratchReg2);
1080}
1081
1082namespace liftoff {
1083
1084inline bool IsRegInRegPair(LiftoffRegister pair, Register reg) {
1085  DCHECK(pair.is_gp_pair());
1086  return pair.low_gp() == reg || pair.high_gp() == reg;
1087}
1088
1089inline void Emit64BitShiftOperation(
1090    LiftoffAssembler* assm, LiftoffRegister dst, LiftoffRegister src,
1091    Register amount,
1092    void (TurboAssembler::*emit_shift)(Register, Register, Register, Register,
1093                                       Register, Register, Register)) {
1094  Label move, done;
1095  LiftoffRegList pinned = {dst, src, amount};
1096
1097  // If some of destination registers are in use, get another, unused pair.
1098  // That way we prevent overwriting some input registers while shifting.
1099  // Do this before any branch so that the cache state will be correct for
1100  // all conditions.
1101  LiftoffRegister tmp = assm->GetUnusedRegister(kGpRegPair, pinned);
1102
1103  // If shift amount is 0, don't do the shifting.
1104  assm->TurboAssembler::Branch(&move, eq, amount, Operand(zero_reg));
1105
1106  if (liftoff::IsRegInRegPair(dst, amount) || dst.overlaps(src)) {
1107    // Do the actual shift.
1108    (assm->*emit_shift)(tmp.low_gp(), tmp.high_gp(), src.low_gp(),
1109                        src.high_gp(), amount, kScratchReg, kScratchReg2);
1110
1111    // Place result in destination register.
1112    assm->TurboAssembler::Move(dst.high_gp(), tmp.high_gp());
1113    assm->TurboAssembler::Move(dst.low_gp(), tmp.low_gp());
1114  } else {
1115    (assm->*emit_shift)(dst.low_gp(), dst.high_gp(), src.low_gp(),
1116                        src.high_gp(), amount, kScratchReg, kScratchReg2);
1117  }
1118  assm->TurboAssembler::Branch(&done);
1119
1120  // If shift amount is 0, move src to dst.
1121  assm->bind(&move);
1122  assm->TurboAssembler::Move(dst.high_gp(), src.high_gp());
1123  assm->TurboAssembler::Move(dst.low_gp(), src.low_gp());
1124
1125  assm->bind(&done);
1126}
1127}  // namespace liftoff
1128
1129void LiftoffAssembler::emit_i64_shl(LiftoffRegister dst, LiftoffRegister src,
1130                                    Register amount) {
1131  liftoff::Emit64BitShiftOperation(this, dst, src, amount,
1132                                   &TurboAssembler::ShlPair);
1133}
1134
1135void LiftoffAssembler::emit_i64_shli(LiftoffRegister dst, LiftoffRegister src,
1136                                     int32_t amount) {
1137  UseScratchRegisterScope temps(this);
1138  // {src.low_gp()} will still be needed after writing {dst.high_gp()} and
1139  // {dst.low_gp()}.
1140  Register src_low = liftoff::EnsureNoAlias(this, src.low_gp(), dst, &temps);
1141  Register src_high = src.high_gp();
1142  // {src.high_gp()} will still be needed after writing {dst.high_gp()}.
1143  if (src_high == dst.high_gp()) {
1144    mov(kScratchReg, src_high);
1145    src_high = kScratchReg;
1146  }
1147  DCHECK_NE(dst.low_gp(), kScratchReg);
1148  DCHECK_NE(dst.high_gp(), kScratchReg);
1149
1150  ShlPair(dst.low_gp(), dst.high_gp(), src_low, src_high, amount, kScratchReg);
1151}
1152
1153void LiftoffAssembler::emit_i64_sar(LiftoffRegister dst, LiftoffRegister src,
1154                                    Register amount) {
1155  liftoff::Emit64BitShiftOperation(this, dst, src, amount,
1156                                   &TurboAssembler::SarPair);
1157}
1158
1159void LiftoffAssembler::emit_i64_sari(LiftoffRegister dst, LiftoffRegister src,
1160                                     int32_t amount) {
1161  UseScratchRegisterScope temps(this);
1162  // {src.high_gp()} will still be needed after writing {dst.high_gp()} and
1163  // {dst.low_gp()}.
1164  Register src_high = liftoff::EnsureNoAlias(this, src.high_gp(), dst, &temps);
1165  DCHECK_NE(dst.low_gp(), kScratchReg);
1166  DCHECK_NE(dst.high_gp(), kScratchReg);
1167
1168  SarPair(dst.low_gp(), dst.high_gp(), src.low_gp(), src_high, amount,
1169          kScratchReg);
1170}
1171
1172void LiftoffAssembler::emit_i64_shr(LiftoffRegister dst, LiftoffRegister src,
1173                                    Register amount) {
1174  liftoff::Emit64BitShiftOperation(this, dst, src, amount,
1175                                   &TurboAssembler::ShrPair);
1176}
1177
1178void LiftoffAssembler::emit_i64_shri(LiftoffRegister dst, LiftoffRegister src,
1179                                     int32_t amount) {
1180  UseScratchRegisterScope temps(this);
1181  // {src.high_gp()} will still be needed after writing {dst.high_gp()} and
1182  // {dst.low_gp()}.
1183  Register src_high = liftoff::EnsureNoAlias(this, src.high_gp(), dst, &temps);
1184  DCHECK_NE(dst.low_gp(), kScratchReg);
1185  DCHECK_NE(dst.high_gp(), kScratchReg);
1186
1187  ShrPair(dst.low_gp(), dst.high_gp(), src.low_gp(), src_high, amount,
1188          kScratchReg);
1189}
1190
1191void LiftoffAssembler::emit_i64_clz(LiftoffRegister dst, LiftoffRegister src) {
1192  // return high == 0 ? 32 + CLZ32(low) : CLZ32(high);
1193  Label done;
1194  Label high_is_zero;
1195  Branch(&high_is_zero, eq, src.high_gp(), Operand(zero_reg));
1196
1197  clz(dst.low_gp(), src.high_gp());
1198  jmp(&done);
1199
1200  bind(&high_is_zero);
1201  clz(dst.low_gp(), src.low_gp());
1202  Addu(dst.low_gp(), dst.low_gp(), Operand(32));
1203
1204  bind(&done);
1205  mov(dst.high_gp(), zero_reg);  // High word of result is always 0.
1206}
1207
1208void LiftoffAssembler::emit_i64_ctz(LiftoffRegister dst, LiftoffRegister src) {
1209  // return low == 0 ? 32 + CTZ32(high) : CTZ32(low);
1210  Label done;
1211  Label low_is_zero;
1212  Branch(&low_is_zero, eq, src.low_gp(), Operand(zero_reg));
1213
1214  Ctz(dst.low_gp(), src.low_gp());
1215  jmp(&done);
1216
1217  bind(&low_is_zero);
1218  Ctz(dst.low_gp(), src.high_gp());
1219  Addu(dst.low_gp(), dst.low_gp(), Operand(32));
1220
1221  bind(&done);
1222  mov(dst.high_gp(), zero_reg);  // High word of result is always 0.
1223}
1224
1225bool LiftoffAssembler::emit_i64_popcnt(LiftoffRegister dst,
1226                                       LiftoffRegister src) {
1227  // Produce partial popcnts in the two dst registers.
1228  Register src1 = src.high_gp() == dst.low_gp() ? src.high_gp() : src.low_gp();
1229  Register src2 = src.high_gp() == dst.low_gp() ? src.low_gp() : src.high_gp();
1230  TurboAssembler::Popcnt(dst.low_gp(), src1);
1231  TurboAssembler::Popcnt(dst.high_gp(), src2);
1232  // Now add the two into the lower dst reg and clear the higher dst reg.
1233  addu(dst.low_gp(), dst.low_gp(), dst.high_gp());
1234  mov(dst.high_gp(), zero_reg);
1235  return true;
1236}
1237
1238void LiftoffAssembler::IncrementSmi(LiftoffRegister dst, int offset) {
1239  UseScratchRegisterScope temps(this);
1240  Register scratch = temps.Acquire();
1241  lw(scratch, MemOperand(dst.gp(), offset));
1242  Addu(scratch, scratch, Operand(Smi::FromInt(1)));
1243  sw(scratch, MemOperand(dst.gp(), offset));
1244}
1245
1246void LiftoffAssembler::emit_f32_neg(DoubleRegister dst, DoubleRegister src) {
1247  TurboAssembler::Neg_s(dst, src);
1248}
1249
1250void LiftoffAssembler::emit_f64_neg(DoubleRegister dst, DoubleRegister src) {
1251  TurboAssembler::Neg_d(dst, src);
1252}
1253
1254void LiftoffAssembler::emit_f32_min(DoubleRegister dst, DoubleRegister lhs,
1255                                    DoubleRegister rhs) {
1256  Label ool, done;
1257  TurboAssembler::Float32Min(dst, lhs, rhs, &ool);
1258  Branch(&done);
1259
1260  bind(&ool);
1261  TurboAssembler::Float32MinOutOfLine(dst, lhs, rhs);
1262  bind(&done);
1263}
1264
1265void LiftoffAssembler::emit_f32_max(DoubleRegister dst, DoubleRegister lhs,
1266                                    DoubleRegister rhs) {
1267  Label ool, done;
1268  TurboAssembler::Float32Max(dst, lhs, rhs, &ool);
1269  Branch(&done);
1270
1271  bind(&ool);
1272  TurboAssembler::Float32MaxOutOfLine(dst, lhs, rhs);
1273  bind(&done);
1274}
1275
1276void LiftoffAssembler::emit_f32_copysign(DoubleRegister dst, DoubleRegister lhs,
1277                                         DoubleRegister rhs) {
1278  bailout(kComplexOperation, "f32_copysign");
1279}
1280
1281void LiftoffAssembler::emit_f64_min(DoubleRegister dst, DoubleRegister lhs,
1282                                    DoubleRegister rhs) {
1283  Label ool, done;
1284  TurboAssembler::Float64Min(dst, lhs, rhs, &ool);
1285  Branch(&done);
1286
1287  bind(&ool);
1288  TurboAssembler::Float64MinOutOfLine(dst, lhs, rhs);
1289  bind(&done);
1290}
1291
1292void LiftoffAssembler::emit_f64_max(DoubleRegister dst, DoubleRegister lhs,
1293                                    DoubleRegister rhs) {
1294  Label ool, done;
1295  TurboAssembler::Float64Max(dst, lhs, rhs, &ool);
1296  Branch(&done);
1297
1298  bind(&ool);
1299  TurboAssembler::Float64MaxOutOfLine(dst, lhs, rhs);
1300  bind(&done);
1301}
1302
1303void LiftoffAssembler::emit_f64_copysign(DoubleRegister dst, DoubleRegister lhs,
1304                                         DoubleRegister rhs) {
1305  bailout(kComplexOperation, "f64_copysign");
1306}
1307
1308#define FP_BINOP(name, instruction)                                          \
1309  void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
1310                                     DoubleRegister rhs) {                   \
1311    instruction(dst, lhs, rhs);                                              \
1312  }
1313#define FP_UNOP(name, instruction)                                             \
1314  void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \
1315    instruction(dst, src);                                                     \
1316  }
1317#define FP_UNOP_RETURN_TRUE(name, instruction)                                 \
1318  bool LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \
1319    instruction(dst, src);                                                     \
1320    return true;                                                               \
1321  }
1322
1323FP_BINOP(f32_add, add_s)
1324FP_BINOP(f32_sub, sub_s)
1325FP_BINOP(f32_mul, mul_s)
1326FP_BINOP(f32_div, div_s)
1327FP_UNOP(f32_abs, abs_s)
1328FP_UNOP_RETURN_TRUE(f32_ceil, Ceil_s_s)
1329FP_UNOP_RETURN_TRUE(f32_floor, Floor_s_s)
1330FP_UNOP_RETURN_TRUE(f32_trunc, Trunc_s_s)
1331FP_UNOP_RETURN_TRUE(f32_nearest_int, Round_s_s)
1332FP_UNOP(f32_sqrt, sqrt_s)
1333FP_BINOP(f64_add, add_d)
1334FP_BINOP(f64_sub, sub_d)
1335FP_BINOP(f64_mul, mul_d)
1336FP_BINOP(f64_div, div_d)
1337FP_UNOP(f64_abs, abs_d)
1338FP_UNOP(f64_sqrt, sqrt_d)
1339
1340#undef FP_BINOP
1341#undef FP_UNOP
1342
1343bool LiftoffAssembler::emit_f64_ceil(DoubleRegister dst, DoubleRegister src) {
1344  if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
1345      IsFp64Mode()) {
1346    Ceil_d_d(dst, src);
1347    return true;
1348  }
1349  return false;
1350}
1351
1352bool LiftoffAssembler::emit_f64_floor(DoubleRegister dst, DoubleRegister src) {
1353  if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
1354      IsFp64Mode()) {
1355    Floor_d_d(dst, src);
1356    return true;
1357  }
1358  return false;
1359}
1360
1361bool LiftoffAssembler::emit_f64_trunc(DoubleRegister dst, DoubleRegister src) {
1362  if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
1363      IsFp64Mode()) {
1364    Trunc_d_d(dst, src);
1365    return true;
1366  }
1367  return false;
1368}
1369
1370bool LiftoffAssembler::emit_f64_nearest_int(DoubleRegister dst,
1371                                            DoubleRegister src) {
1372  if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
1373      IsFp64Mode()) {
1374    Round_d_d(dst, src);
1375    return true;
1376  }
1377  return false;
1378}
1379
1380bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
1381                                            LiftoffRegister dst,
1382                                            LiftoffRegister src, Label* trap) {
1383  switch (opcode) {
1384    case kExprI32ConvertI64:
1385      TurboAssembler::Move(dst.gp(), src.low_gp());
1386      return true;
1387    case kExprI32SConvertF32: {
1388      LiftoffRegister rounded = GetUnusedRegister(kFpReg, LiftoffRegList{src});
1389      LiftoffRegister converted_back =
1390          GetUnusedRegister(kFpReg, LiftoffRegList{src, rounded});
1391
1392      // Real conversion.
1393      TurboAssembler::Trunc_s_s(rounded.fp(), src.fp());
1394      trunc_w_s(kScratchDoubleReg, rounded.fp());
1395      mfc1(dst.gp(), kScratchDoubleReg);
1396      // Avoid INT32_MAX as an overflow indicator and use INT32_MIN instead,
1397      // because INT32_MIN allows easier out-of-bounds detection.
1398      TurboAssembler::Addu(kScratchReg, dst.gp(), 1);
1399      TurboAssembler::Slt(kScratchReg2, kScratchReg, dst.gp());
1400      TurboAssembler::Movn(dst.gp(), kScratchReg, kScratchReg2);
1401
1402      // Checking if trap.
1403      mtc1(dst.gp(), kScratchDoubleReg);
1404      cvt_s_w(converted_back.fp(), kScratchDoubleReg);
1405      TurboAssembler::CompareF32(EQ, rounded.fp(), converted_back.fp());
1406      TurboAssembler::BranchFalseF(trap);
1407      return true;
1408    }
1409    case kExprI32UConvertF32: {
1410      LiftoffRegister rounded = GetUnusedRegister(kFpReg, LiftoffRegList{src});
1411      LiftoffRegister converted_back =
1412          GetUnusedRegister(kFpReg, LiftoffRegList{src, rounded});
1413
1414      // Real conversion.
1415      TurboAssembler::Trunc_s_s(rounded.fp(), src.fp());
1416      TurboAssembler::Trunc_uw_s(dst.gp(), rounded.fp(), kScratchDoubleReg);
1417      // Avoid UINT32_MAX as an overflow indicator and use 0 instead,
1418      // because 0 allows easier out-of-bounds detection.
1419      TurboAssembler::Addu(kScratchReg, dst.gp(), 1);
1420      TurboAssembler::Movz(dst.gp(), zero_reg, kScratchReg);
1421
1422      // Checking if trap.
1423      TurboAssembler::Cvt_d_uw(converted_back.fp(), dst.gp(),
1424                               kScratchDoubleReg);
1425      cvt_s_d(converted_back.fp(), converted_back.fp());
1426      TurboAssembler::CompareF32(EQ, rounded.fp(), converted_back.fp());
1427      TurboAssembler::BranchFalseF(trap);
1428      return true;
1429    }
1430    case kExprI32SConvertF64: {
1431      LiftoffRegister scratch = GetUnusedRegister(kGpReg, LiftoffRegList{dst});
1432
1433      // Try a conversion to a signed integer.
1434      trunc_w_d(kScratchDoubleReg, src.fp());
1435      mfc1(dst.gp(), kScratchDoubleReg);
1436      // Retrieve the FCSR.
1437      cfc1(scratch.gp(), FCSR);
1438      // Check for overflow and NaNs.
1439      And(scratch.gp(), scratch.gp(),
1440          kFCSROverflowCauseMask | kFCSRUnderflowCauseMask |
1441              kFCSRInvalidOpCauseMask);
1442      // If we had exceptions we are trap.
1443      Branch(trap, ne, scratch.gp(), Operand(zero_reg));
1444      return true;
1445    }
1446    case kExprI32UConvertF64: {
1447      if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
1448          IsFp64Mode()) {
1449        LiftoffRegister rounded =
1450            GetUnusedRegister(kFpReg, LiftoffRegList{src});
1451        LiftoffRegister converted_back =
1452            GetUnusedRegister(kFpReg, LiftoffRegList{src, rounded});
1453
1454        // Real conversion.
1455        TurboAssembler::Trunc_d_d(rounded.fp(), src.fp());
1456        TurboAssembler::Trunc_uw_d(dst.gp(), rounded.fp(), kScratchDoubleReg);
1457
1458        // Checking if trap.
1459        TurboAssembler::Cvt_d_uw(converted_back.fp(), dst.gp(),
1460                                 kScratchDoubleReg);
1461        TurboAssembler::CompareF64(EQ, rounded.fp(), converted_back.fp());
1462        TurboAssembler::BranchFalseF(trap);
1463        return true;
1464      }
1465      bailout(kUnsupportedArchitecture, "kExprI32UConvertF64");
1466      return true;
1467    }
1468    case kExprI32SConvertSatF32:
1469      bailout(kNonTrappingFloatToInt, "kExprI32SConvertSatF32");
1470      return true;
1471    case kExprI32UConvertSatF32:
1472      bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF32");
1473      return true;
1474    case kExprI32SConvertSatF64:
1475      bailout(kNonTrappingFloatToInt, "kExprI32SConvertSatF64");
1476      return true;
1477    case kExprI32UConvertSatF64:
1478      bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64");
1479      return true;
1480    case kExprI64SConvertSatF32:
1481      bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF32");
1482      return true;
1483    case kExprI64UConvertSatF32:
1484      bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF32");
1485      return true;
1486    case kExprI64SConvertSatF64:
1487      bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF64");
1488      return true;
1489    case kExprI64UConvertSatF64:
1490      bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF64");
1491      return true;
1492    case kExprI32ReinterpretF32:
1493      mfc1(dst.gp(), src.fp());
1494      return true;
1495    case kExprI64SConvertI32:
1496      TurboAssembler::Move(dst.low_gp(), src.gp());
1497      TurboAssembler::Move(dst.high_gp(), src.gp());
1498      sra(dst.high_gp(), dst.high_gp(), 31);
1499      return true;
1500    case kExprI64UConvertI32:
1501      TurboAssembler::Move(dst.low_gp(), src.gp());
1502      TurboAssembler::Move(dst.high_gp(), zero_reg);
1503      return true;
1504    case kExprI64ReinterpretF64:
1505      mfc1(dst.low_gp(), src.fp());
1506      TurboAssembler::Mfhc1(dst.high_gp(), src.fp());
1507      return true;
1508    case kExprF32SConvertI32: {
1509      LiftoffRegister scratch = GetUnusedRegister(kFpReg, LiftoffRegList{dst});
1510      mtc1(src.gp(), scratch.fp());
1511      cvt_s_w(dst.fp(), scratch.fp());
1512      return true;
1513    }
1514    case kExprF32UConvertI32: {
1515      LiftoffRegister scratch = GetUnusedRegister(kFpReg, LiftoffRegList{dst});
1516      TurboAssembler::Cvt_d_uw(dst.fp(), src.gp(), scratch.fp());
1517      cvt_s_d(dst.fp(), dst.fp());
1518      return true;
1519    }
1520    case kExprF32ConvertF64:
1521      cvt_s_d(dst.fp(), src.fp());
1522      return true;
1523    case kExprF32ReinterpretI32:
1524      TurboAssembler::FmoveLow(dst.fp(), src.gp());
1525      return true;
1526    case kExprF64SConvertI32: {
1527      LiftoffRegister scratch = GetUnusedRegister(kFpReg, LiftoffRegList{dst});
1528      mtc1(src.gp(), scratch.fp());
1529      cvt_d_w(dst.fp(), scratch.fp());
1530      return true;
1531    }
1532    case kExprF64UConvertI32: {
1533      LiftoffRegister scratch = GetUnusedRegister(kFpReg, LiftoffRegList{dst});
1534      TurboAssembler::Cvt_d_uw(dst.fp(), src.gp(), scratch.fp());
1535      return true;
1536    }
1537    case kExprF64ConvertF32:
1538      cvt_d_s(dst.fp(), src.fp());
1539      return true;
1540    case kExprF64ReinterpretI64:
1541      mtc1(src.low_gp(), dst.fp());
1542      TurboAssembler::Mthc1(src.high_gp(), dst.fp());
1543      return true;
1544    default:
1545      return false;
1546  }
1547}
1548
1549void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) {
1550  bailout(kComplexOperation, "i32_signextend_i8");
1551}
1552
1553void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) {
1554  bailout(kComplexOperation, "i32_signextend_i16");
1555}
1556
1557void LiftoffAssembler::emit_i64_signextend_i8(LiftoffRegister dst,
1558                                              LiftoffRegister src) {
1559  bailout(kComplexOperation, "i64_signextend_i8");
1560}
1561
1562void LiftoffAssembler::emit_i64_signextend_i16(LiftoffRegister dst,
1563                                               LiftoffRegister src) {
1564  bailout(kComplexOperation, "i64_signextend_i16");
1565}
1566
1567void LiftoffAssembler::emit_i64_signextend_i32(LiftoffRegister dst,
1568                                               LiftoffRegister src) {
1569  bailout(kComplexOperation, "i64_signextend_i32");
1570}
1571
1572void LiftoffAssembler::emit_jump(Label* label) {
1573  TurboAssembler::Branch(label);
1574}
1575
1576void LiftoffAssembler::emit_jump(Register target) {
1577  TurboAssembler::Jump(target);
1578}
1579
1580void LiftoffAssembler::emit_cond_jump(LiftoffCondition liftoff_cond,
1581                                      Label* label, ValueKind kind,
1582                                      Register lhs, Register rhs) {
1583  Condition cond = liftoff::ToCondition(liftoff_cond);
1584  if (rhs == no_reg) {
1585    DCHECK_EQ(kind, kI32);
1586    TurboAssembler::Branch(label, cond, lhs, Operand(zero_reg));
1587  } else {
1588    DCHECK(kind == kI32 || (is_reference(kind) && (liftoff_cond == kEqual ||
1589                                                   liftoff_cond == kUnequal)));
1590    TurboAssembler::Branch(label, cond, lhs, Operand(rhs));
1591  }
1592}
1593
1594void LiftoffAssembler::emit_i32_cond_jumpi(LiftoffCondition liftoff_cond,
1595                                           Label* label, Register lhs,
1596                                           int32_t imm) {
1597  Condition cond = liftoff::ToCondition(liftoff_cond);
1598  TurboAssembler::Branch(label, cond, lhs, Operand(imm));
1599}
1600
1601void LiftoffAssembler::emit_i32_subi_jump_negative(Register value,
1602                                                   int subtrahend,
1603                                                   Label* result_negative) {
1604  TurboAssembler::Subu(value, value, Operand(subtrahend));
1605  TurboAssembler::Branch(result_negative, less, value, Operand(zero_reg));
1606}
1607
1608void LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
1609  sltiu(dst, src, 1);
1610}
1611
1612void LiftoffAssembler::emit_i32_set_cond(LiftoffCondition liftoff_cond,
1613                                         Register dst, Register lhs,
1614                                         Register rhs) {
1615  Condition cond = liftoff::ToCondition(liftoff_cond);
1616  Register tmp = dst;
1617  if (dst == lhs || dst == rhs) {
1618    tmp = GetUnusedRegister(kGpReg, LiftoffRegList{lhs, rhs}).gp();
1619  }
1620  // Write 1 as result.
1621  TurboAssembler::li(tmp, 1);
1622
1623  // If negative condition is true, write 0 as result.
1624  Condition neg_cond = NegateCondition(cond);
1625  TurboAssembler::LoadZeroOnCondition(tmp, lhs, Operand(rhs), neg_cond);
1626
1627  // If tmp != dst, result will be moved.
1628  TurboAssembler::Move(dst, tmp);
1629}
1630
1631void LiftoffAssembler::emit_i64_eqz(Register dst, LiftoffRegister src) {
1632  Register tmp = GetUnusedRegister(kGpReg, LiftoffRegList{src, dst}).gp();
1633  sltiu(tmp, src.low_gp(), 1);
1634  sltiu(dst, src.high_gp(), 1);
1635  and_(dst, dst, tmp);
1636}
1637
1638namespace liftoff {
1639inline LiftoffCondition cond_make_unsigned(LiftoffCondition cond) {
1640  switch (cond) {
1641    case kSignedLessThan:
1642      return kUnsignedLessThan;
1643    case kSignedLessEqual:
1644      return kUnsignedLessEqual;
1645    case kSignedGreaterThan:
1646      return kUnsignedGreaterThan;
1647    case kSignedGreaterEqual:
1648      return kUnsignedGreaterEqual;
1649    default:
1650      return cond;
1651  }
1652}
1653}  // namespace liftoff
1654
1655void LiftoffAssembler::emit_i64_set_cond(LiftoffCondition liftoff_cond,
1656                                         Register dst, LiftoffRegister lhs,
1657                                         LiftoffRegister rhs) {
1658  Condition cond = liftoff::ToCondition(liftoff_cond);
1659  Label low, cont;
1660
1661  // For signed i64 comparisons, we still need to use unsigned comparison for
1662  // the low word (the only bit carrying signedness information is the MSB in
1663  // the high word).
1664  Condition unsigned_cond =
1665      liftoff::ToCondition(liftoff::cond_make_unsigned(liftoff_cond));
1666
1667  Register tmp = dst;
1668  if (liftoff::IsRegInRegPair(lhs, dst) || liftoff::IsRegInRegPair(rhs, dst)) {
1669    tmp = GetUnusedRegister(kGpReg, LiftoffRegList{dst, lhs, rhs}).gp();
1670  }
1671
1672  // Write 1 initially in tmp register.
1673  TurboAssembler::li(tmp, 1);
1674
1675  // If high words are equal, then compare low words, else compare high.
1676  Branch(&low, eq, lhs.high_gp(), Operand(rhs.high_gp()));
1677
1678  TurboAssembler::LoadZeroOnCondition(
1679      tmp, lhs.high_gp(), Operand(rhs.high_gp()), NegateCondition(cond));
1680  Branch(&cont);
1681
1682  bind(&low);
1683  TurboAssembler::LoadZeroOnCondition(tmp, lhs.low_gp(), Operand(rhs.low_gp()),
1684                                      NegateCondition(unsigned_cond));
1685
1686  bind(&cont);
1687  // Move result to dst register if needed.
1688  TurboAssembler::Move(dst, tmp);
1689}
1690
1691namespace liftoff {
1692
1693inline FPUCondition ConditionToConditionCmpFPU(LiftoffCondition condition,
1694                                               bool* predicate) {
1695  switch (condition) {
1696    case kEqual:
1697      *predicate = true;
1698      return EQ;
1699    case kUnequal:
1700      *predicate = false;
1701      return EQ;
1702    case kUnsignedLessThan:
1703      *predicate = true;
1704      return OLT;
1705    case kUnsignedGreaterEqual:
1706      *predicate = false;
1707      return OLT;
1708    case kUnsignedLessEqual:
1709      *predicate = true;
1710      return OLE;
1711    case kUnsignedGreaterThan:
1712      *predicate = false;
1713      return OLE;
1714    default:
1715      *predicate = true;
1716      break;
1717  }
1718  UNREACHABLE();
1719}
1720
1721}  // namespace liftoff
1722
1723void LiftoffAssembler::emit_f32_set_cond(LiftoffCondition liftoff_cond,
1724                                         Register dst, DoubleRegister lhs,
1725                                         DoubleRegister rhs) {
1726  Condition cond = liftoff::ToCondition(liftoff_cond);
1727  Label not_nan, cont;
1728  TurboAssembler::CompareIsNanF32(lhs, rhs);
1729  TurboAssembler::BranchFalseF(&not_nan);
1730  // If one of the operands is NaN, return 1 for f32.ne, else 0.
1731  if (cond == ne) {
1732    TurboAssembler::li(dst, 1);
1733  } else {
1734    TurboAssembler::Move(dst, zero_reg);
1735  }
1736  TurboAssembler::Branch(&cont);
1737
1738  bind(&not_nan);
1739
1740  TurboAssembler::li(dst, 1);
1741  bool predicate;
1742  FPUCondition fcond =
1743      liftoff::ConditionToConditionCmpFPU(liftoff_cond, &predicate);
1744  TurboAssembler::CompareF32(fcond, lhs, rhs);
1745  if (predicate) {
1746    TurboAssembler::LoadZeroIfNotFPUCondition(dst);
1747  } else {
1748    TurboAssembler::LoadZeroIfFPUCondition(dst);
1749  }
1750
1751  bind(&cont);
1752}
1753
1754void LiftoffAssembler::emit_f64_set_cond(LiftoffCondition liftoff_cond,
1755                                         Register dst, DoubleRegister lhs,
1756                                         DoubleRegister rhs) {
1757  Condition cond = liftoff::ToCondition(liftoff_cond);
1758  Label not_nan, cont;
1759  TurboAssembler::CompareIsNanF64(lhs, rhs);
1760  TurboAssembler::BranchFalseF(&not_nan);
1761  // If one of the operands is NaN, return 1 for f64.ne, else 0.
1762  if (cond == ne) {
1763    TurboAssembler::li(dst, 1);
1764  } else {
1765    TurboAssembler::Move(dst, zero_reg);
1766  }
1767  TurboAssembler::Branch(&cont);
1768
1769  bind(&not_nan);
1770
1771  TurboAssembler::li(dst, 1);
1772  bool predicate;
1773  FPUCondition fcond =
1774      liftoff::ConditionToConditionCmpFPU(liftoff_cond, &predicate);
1775  TurboAssembler::CompareF64(fcond, lhs, rhs);
1776  if (predicate) {
1777    TurboAssembler::LoadZeroIfNotFPUCondition(dst);
1778  } else {
1779    TurboAssembler::LoadZeroIfFPUCondition(dst);
1780  }
1781
1782  bind(&cont);
1783}
1784
1785bool LiftoffAssembler::emit_select(LiftoffRegister dst, Register condition,
1786                                   LiftoffRegister true_value,
1787                                   LiftoffRegister false_value,
1788                                   ValueKind kind) {
1789  return false;
1790}
1791
1792void LiftoffAssembler::emit_smi_check(Register obj, Label* target,
1793                                      SmiCheckMode mode) {
1794  UseScratchRegisterScope temps(this);
1795  Register scratch = temps.Acquire();
1796  And(scratch, obj, Operand(kSmiTagMask));
1797  Condition condition = mode == kJumpOnSmi ? eq : ne;
1798  Branch(target, condition, scratch, Operand(zero_reg));
1799}
1800
1801void LiftoffAssembler::LoadTransform(LiftoffRegister dst, Register src_addr,
1802                                     Register offset_reg, uintptr_t offset_imm,
1803                                     LoadType type,
1804                                     LoadTransformationKind transform,
1805                                     uint32_t* protected_load_pc) {
1806  bailout(kSimd, "load extend and load splat unimplemented");
1807}
1808
1809void LiftoffAssembler::StoreLane(Register dst, Register offset,
1810                                 uintptr_t offset_imm, LiftoffRegister src,
1811                                 StoreType type, uint8_t lane,
1812                                 uint32_t* protected_store_pc) {
1813  bailout(kSimd, "storelane");
1814}
1815
1816void LiftoffAssembler::LoadLane(LiftoffRegister dst, LiftoffRegister src,
1817                                Register addr, Register offset_reg,
1818                                uintptr_t offset_imm, LoadType type,
1819                                uint8_t laneidx, uint32_t* protected_load_pc) {
1820  bailout(kSimd, "loadlane");
1821}
1822
1823void LiftoffAssembler::emit_i8x16_shuffle(LiftoffRegister dst,
1824                                          LiftoffRegister lhs,
1825                                          LiftoffRegister rhs,
1826                                          const uint8_t shuffle[16],
1827                                          bool is_swizzle) {
1828  bailout(kSimd, "emit_i8x16_shuffle");
1829}
1830
1831void LiftoffAssembler::emit_i8x16_swizzle(LiftoffRegister dst,
1832                                          LiftoffRegister lhs,
1833                                          LiftoffRegister rhs) {
1834  bailout(kSimd, "emit_i8x16_swizzle");
1835}
1836
1837void LiftoffAssembler::emit_i8x16_splat(LiftoffRegister dst,
1838                                        LiftoffRegister src) {
1839  bailout(kSimd, "emit_i8x16_splat");
1840}
1841
1842void LiftoffAssembler::emit_i16x8_splat(LiftoffRegister dst,
1843                                        LiftoffRegister src) {
1844  bailout(kSimd, "emit_i16x8_splat");
1845}
1846
1847void LiftoffAssembler::emit_i32x4_splat(LiftoffRegister dst,
1848                                        LiftoffRegister src) {
1849  bailout(kSimd, "emit_i32x4_splat");
1850}
1851
1852void LiftoffAssembler::emit_i64x2_splat(LiftoffRegister dst,
1853                                        LiftoffRegister src) {
1854  bailout(kSimd, "emit_i64x2_splat");
1855}
1856
1857void LiftoffAssembler::emit_f32x4_splat(LiftoffRegister dst,
1858                                        LiftoffRegister src) {
1859  bailout(kSimd, "emit_f32x4_splat");
1860}
1861
1862void LiftoffAssembler::emit_f64x2_splat(LiftoffRegister dst,
1863                                        LiftoffRegister src) {
1864  bailout(kSimd, "emit_f64x2_splat");
1865}
1866
1867#define SIMD_BINOP(name, ilv_instr, dotp_instr)                          \
1868  void LiftoffAssembler::emit_##name(                                    \
1869      LiftoffRegister dst, LiftoffRegister src1, LiftoffRegister src2) { \
1870    MSARegister dst_msa = MSARegister::from_code(dst.liftoff_code());    \
1871    MSARegister src1_msa = MSARegister::from_code(src1.liftoff_code());  \
1872    MSARegister src2_msa = MSARegister::from_code(src2.liftoff_code());  \
1873    xor_v(kSimd128RegZero, kSimd128RegZero, kSimd128RegZero);            \
1874    ilv_instr(kSimd128ScratchReg, kSimd128RegZero, src1_msa);            \
1875    ilv_instr(kSimd128RegZero, kSimd128RegZero, src2_msa);               \
1876    dotp_instr(dst_msa, kSimd128ScratchReg, kSimd128RegZero);            \
1877  }
1878
1879SIMD_BINOP(i16x8_extmul_low_i8x16_s, ilvr_b, dotp_s_h)
1880SIMD_BINOP(i16x8_extmul_high_i8x16_s, ilvl_b, dotp_s_h)
1881SIMD_BINOP(i16x8_extmul_low_i8x16_u, ilvr_b, dotp_u_h)
1882SIMD_BINOP(i16x8_extmul_high_i8x16_u, ilvl_b, dotp_u_h)
1883
1884SIMD_BINOP(i32x4_extmul_low_i16x8_s, ilvr_h, dotp_s_w)
1885SIMD_BINOP(i32x4_extmul_high_i16x8_s, ilvl_h, dotp_s_w)
1886SIMD_BINOP(i32x4_extmul_low_i16x8_u, ilvr_h, dotp_u_w)
1887SIMD_BINOP(i32x4_extmul_high_i16x8_u, ilvl_h, dotp_u_w)
1888
1889SIMD_BINOP(i64x2_extmul_low_i32x4_s, ilvr_w, dotp_s_d)
1890SIMD_BINOP(i64x2_extmul_high_i32x4_s, ilvl_w, dotp_s_d)
1891SIMD_BINOP(i64x2_extmul_low_i32x4_u, ilvr_w, dotp_u_d)
1892SIMD_BINOP(i64x2_extmul_high_i32x4_u, ilvl_w, dotp_u_d)
1893
1894#undef SIMD_BINOP
1895
1896void LiftoffAssembler::emit_i16x8_q15mulr_sat_s(LiftoffRegister dst,
1897                                                LiftoffRegister src1,
1898                                                LiftoffRegister src2) {
1899  bailout(kSimd, "i16x8_q15mulr_sat_s");
1900}
1901
1902void LiftoffAssembler::emit_i8x16_eq(LiftoffRegister dst, LiftoffRegister lhs,
1903                                     LiftoffRegister rhs) {
1904  bailout(kSimd, "emit_i8x16_eq");
1905}
1906
1907void LiftoffAssembler::emit_i8x16_ne(LiftoffRegister dst, LiftoffRegister lhs,
1908                                     LiftoffRegister rhs) {
1909  bailout(kSimd, "emit_i8x16_ne");
1910}
1911
1912void LiftoffAssembler::emit_i8x16_gt_s(LiftoffRegister dst, LiftoffRegister lhs,
1913                                       LiftoffRegister rhs) {
1914  bailout(kSimd, "emit_i8x16_gt_s");
1915}
1916
1917void LiftoffAssembler::emit_i8x16_gt_u(LiftoffRegister dst, LiftoffRegister lhs,
1918                                       LiftoffRegister rhs) {
1919  bailout(kSimd, "emit_i8x16_gt_u");
1920}
1921
1922void LiftoffAssembler::emit_i8x16_ge_s(LiftoffRegister dst, LiftoffRegister lhs,
1923                                       LiftoffRegister rhs) {
1924  bailout(kSimd, "emit_i8x16_ge_s");
1925}
1926
1927void LiftoffAssembler::emit_i8x16_ge_u(LiftoffRegister dst, LiftoffRegister lhs,
1928                                       LiftoffRegister rhs) {
1929  bailout(kSimd, "emit_i8x16_ge_u");
1930}
1931
1932void LiftoffAssembler::emit_i16x8_eq(LiftoffRegister dst, LiftoffRegister lhs,
1933                                     LiftoffRegister rhs) {
1934  bailout(kSimd, "emit_i16x8_eq");
1935}
1936
1937void LiftoffAssembler::emit_i16x8_ne(LiftoffRegister dst, LiftoffRegister lhs,
1938                                     LiftoffRegister rhs) {
1939  bailout(kSimd, "emit_i16x8_ne");
1940}
1941
1942void LiftoffAssembler::emit_i16x8_gt_s(LiftoffRegister dst, LiftoffRegister lhs,
1943                                       LiftoffRegister rhs) {
1944  bailout(kSimd, "emit_i16x8_gt_s");
1945}
1946
1947void LiftoffAssembler::emit_i16x8_gt_u(LiftoffRegister dst, LiftoffRegister lhs,
1948                                       LiftoffRegister rhs) {
1949  bailout(kSimd, "emit_i16x8_gt_u");
1950}
1951
1952void LiftoffAssembler::emit_i16x8_ge_s(LiftoffRegister dst, LiftoffRegister lhs,
1953                                       LiftoffRegister rhs) {
1954  bailout(kSimd, "emit_i16x8_ge_s");
1955}
1956
1957void LiftoffAssembler::emit_i16x8_ge_u(LiftoffRegister dst, LiftoffRegister lhs,
1958                                       LiftoffRegister rhs) {
1959  bailout(kSimd, "emit_i16x8_ge_u");
1960}
1961
1962void LiftoffAssembler::emit_i32x4_eq(LiftoffRegister dst, LiftoffRegister lhs,
1963                                     LiftoffRegister rhs) {
1964  bailout(kSimd, "emit_i32x4_eq");
1965}
1966
1967void LiftoffAssembler::emit_i32x4_ne(LiftoffRegister dst, LiftoffRegister lhs,
1968                                     LiftoffRegister rhs) {
1969  bailout(kSimd, "emit_i32x4_ne");
1970}
1971
1972void LiftoffAssembler::emit_i32x4_gt_s(LiftoffRegister dst, LiftoffRegister lhs,
1973                                       LiftoffRegister rhs) {
1974  bailout(kSimd, "emit_i32x4_gt_s");
1975}
1976
1977void LiftoffAssembler::emit_i32x4_gt_u(LiftoffRegister dst, LiftoffRegister lhs,
1978                                       LiftoffRegister rhs) {
1979  bailout(kSimd, "emit_i32x4_gt_u");
1980}
1981
1982void LiftoffAssembler::emit_i32x4_ge_s(LiftoffRegister dst, LiftoffRegister lhs,
1983                                       LiftoffRegister rhs) {
1984  bailout(kSimd, "emit_i32x4_ge_s");
1985}
1986
1987void LiftoffAssembler::emit_i32x4_ge_u(LiftoffRegister dst, LiftoffRegister lhs,
1988                                       LiftoffRegister rhs) {
1989  bailout(kSimd, "emit_i32x4_ge_u");
1990}
1991
1992void LiftoffAssembler::emit_f32x4_eq(LiftoffRegister dst, LiftoffRegister lhs,
1993                                     LiftoffRegister rhs) {
1994  bailout(kSimd, "emit_f32x4_eq");
1995}
1996
1997void LiftoffAssembler::emit_f32x4_ne(LiftoffRegister dst, LiftoffRegister lhs,
1998                                     LiftoffRegister rhs) {
1999  bailout(kSimd, "emit_f32x4_ne");
2000}
2001
2002void LiftoffAssembler::emit_f32x4_lt(LiftoffRegister dst, LiftoffRegister lhs,
2003                                     LiftoffRegister rhs) {
2004  bailout(kSimd, "emit_f32x4_lt");
2005}
2006
2007void LiftoffAssembler::emit_f32x4_le(LiftoffRegister dst, LiftoffRegister lhs,
2008                                     LiftoffRegister rhs) {
2009  bailout(kSimd, "emit_f32x4_le");
2010}
2011
2012void LiftoffAssembler::emit_i64x2_eq(LiftoffRegister dst, LiftoffRegister lhs,
2013                                     LiftoffRegister rhs) {
2014  bailout(kSimd, "emit_i64x2_eq");
2015}
2016
2017void LiftoffAssembler::emit_i64x2_ne(LiftoffRegister dst, LiftoffRegister lhs,
2018                                     LiftoffRegister rhs) {
2019  bailout(kSimd, "emit_i64x2_ne");
2020}
2021
2022void LiftoffAssembler::emit_i64x2_abs(LiftoffRegister dst,
2023                                      LiftoffRegister src) {
2024  bailout(kSimd, "emit_i64x2_abs");
2025}
2026
2027void LiftoffAssembler::emit_f64x2_eq(LiftoffRegister dst, LiftoffRegister lhs,
2028                                     LiftoffRegister rhs) {
2029  bailout(kSimd, "emit_f64x2_eq");
2030}
2031
2032void LiftoffAssembler::emit_f64x2_ne(LiftoffRegister dst, LiftoffRegister lhs,
2033                                     LiftoffRegister rhs) {
2034  bailout(kSimd, "emit_f64x2_ne");
2035}
2036
2037void LiftoffAssembler::emit_f64x2_lt(LiftoffRegister dst, LiftoffRegister lhs,
2038                                     LiftoffRegister rhs) {
2039  bailout(kSimd, "emit_f64x2_lt");
2040}
2041
2042void LiftoffAssembler::emit_f64x2_le(LiftoffRegister dst, LiftoffRegister lhs,
2043                                     LiftoffRegister rhs) {
2044  bailout(kSimd, "emit_f64x2_le");
2045}
2046
2047void LiftoffAssembler::emit_s128_const(LiftoffRegister dst,
2048                                       const uint8_t imms[16]) {
2049  bailout(kSimd, "emit_s128_const");
2050}
2051
2052void LiftoffAssembler::emit_s128_not(LiftoffRegister dst, LiftoffRegister src) {
2053  bailout(kSimd, "emit_s128_not");
2054}
2055
2056void LiftoffAssembler::emit_s128_and(LiftoffRegister dst, LiftoffRegister lhs,
2057                                     LiftoffRegister rhs) {
2058  bailout(kSimd, "emit_s128_and");
2059}
2060
2061void LiftoffAssembler::emit_s128_or(LiftoffRegister dst, LiftoffRegister lhs,
2062                                    LiftoffRegister rhs) {
2063  bailout(kSimd, "emit_s128_or");
2064}
2065
2066void LiftoffAssembler::emit_s128_xor(LiftoffRegister dst, LiftoffRegister lhs,
2067                                     LiftoffRegister rhs) {
2068  bailout(kSimd, "emit_s128_xor");
2069}
2070
2071void LiftoffAssembler::emit_s128_and_not(LiftoffRegister dst,
2072                                         LiftoffRegister lhs,
2073                                         LiftoffRegister rhs) {
2074  bailout(kSimd, "emit_s128_and_not");
2075}
2076
2077void LiftoffAssembler::emit_s128_select(LiftoffRegister dst,
2078                                        LiftoffRegister src1,
2079                                        LiftoffRegister src2,
2080                                        LiftoffRegister mask) {
2081  bailout(kSimd, "emit_s128_select");
2082}
2083
2084void LiftoffAssembler::emit_i8x16_neg(LiftoffRegister dst,
2085                                      LiftoffRegister src) {
2086  bailout(kSimd, "emit_i8x16_neg");
2087}
2088
2089void LiftoffAssembler::emit_v128_anytrue(LiftoffRegister dst,
2090                                         LiftoffRegister src) {
2091  bailout(kSimd, "emit_v128_anytrue");
2092}
2093
2094void LiftoffAssembler::emit_i8x16_alltrue(LiftoffRegister dst,
2095                                          LiftoffRegister src) {
2096  bailout(kSimd, "emit_i8x16_alltrue");
2097}
2098
2099void LiftoffAssembler::emit_i8x16_bitmask(LiftoffRegister dst,
2100                                          LiftoffRegister src) {
2101  bailout(kSimd, "emit_i8x16_bitmask");
2102}
2103
2104void LiftoffAssembler::emit_i8x16_shl(LiftoffRegister dst, LiftoffRegister lhs,
2105                                      LiftoffRegister rhs) {
2106  bailout(kSimd, "emit_i8x16_shl");
2107}
2108
2109void LiftoffAssembler::emit_i8x16_shli(LiftoffRegister dst, LiftoffRegister lhs,
2110                                       int32_t rhs) {
2111  bailout(kSimd, "emit_i8x16_shli");
2112}
2113
2114void LiftoffAssembler::emit_i8x16_shr_s(LiftoffRegister dst,
2115                                        LiftoffRegister lhs,
2116                                        LiftoffRegister rhs) {
2117  bailout(kSimd, "emit_i8x16_shr_s");
2118}
2119
2120void LiftoffAssembler::emit_i8x16_shri_s(LiftoffRegister dst,
2121                                         LiftoffRegister lhs, int32_t rhs) {
2122  bailout(kSimd, "emit_i8x16_shri_s");
2123}
2124
2125void LiftoffAssembler::emit_i8x16_shr_u(LiftoffRegister dst,
2126                                        LiftoffRegister lhs,
2127                                        LiftoffRegister rhs) {
2128  bailout(kSimd, "emit_i8x16_shr_u");
2129}
2130
2131void LiftoffAssembler::emit_i8x16_shri_u(LiftoffRegister dst,
2132                                         LiftoffRegister lhs, int32_t rhs) {
2133  bailout(kSimd, "emit_i8x16_shri_u");
2134}
2135
2136void LiftoffAssembler::emit_i8x16_add(LiftoffRegister dst, LiftoffRegister lhs,
2137                                      LiftoffRegister rhs) {
2138  bailout(kSimd, "emit_i8x16_add");
2139}
2140
2141void LiftoffAssembler::emit_i8x16_add_sat_s(LiftoffRegister dst,
2142                                            LiftoffRegister lhs,
2143                                            LiftoffRegister rhs) {
2144  bailout(kSimd, "emit_i8x16_add_sat_s");
2145}
2146
2147void LiftoffAssembler::emit_i8x16_add_sat_u(LiftoffRegister dst,
2148                                            LiftoffRegister lhs,
2149                                            LiftoffRegister rhs) {
2150  bailout(kSimd, "emit_i8x16_add_sat_u");
2151}
2152
2153void LiftoffAssembler::emit_i8x16_sub(LiftoffRegister dst, LiftoffRegister lhs,
2154                                      LiftoffRegister rhs) {
2155  bailout(kSimd, "emit_i8x16_sub");
2156}
2157
2158void LiftoffAssembler::emit_i8x16_sub_sat_s(LiftoffRegister dst,
2159                                            LiftoffRegister lhs,
2160                                            LiftoffRegister rhs) {
2161  bailout(kSimd, "emit_i8x16_sub_sat_s");
2162}
2163
2164void LiftoffAssembler::emit_i8x16_sub_sat_u(LiftoffRegister dst,
2165                                            LiftoffRegister lhs,
2166                                            LiftoffRegister rhs) {
2167  bailout(kSimd, "emit_i8x16_sub_sat_u");
2168}
2169
2170void LiftoffAssembler::emit_i8x16_min_s(LiftoffRegister dst,
2171                                        LiftoffRegister lhs,
2172                                        LiftoffRegister rhs) {
2173  bailout(kSimd, "emit_i8x16_min_s");
2174}
2175
2176void LiftoffAssembler::emit_i8x16_min_u(LiftoffRegister dst,
2177                                        LiftoffRegister lhs,
2178                                        LiftoffRegister rhs) {
2179  bailout(kSimd, "emit_i8x16_min_u");
2180}
2181
2182void LiftoffAssembler::emit_i8x16_max_s(LiftoffRegister dst,
2183                                        LiftoffRegister lhs,
2184                                        LiftoffRegister rhs) {
2185  bailout(kSimd, "emit_i8x16_max_s");
2186}
2187
2188void LiftoffAssembler::emit_i8x16_max_u(LiftoffRegister dst,
2189                                        LiftoffRegister lhs,
2190                                        LiftoffRegister rhs) {
2191  bailout(kSimd, "emit_i8x16_max_u");
2192}
2193
2194void LiftoffAssembler::emit_i8x16_popcnt(LiftoffRegister dst,
2195                                         LiftoffRegister src) {
2196  bailout(kSimd, "emit_i8x16_popcnt");
2197}
2198
2199void LiftoffAssembler::emit_i16x8_neg(LiftoffRegister dst,
2200                                      LiftoffRegister src) {
2201  bailout(kSimd, "emit_i16x8_neg");
2202}
2203
2204void LiftoffAssembler::emit_i16x8_alltrue(LiftoffRegister dst,
2205                                          LiftoffRegister src) {
2206  bailout(kSimd, "emit_i16x8_alltrue");
2207}
2208
2209void LiftoffAssembler::emit_i16x8_bitmask(LiftoffRegister dst,
2210                                          LiftoffRegister src) {
2211  bailout(kSimd, "emit_i16x8_bitmask");
2212}
2213
2214void LiftoffAssembler::emit_i16x8_shl(LiftoffRegister dst, LiftoffRegister lhs,
2215                                      LiftoffRegister rhs) {
2216  bailout(kSimd, "emit_i16x8_shl");
2217}
2218
2219void LiftoffAssembler::emit_i16x8_shli(LiftoffRegister dst, LiftoffRegister lhs,
2220                                       int32_t rhs) {
2221  bailout(kSimd, "emit_i16x8_shli");
2222}
2223
2224void LiftoffAssembler::emit_i16x8_shr_s(LiftoffRegister dst,
2225                                        LiftoffRegister lhs,
2226                                        LiftoffRegister rhs) {
2227  bailout(kSimd, "emit_i16x8_shr_s");
2228}
2229
2230void LiftoffAssembler::emit_i16x8_shri_s(LiftoffRegister dst,
2231                                         LiftoffRegister lhs, int32_t rhs) {
2232  bailout(kSimd, "emit_i16x8_shri_s");
2233}
2234
2235void LiftoffAssembler::emit_i16x8_shr_u(LiftoffRegister dst,
2236                                        LiftoffRegister lhs,
2237                                        LiftoffRegister rhs) {
2238  bailout(kSimd, "emit_i16x8_shr_u");
2239}
2240
2241void LiftoffAssembler::emit_i16x8_shri_u(LiftoffRegister dst,
2242                                         LiftoffRegister lhs, int32_t rhs) {
2243  bailout(kSimd, "emit_i16x8_shri_u");
2244}
2245
2246void LiftoffAssembler::emit_i16x8_add(LiftoffRegister dst, LiftoffRegister lhs,
2247                                      LiftoffRegister rhs) {
2248  bailout(kSimd, "emit_i16x8_add");
2249}
2250
2251void LiftoffAssembler::emit_i16x8_add_sat_s(LiftoffRegister dst,
2252                                            LiftoffRegister lhs,
2253                                            LiftoffRegister rhs) {
2254  bailout(kSimd, "emit_i16x8_add_sat_s");
2255}
2256
2257void LiftoffAssembler::emit_i16x8_add_sat_u(LiftoffRegister dst,
2258                                            LiftoffRegister lhs,
2259                                            LiftoffRegister rhs) {
2260  bailout(kSimd, "emit_i16x8_add_sat_u");
2261}
2262
2263void LiftoffAssembler::emit_i16x8_sub(LiftoffRegister dst, LiftoffRegister lhs,
2264                                      LiftoffRegister rhs) {
2265  bailout(kSimd, "emit_i16x8_sub");
2266}
2267
2268void LiftoffAssembler::emit_i16x8_sub_sat_s(LiftoffRegister dst,
2269                                            LiftoffRegister lhs,
2270                                            LiftoffRegister rhs) {
2271  bailout(kSimd, "emit_i16x8_sub_sat_s");
2272}
2273
2274void LiftoffAssembler::emit_i16x8_sub_sat_u(LiftoffRegister dst,
2275                                            LiftoffRegister lhs,
2276                                            LiftoffRegister rhs) {
2277  bailout(kSimd, "emit_i16x8_sub_sat_u");
2278}
2279
2280void LiftoffAssembler::emit_i16x8_mul(LiftoffRegister dst, LiftoffRegister lhs,
2281                                      LiftoffRegister rhs) {
2282  bailout(kSimd, "emit_i16x8_mul");
2283}
2284
2285void LiftoffAssembler::emit_i16x8_min_s(LiftoffRegister dst,
2286                                        LiftoffRegister lhs,
2287                                        LiftoffRegister rhs) {
2288  bailout(kSimd, "emit_i16x8_min_s");
2289}
2290
2291void LiftoffAssembler::emit_i16x8_min_u(LiftoffRegister dst,
2292                                        LiftoffRegister lhs,
2293                                        LiftoffRegister rhs) {
2294  bailout(kSimd, "emit_i16x8_min_u");
2295}
2296
2297void LiftoffAssembler::emit_i16x8_max_s(LiftoffRegister dst,
2298                                        LiftoffRegister lhs,
2299                                        LiftoffRegister rhs) {
2300  bailout(kSimd, "emit_i16x8_max_s");
2301}
2302
2303void LiftoffAssembler::emit_i16x8_max_u(LiftoffRegister dst,
2304                                        LiftoffRegister lhs,
2305                                        LiftoffRegister rhs) {
2306  bailout(kSimd, "emit_i16x8_max_u");
2307}
2308
2309void LiftoffAssembler::emit_i16x8_extadd_pairwise_i8x16_s(LiftoffRegister dst,
2310                                                          LiftoffRegister src) {
2311  bailout(kSimd, "emit_i16x8_extadd_pairwise_i8x16_s");
2312}
2313
2314void LiftoffAssembler::emit_i16x8_extadd_pairwise_i8x16_u(LiftoffRegister dst,
2315                                                          LiftoffRegister src) {
2316  bailout(kSimd, "emit_i16x8_extadd_pairwise_i8x16_u");
2317}
2318
2319void LiftoffAssembler::emit_i32x4_neg(LiftoffRegister dst,
2320                                      LiftoffRegister src) {
2321  bailout(kSimd, "emit_i32x4_neg");
2322}
2323
2324void LiftoffAssembler::emit_i32x4_alltrue(LiftoffRegister dst,
2325                                          LiftoffRegister src) {
2326  bailout(kSimd, "emit_i32x4_alltrue");
2327}
2328
2329void LiftoffAssembler::emit_i32x4_bitmask(LiftoffRegister dst,
2330                                          LiftoffRegister src) {
2331  bailout(kSimd, "emit_i32x4_bitmask");
2332}
2333
2334void LiftoffAssembler::emit_i32x4_shl(LiftoffRegister dst, LiftoffRegister lhs,
2335                                      LiftoffRegister rhs) {
2336  bailout(kSimd, "emit_i32x4_shl");
2337}
2338
2339void LiftoffAssembler::emit_i32x4_shli(LiftoffRegister dst, LiftoffRegister lhs,
2340                                       int32_t rhs) {
2341  bailout(kSimd, "emit_i32x4_shli");
2342}
2343
2344void LiftoffAssembler::emit_i32x4_shr_s(LiftoffRegister dst,
2345                                        LiftoffRegister lhs,
2346                                        LiftoffRegister rhs) {
2347  bailout(kSimd, "emit_i32x4_shr_s");
2348}
2349
2350void LiftoffAssembler::emit_i32x4_shri_s(LiftoffRegister dst,
2351                                         LiftoffRegister lhs, int32_t rhs) {
2352  bailout(kSimd, "emit_i32x4_shri_s");
2353}
2354
2355void LiftoffAssembler::emit_i32x4_shr_u(LiftoffRegister dst,
2356                                        LiftoffRegister lhs,
2357                                        LiftoffRegister rhs) {
2358  bailout(kSimd, "emit_i32x4_shr_u");
2359}
2360
2361void LiftoffAssembler::emit_i32x4_shri_u(LiftoffRegister dst,
2362                                         LiftoffRegister lhs, int32_t rhs) {
2363  bailout(kSimd, "emit_i32x4_shri_u");
2364}
2365
2366void LiftoffAssembler::emit_i32x4_add(LiftoffRegister dst, LiftoffRegister lhs,
2367                                      LiftoffRegister rhs) {
2368  bailout(kSimd, "emit_i32x4_add");
2369}
2370
2371void LiftoffAssembler::emit_i32x4_sub(LiftoffRegister dst, LiftoffRegister lhs,
2372                                      LiftoffRegister rhs) {
2373  bailout(kSimd, "emit_i32x4_sub");
2374}
2375
2376void LiftoffAssembler::emit_i32x4_mul(LiftoffRegister dst, LiftoffRegister lhs,
2377                                      LiftoffRegister rhs) {
2378  bailout(kSimd, "emit_i32x4_mul");
2379}
2380
2381void LiftoffAssembler::emit_i32x4_min_s(LiftoffRegister dst,
2382                                        LiftoffRegister lhs,
2383                                        LiftoffRegister rhs) {
2384  bailout(kSimd, "emit_i32x4_min_s");
2385}
2386
2387void LiftoffAssembler::emit_i32x4_min_u(LiftoffRegister dst,
2388                                        LiftoffRegister lhs,
2389                                        LiftoffRegister rhs) {
2390  bailout(kSimd, "emit_i32x4_min_u");
2391}
2392
2393void LiftoffAssembler::emit_i32x4_max_s(LiftoffRegister dst,
2394                                        LiftoffRegister lhs,
2395                                        LiftoffRegister rhs) {
2396  bailout(kSimd, "emit_i32x4_max_s");
2397}
2398
2399void LiftoffAssembler::emit_i32x4_max_u(LiftoffRegister dst,
2400                                        LiftoffRegister lhs,
2401                                        LiftoffRegister rhs) {
2402  bailout(kSimd, "emit_i32x4_max_u");
2403}
2404
2405void LiftoffAssembler::emit_i32x4_dot_i16x8_s(LiftoffRegister dst,
2406                                              LiftoffRegister lhs,
2407                                              LiftoffRegister rhs) {
2408  bailout(kSimd, "emit_i32x4_dot_i16x8_s");
2409}
2410
2411void LiftoffAssembler::emit_i32x4_extadd_pairwise_i16x8_s(LiftoffRegister dst,
2412                                                          LiftoffRegister src) {
2413  bailout(kSimd, "emit_i32x4_extadd_pairwise_i16x8_s");
2414}
2415
2416void LiftoffAssembler::emit_i32x4_extadd_pairwise_i16x8_u(LiftoffRegister dst,
2417                                                          LiftoffRegister src) {
2418  bailout(kSimd, "emit_i32x4_extadd_pairwise_i16x8_u");
2419}
2420
2421void LiftoffAssembler::emit_i64x2_neg(LiftoffRegister dst,
2422                                      LiftoffRegister src) {
2423  bailout(kSimd, "emit_i64x2_neg");
2424}
2425
2426void LiftoffAssembler::emit_i64x2_alltrue(LiftoffRegister dst,
2427                                          LiftoffRegister src) {
2428  bailout(kSimd, "emit_i64x2_alltrue");
2429}
2430
2431void LiftoffAssembler::emit_i64x2_bitmask(LiftoffRegister dst,
2432                                          LiftoffRegister src) {
2433  bailout(kSimd, "emit_i64x2_bitmask");
2434}
2435
2436void LiftoffAssembler::emit_i64x2_shl(LiftoffRegister dst, LiftoffRegister lhs,
2437                                      LiftoffRegister rhs) {
2438  bailout(kSimd, "emit_i64x2_shl");
2439}
2440
2441void LiftoffAssembler::emit_i64x2_shli(LiftoffRegister dst, LiftoffRegister lhs,
2442                                       int32_t rhs) {
2443  bailout(kSimd, "emit_i64x2_shli");
2444}
2445
2446void LiftoffAssembler::emit_i64x2_shr_s(LiftoffRegister dst,
2447                                        LiftoffRegister lhs,
2448                                        LiftoffRegister rhs) {
2449  bailout(kSimd, "emit_i64x2_shr_s");
2450}
2451
2452void LiftoffAssembler::emit_i64x2_shri_s(LiftoffRegister dst,
2453                                         LiftoffRegister lhs, int32_t rhs) {
2454  bailout(kSimd, "emit_i64x2_shri_s");
2455}
2456
2457void LiftoffAssembler::emit_i64x2_shr_u(LiftoffRegister dst,
2458                                        LiftoffRegister lhs,
2459                                        LiftoffRegister rhs) {
2460  bailout(kSimd, "emit_i64x2_shr_u");
2461}
2462
2463void LiftoffAssembler::emit_i64x2_shri_u(LiftoffRegister dst,
2464                                         LiftoffRegister lhs, int32_t rhs) {
2465  bailout(kSimd, "emit_i64x2_shri_u");
2466}
2467
2468void LiftoffAssembler::emit_i64x2_add(LiftoffRegister dst, LiftoffRegister lhs,
2469                                      LiftoffRegister rhs) {
2470  bailout(kSimd, "emit_i64x2_add");
2471}
2472
2473void LiftoffAssembler::emit_i64x2_sub(LiftoffRegister dst, LiftoffRegister lhs,
2474                                      LiftoffRegister rhs) {
2475  bailout(kSimd, "emit_i64x2_sub");
2476}
2477
2478void LiftoffAssembler::emit_i64x2_mul(LiftoffRegister dst, LiftoffRegister lhs,
2479                                      LiftoffRegister rhs) {
2480  bailout(kSimd, "emit_i64x2_mul");
2481}
2482
2483void LiftoffAssembler::emit_i64x2_gt_s(LiftoffRegister dst, LiftoffRegister lhs,
2484                                       LiftoffRegister rhs) {
2485  bailout(kSimd, "emit_i64x2_gt_s");
2486}
2487
2488void LiftoffAssembler::emit_i64x2_ge_s(LiftoffRegister dst, LiftoffRegister lhs,
2489                                       LiftoffRegister rhs) {
2490  bailout(kSimd, "emit_i64x2_ge_s");
2491}
2492
2493void LiftoffAssembler::emit_f32x4_abs(LiftoffRegister dst,
2494                                      LiftoffRegister src) {
2495  bailout(kSimd, "emit_f32x4_abs");
2496}
2497
2498void LiftoffAssembler::emit_f32x4_neg(LiftoffRegister dst,
2499                                      LiftoffRegister src) {
2500  bailout(kSimd, "emit_f32x4_neg");
2501}
2502
2503void LiftoffAssembler::emit_f32x4_sqrt(LiftoffRegister dst,
2504                                       LiftoffRegister src) {
2505  bailout(kSimd, "emit_f32x4_sqrt");
2506}
2507
2508bool LiftoffAssembler::emit_f32x4_ceil(LiftoffRegister dst,
2509                                       LiftoffRegister src) {
2510  return false;
2511}
2512
2513bool LiftoffAssembler::emit_f32x4_floor(LiftoffRegister dst,
2514                                        LiftoffRegister src) {
2515  return false;
2516}
2517
2518bool LiftoffAssembler::emit_f32x4_trunc(LiftoffRegister dst,
2519                                        LiftoffRegister src) {
2520  return false;
2521}
2522
2523bool LiftoffAssembler::emit_f32x4_nearest_int(LiftoffRegister dst,
2524                                              LiftoffRegister src) {
2525  return false;
2526}
2527
2528void LiftoffAssembler::emit_f32x4_add(LiftoffRegister dst, LiftoffRegister lhs,
2529                                      LiftoffRegister rhs) {
2530  bailout(kSimd, "emit_f32x4_add");
2531}
2532
2533void LiftoffAssembler::emit_f32x4_sub(LiftoffRegister dst, LiftoffRegister lhs,
2534                                      LiftoffRegister rhs) {
2535  bailout(kSimd, "emit_f32x4_sub");
2536}
2537
2538void LiftoffAssembler::emit_f32x4_mul(LiftoffRegister dst, LiftoffRegister lhs,
2539                                      LiftoffRegister rhs) {
2540  bailout(kSimd, "emit_f32x4_mul");
2541}
2542
2543void LiftoffAssembler::emit_f32x4_div(LiftoffRegister dst, LiftoffRegister lhs,
2544                                      LiftoffRegister rhs) {
2545  bailout(kSimd, "emit_f32x4_div");
2546}
2547
2548void LiftoffAssembler::emit_f32x4_min(LiftoffRegister dst, LiftoffRegister lhs,
2549                                      LiftoffRegister rhs) {
2550  bailout(kSimd, "emit_f32x4_min");
2551}
2552
2553void LiftoffAssembler::emit_f32x4_max(LiftoffRegister dst, LiftoffRegister lhs,
2554                                      LiftoffRegister rhs) {
2555  bailout(kSimd, "emit_f32x4_max");
2556}
2557
2558void LiftoffAssembler::emit_f32x4_pmin(LiftoffRegister dst, LiftoffRegister lhs,
2559                                       LiftoffRegister rhs) {
2560  bailout(kSimd, "emit_f32x4_pmin");
2561}
2562
2563void LiftoffAssembler::emit_f32x4_pmax(LiftoffRegister dst, LiftoffRegister lhs,
2564                                       LiftoffRegister rhs) {
2565  bailout(kSimd, "emit_f32x4_pmax");
2566}
2567
2568void LiftoffAssembler::emit_f64x2_abs(LiftoffRegister dst,
2569                                      LiftoffRegister src) {
2570  bailout(kSimd, "emit_f64x2_abs");
2571}
2572
2573void LiftoffAssembler::emit_f64x2_neg(LiftoffRegister dst,
2574                                      LiftoffRegister src) {
2575  bailout(kSimd, "emit_f64x2_neg");
2576}
2577
2578void LiftoffAssembler::emit_f64x2_sqrt(LiftoffRegister dst,
2579                                       LiftoffRegister src) {
2580  bailout(kSimd, "emit_f64x2_sqrt");
2581}
2582
2583bool LiftoffAssembler::emit_f64x2_ceil(LiftoffRegister dst,
2584                                       LiftoffRegister src) {
2585  return false;
2586}
2587
2588bool LiftoffAssembler::emit_f64x2_floor(LiftoffRegister dst,
2589                                        LiftoffRegister src) {
2590  return false;
2591}
2592
2593bool LiftoffAssembler::emit_f64x2_trunc(LiftoffRegister dst,
2594                                        LiftoffRegister src) {
2595  return false;
2596}
2597
2598bool LiftoffAssembler::emit_f64x2_nearest_int(LiftoffRegister dst,
2599                                              LiftoffRegister src) {
2600  return false;
2601}
2602
2603void LiftoffAssembler::emit_f64x2_add(LiftoffRegister dst, LiftoffRegister lhs,
2604                                      LiftoffRegister rhs) {
2605  bailout(kSimd, "emit_f64x2_add");
2606}
2607
2608void LiftoffAssembler::emit_f64x2_sub(LiftoffRegister dst, LiftoffRegister lhs,
2609                                      LiftoffRegister rhs) {
2610  bailout(kSimd, "emit_f64x2_sub");
2611}
2612
2613void LiftoffAssembler::emit_f64x2_mul(LiftoffRegister dst, LiftoffRegister lhs,
2614                                      LiftoffRegister rhs) {
2615  bailout(kSimd, "emit_f64x2_mul");
2616}
2617
2618void LiftoffAssembler::emit_f64x2_div(LiftoffRegister dst, LiftoffRegister lhs,
2619                                      LiftoffRegister rhs) {
2620  bailout(kSimd, "emit_f64x2_div");
2621}
2622
2623void LiftoffAssembler::emit_f64x2_min(LiftoffRegister dst, LiftoffRegister lhs,
2624                                      LiftoffRegister rhs) {
2625  bailout(kSimd, "emit_f64x2_min");
2626}
2627
2628void LiftoffAssembler::emit_f64x2_max(LiftoffRegister dst, LiftoffRegister lhs,
2629                                      LiftoffRegister rhs) {
2630  bailout(kSimd, "emit_f64x2_max");
2631}
2632
2633void LiftoffAssembler::emit_f64x2_pmin(LiftoffRegister dst, LiftoffRegister lhs,
2634                                       LiftoffRegister rhs) {
2635  bailout(kSimd, "emit_f64x2_pmin");
2636}
2637
2638void LiftoffAssembler::emit_f64x2_pmax(LiftoffRegister dst, LiftoffRegister lhs,
2639                                       LiftoffRegister rhs) {
2640  bailout(kSimd, "emit_f64x2_pmax");
2641}
2642
2643void LiftoffAssembler::emit_f64x2_convert_low_i32x4_s(LiftoffRegister dst,
2644                                                      LiftoffRegister src) {
2645  bailout(kSimd, "emit_f64x2_convert_low_i32x4_s");
2646}
2647
2648void LiftoffAssembler::emit_f64x2_convert_low_i32x4_u(LiftoffRegister dst,
2649                                                      LiftoffRegister src) {
2650  bailout(kSimd, "emit_f64x2_convert_low_i32x4_u");
2651}
2652
2653void LiftoffAssembler::emit_f64x2_promote_low_f32x4(LiftoffRegister dst,
2654                                                    LiftoffRegister src) {
2655  bailout(kSimd, "emit_f64x2_promote_low_f32x4");
2656}
2657
2658void LiftoffAssembler::emit_i32x4_sconvert_f32x4(LiftoffRegister dst,
2659                                                 LiftoffRegister src) {
2660  bailout(kSimd, "emit_i32x4_sconvert_f32x4");
2661}
2662
2663void LiftoffAssembler::emit_i32x4_uconvert_f32x4(LiftoffRegister dst,
2664                                                 LiftoffRegister src) {
2665  bailout(kSimd, "emit_i32x4_uconvert_f32x4");
2666}
2667
2668void LiftoffAssembler::emit_i32x4_trunc_sat_f64x2_s_zero(LiftoffRegister dst,
2669                                                         LiftoffRegister src) {
2670  bailout(kSimd, "emit_i32x4_trunc_sat_f64x2_s_zero");
2671}
2672
2673void LiftoffAssembler::emit_i32x4_trunc_sat_f64x2_u_zero(LiftoffRegister dst,
2674                                                         LiftoffRegister src) {
2675  bailout(kSimd, "emit_i32x4_trunc_sat_f64x2_u_zero");
2676}
2677
2678void LiftoffAssembler::emit_f32x4_sconvert_i32x4(LiftoffRegister dst,
2679                                                 LiftoffRegister src) {
2680  bailout(kSimd, "emit_f32x4_sconvert_i32x4");
2681}
2682
2683void LiftoffAssembler::emit_f32x4_uconvert_i32x4(LiftoffRegister dst,
2684                                                 LiftoffRegister src) {
2685  bailout(kSimd, "emit_f32x4_uconvert_i32x4");
2686}
2687
2688void LiftoffAssembler::emit_f32x4_demote_f64x2_zero(LiftoffRegister dst,
2689                                                    LiftoffRegister src) {
2690  bailout(kSimd, "emit_f32x4_demote_f64x2_zero");
2691}
2692
2693void LiftoffAssembler::emit_i8x16_sconvert_i16x8(LiftoffRegister dst,
2694                                                 LiftoffRegister lhs,
2695                                                 LiftoffRegister rhs) {
2696  bailout(kSimd, "emit_i8x16_sconvert_i16x8");
2697}
2698
2699void LiftoffAssembler::emit_i8x16_uconvert_i16x8(LiftoffRegister dst,
2700                                                 LiftoffRegister lhs,
2701                                                 LiftoffRegister rhs) {
2702  bailout(kSimd, "emit_i8x16_uconvert_i16x8");
2703}
2704
2705void LiftoffAssembler::emit_i16x8_sconvert_i32x4(LiftoffRegister dst,
2706                                                 LiftoffRegister lhs,
2707                                                 LiftoffRegister rhs) {
2708  bailout(kSimd, "emit_i16x8_sconvert_i32x4");
2709}
2710
2711void LiftoffAssembler::emit_i16x8_uconvert_i32x4(LiftoffRegister dst,
2712                                                 LiftoffRegister lhs,
2713                                                 LiftoffRegister rhs) {
2714  bailout(kSimd, "emit_i16x8_uconvert_i32x4");
2715}
2716
2717void LiftoffAssembler::emit_i16x8_sconvert_i8x16_low(LiftoffRegister dst,
2718                                                     LiftoffRegister src) {
2719  bailout(kSimd, "emit_i16x8_sconvert_i8x16_low");
2720}
2721
2722void LiftoffAssembler::emit_i16x8_sconvert_i8x16_high(LiftoffRegister dst,
2723                                                      LiftoffRegister src) {
2724  bailout(kSimd, "emit_i16x8_sconvert_i8x16_high");
2725}
2726
2727void LiftoffAssembler::emit_i16x8_uconvert_i8x16_low(LiftoffRegister dst,
2728                                                     LiftoffRegister src) {
2729  bailout(kSimd, "emit_i16x8_uconvert_i8x16_low");
2730}
2731
2732void LiftoffAssembler::emit_i16x8_uconvert_i8x16_high(LiftoffRegister dst,
2733                                                      LiftoffRegister src) {
2734  bailout(kSimd, "emit_i16x8_uconvert_i8x16_high");
2735}
2736
2737void LiftoffAssembler::emit_i32x4_sconvert_i16x8_low(LiftoffRegister dst,
2738                                                     LiftoffRegister src) {
2739  bailout(kSimd, "emit_i32x4_sconvert_i16x8_low");
2740}
2741
2742void LiftoffAssembler::emit_i32x4_sconvert_i16x8_high(LiftoffRegister dst,
2743                                                      LiftoffRegister src) {
2744  bailout(kSimd, "emit_i32x4_sconvert_i16x8_high");
2745}
2746
2747void LiftoffAssembler::emit_i32x4_uconvert_i16x8_low(LiftoffRegister dst,
2748                                                     LiftoffRegister src) {
2749  bailout(kSimd, "emit_i32x4_uconvert_i16x8_low");
2750}
2751
2752void LiftoffAssembler::emit_i32x4_uconvert_i16x8_high(LiftoffRegister dst,
2753                                                      LiftoffRegister src) {
2754  bailout(kSimd, "emit_i32x4_uconvert_i16x8_high");
2755}
2756
2757void LiftoffAssembler::emit_i64x2_sconvert_i32x4_low(LiftoffRegister dst,
2758                                                     LiftoffRegister src) {
2759  bailout(kSimd, "emit_i64x2_sconvert_i32x4_low");
2760}
2761
2762void LiftoffAssembler::emit_i64x2_sconvert_i32x4_high(LiftoffRegister dst,
2763                                                      LiftoffRegister src) {
2764  bailout(kSimd, "emit_i64x2_sconvert_i32x4_high");
2765}
2766
2767void LiftoffAssembler::emit_i64x2_uconvert_i32x4_low(LiftoffRegister dst,
2768                                                     LiftoffRegister src) {
2769  bailout(kSimd, "emit_i64x2_uconvert_i32x4_low");
2770}
2771
2772void LiftoffAssembler::emit_i64x2_uconvert_i32x4_high(LiftoffRegister dst,
2773                                                      LiftoffRegister src) {
2774  bailout(kSimd, "emit_i64x2_uconvert_i32x4_high");
2775}
2776
2777void LiftoffAssembler::emit_i8x16_rounding_average_u(LiftoffRegister dst,
2778                                                     LiftoffRegister lhs,
2779                                                     LiftoffRegister rhs) {
2780  bailout(kSimd, "emit_i8x16_rounding_average_u");
2781}
2782
2783void LiftoffAssembler::emit_i16x8_rounding_average_u(LiftoffRegister dst,
2784                                                     LiftoffRegister lhs,
2785                                                     LiftoffRegister rhs) {
2786  bailout(kSimd, "emit_i16x8_rounding_average_u");
2787}
2788
2789void LiftoffAssembler::emit_i8x16_abs(LiftoffRegister dst,
2790                                      LiftoffRegister src) {
2791  bailout(kSimd, "emit_i8x16_abs");
2792}
2793
2794void LiftoffAssembler::emit_i16x8_abs(LiftoffRegister dst,
2795                                      LiftoffRegister src) {
2796  bailout(kSimd, "emit_i16x8_abs");
2797}
2798
2799void LiftoffAssembler::emit_i32x4_abs(LiftoffRegister dst,
2800                                      LiftoffRegister src) {
2801  bailout(kSimd, "emit_i32x4_abs");
2802}
2803
2804void LiftoffAssembler::emit_i8x16_extract_lane_s(LiftoffRegister dst,
2805                                                 LiftoffRegister lhs,
2806                                                 uint8_t imm_lane_idx) {
2807  bailout(kSimd, "emit_i8x16_extract_lane_s");
2808}
2809
2810void LiftoffAssembler::emit_i8x16_extract_lane_u(LiftoffRegister dst,
2811                                                 LiftoffRegister lhs,
2812                                                 uint8_t imm_lane_idx) {
2813  bailout(kSimd, "emit_i8x16_extract_lane_u");
2814}
2815
2816void LiftoffAssembler::emit_i16x8_extract_lane_s(LiftoffRegister dst,
2817                                                 LiftoffRegister lhs,
2818                                                 uint8_t imm_lane_idx) {
2819  bailout(kSimd, "emit_i16x8_extract_lane_s");
2820}
2821
2822void LiftoffAssembler::emit_i16x8_extract_lane_u(LiftoffRegister dst,
2823                                                 LiftoffRegister lhs,
2824                                                 uint8_t imm_lane_idx) {
2825  bailout(kSimd, "emit_i16x8_extract_lane_u");
2826}
2827
2828void LiftoffAssembler::emit_i32x4_extract_lane(LiftoffRegister dst,
2829                                               LiftoffRegister lhs,
2830                                               uint8_t imm_lane_idx) {
2831  bailout(kSimd, "emit_i32x4_extract_lane");
2832}
2833
2834void LiftoffAssembler::emit_i64x2_extract_lane(LiftoffRegister dst,
2835                                               LiftoffRegister lhs,
2836                                               uint8_t imm_lane_idx) {
2837  bailout(kSimd, "emit_i64x2_extract_lane");
2838}
2839
2840void LiftoffAssembler::emit_f32x4_extract_lane(LiftoffRegister dst,
2841                                               LiftoffRegister lhs,
2842                                               uint8_t imm_lane_idx) {
2843  bailout(kSimd, "emit_f32x4_extract_lane");
2844}
2845
2846void LiftoffAssembler::emit_f64x2_extract_lane(LiftoffRegister dst,
2847                                               LiftoffRegister lhs,
2848                                               uint8_t imm_lane_idx) {
2849  bailout(kSimd, "emit_f64x2_extract_lane");
2850}
2851
2852void LiftoffAssembler::emit_i8x16_replace_lane(LiftoffRegister dst,
2853                                               LiftoffRegister src1,
2854                                               LiftoffRegister src2,
2855                                               uint8_t imm_lane_idx) {
2856  bailout(kSimd, "emit_i8x16_replace_lane");
2857}
2858
2859void LiftoffAssembler::emit_i16x8_replace_lane(LiftoffRegister dst,
2860                                               LiftoffRegister src1,
2861                                               LiftoffRegister src2,
2862                                               uint8_t imm_lane_idx) {
2863  bailout(kSimd, "emit_i16x8_replace_lane");
2864}
2865
2866void LiftoffAssembler::emit_i32x4_replace_lane(LiftoffRegister dst,
2867                                               LiftoffRegister src1,
2868                                               LiftoffRegister src2,
2869                                               uint8_t imm_lane_idx) {
2870  bailout(kSimd, "emit_i32x4_replace_lane");
2871}
2872
2873void LiftoffAssembler::emit_i64x2_replace_lane(LiftoffRegister dst,
2874                                               LiftoffRegister src1,
2875                                               LiftoffRegister src2,
2876                                               uint8_t imm_lane_idx) {
2877  bailout(kSimd, "emit_i64x2_replace_lane");
2878}
2879
2880void LiftoffAssembler::emit_f32x4_replace_lane(LiftoffRegister dst,
2881                                               LiftoffRegister src1,
2882                                               LiftoffRegister src2,
2883                                               uint8_t imm_lane_idx) {
2884  bailout(kSimd, "emit_f32x4_replace_lane");
2885}
2886
2887void LiftoffAssembler::emit_f64x2_replace_lane(LiftoffRegister dst,
2888                                               LiftoffRegister src1,
2889                                               LiftoffRegister src2,
2890                                               uint8_t imm_lane_idx) {
2891  bailout(kSimd, "emit_f64x2_replace_lane");
2892}
2893
2894void LiftoffAssembler::StackCheck(Label* ool_code, Register limit_address) {
2895  TurboAssembler::Ulw(limit_address, MemOperand(limit_address));
2896  TurboAssembler::Branch(ool_code, ule, sp, Operand(limit_address));
2897}
2898
2899void LiftoffAssembler::CallTrapCallbackForTesting() {
2900  PrepareCallCFunction(0, GetUnusedRegister(kGpReg, {}).gp());
2901  CallCFunction(ExternalReference::wasm_call_trap_callback_for_testing(), 0);
2902}
2903
2904void LiftoffAssembler::AssertUnreachable(AbortReason reason) {
2905  if (FLAG_debug_code) Abort(reason);
2906}
2907
2908void LiftoffAssembler::PushRegisters(LiftoffRegList regs) {
2909  LiftoffRegList gp_regs = regs & kGpCacheRegList;
2910  unsigned num_gp_regs = gp_regs.GetNumRegsSet();
2911  if (num_gp_regs) {
2912    unsigned offset = num_gp_regs * kSystemPointerSize;
2913    addiu(sp, sp, -offset);
2914    while (!gp_regs.is_empty()) {
2915      LiftoffRegister reg = gp_regs.GetFirstRegSet();
2916      offset -= kSystemPointerSize;
2917      sw(reg.gp(), MemOperand(sp, offset));
2918      gp_regs.clear(reg);
2919    }
2920    DCHECK_EQ(offset, 0);
2921  }
2922  LiftoffRegList fp_regs = regs & kFpCacheRegList;
2923  unsigned num_fp_regs = fp_regs.GetNumRegsSet();
2924  if (num_fp_regs) {
2925    addiu(sp, sp, -(num_fp_regs * kStackSlotSize));
2926    unsigned offset = 0;
2927    while (!fp_regs.is_empty()) {
2928      LiftoffRegister reg = fp_regs.GetFirstRegSet();
2929      TurboAssembler::Sdc1(reg.fp(), MemOperand(sp, offset));
2930      fp_regs.clear(reg);
2931      offset += sizeof(double);
2932    }
2933    DCHECK_EQ(offset, num_fp_regs * sizeof(double));
2934  }
2935}
2936
2937void LiftoffAssembler::PopRegisters(LiftoffRegList regs) {
2938  LiftoffRegList fp_regs = regs & kFpCacheRegList;
2939  unsigned fp_offset = 0;
2940  while (!fp_regs.is_empty()) {
2941    LiftoffRegister reg = fp_regs.GetFirstRegSet();
2942    TurboAssembler::Ldc1(reg.fp(), MemOperand(sp, fp_offset));
2943    fp_regs.clear(reg);
2944    fp_offset += sizeof(double);
2945  }
2946  if (fp_offset) addiu(sp, sp, fp_offset);
2947  LiftoffRegList gp_regs = regs & kGpCacheRegList;
2948  unsigned gp_offset = 0;
2949  while (!gp_regs.is_empty()) {
2950    LiftoffRegister reg = gp_regs.GetLastRegSet();
2951    lw(reg.gp(), MemOperand(sp, gp_offset));
2952    gp_regs.clear(reg);
2953    gp_offset += kSystemPointerSize;
2954  }
2955  addiu(sp, sp, gp_offset);
2956}
2957
2958void LiftoffAssembler::RecordSpillsInSafepoint(
2959    SafepointTableBuilder::Safepoint& safepoint, LiftoffRegList all_spills,
2960    LiftoffRegList ref_spills, int spill_offset) {
2961  int spill_space_size = 0;
2962  while (!all_spills.is_empty()) {
2963    LiftoffRegister reg = all_spills.GetFirstRegSet();
2964    if (ref_spills.has(reg)) {
2965      safepoint.DefineTaggedStackSlot(spill_offset);
2966    }
2967    all_spills.clear(reg);
2968    ++spill_offset;
2969    spill_space_size += kSystemPointerSize;
2970  }
2971  // Record the number of additional spill slots.
2972  RecordOolSpillSpaceSize(spill_space_size);
2973}
2974
2975void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
2976  DCHECK_LT(num_stack_slots,
2977            (1 << 16) / kSystemPointerSize);  // 16 bit immediate
2978  TurboAssembler::DropAndRet(static_cast<int>(num_stack_slots));
2979}
2980
2981void LiftoffAssembler::CallC(const ValueKindSig* sig,
2982                             const LiftoffRegister* args,
2983                             const LiftoffRegister* rets,
2984                             ValueKind out_argument_kind, int stack_bytes,
2985                             ExternalReference ext_ref) {
2986  addiu(sp, sp, -stack_bytes);
2987
2988  int arg_bytes = 0;
2989  for (ValueKind param_kind : sig->parameters()) {
2990    liftoff::Store(this, sp, arg_bytes, *args++, param_kind);
2991    arg_bytes += value_kind_size(param_kind);
2992  }
2993  DCHECK_LE(arg_bytes, stack_bytes);
2994
2995  // Pass a pointer to the buffer with the arguments to the C function.
2996  // On mips, the first argument is passed in {a0}.
2997  constexpr Register kFirstArgReg = a0;
2998  mov(kFirstArgReg, sp);
2999
3000  // Now call the C function.
3001  constexpr int kNumCCallArgs = 1;
3002  PrepareCallCFunction(kNumCCallArgs, kScratchReg);
3003  CallCFunction(ext_ref, kNumCCallArgs);
3004
3005  // Move return value to the right register.
3006  const LiftoffRegister* next_result_reg = rets;
3007  if (sig->return_count() > 0) {
3008    DCHECK_EQ(1, sig->return_count());
3009    constexpr Register kReturnReg = v0;
3010    if (kReturnReg != next_result_reg->gp()) {
3011      Move(*next_result_reg, LiftoffRegister(kReturnReg), sig->GetReturn(0));
3012    }
3013    ++next_result_reg;
3014  }
3015
3016  // Load potential output value from the buffer on the stack.
3017  if (out_argument_kind != kVoid) {
3018    liftoff::Load(this, *next_result_reg, sp, 0, out_argument_kind);
3019  }
3020
3021  addiu(sp, sp, stack_bytes);
3022}
3023
3024void LiftoffAssembler::CallNativeWasmCode(Address addr) {
3025  Call(addr, RelocInfo::WASM_CALL);
3026}
3027
3028void LiftoffAssembler::TailCallNativeWasmCode(Address addr) {
3029  Jump(addr, RelocInfo::WASM_CALL);
3030}
3031
3032void LiftoffAssembler::CallIndirect(const ValueKindSig* sig,
3033                                    compiler::CallDescriptor* call_descriptor,
3034                                    Register target) {
3035  if (target == no_reg) {
3036    pop(kScratchReg);
3037    Call(kScratchReg);
3038  } else {
3039    Call(target);
3040  }
3041}
3042
3043void LiftoffAssembler::TailCallIndirect(Register target) {
3044  if (target == no_reg) {
3045    Pop(kScratchReg);
3046    Jump(kScratchReg);
3047  } else {
3048    Jump(target);
3049  }
3050}
3051
3052void LiftoffAssembler::CallRuntimeStub(WasmCode::RuntimeStubId sid) {
3053  // A direct call to a wasm runtime stub defined in this module.
3054  // Just encode the stub index. This will be patched at relocation.
3055  Call(static_cast<Address>(sid), RelocInfo::WASM_STUB_CALL);
3056}
3057
3058void LiftoffAssembler::AllocateStackSlot(Register addr, uint32_t size) {
3059  addiu(sp, sp, -size);
3060  TurboAssembler::Move(addr, sp);
3061}
3062
3063void LiftoffAssembler::DeallocateStackSlot(uint32_t size) {
3064  addiu(sp, sp, size);
3065}
3066
3067void LiftoffAssembler::MaybeOSR() {}
3068
3069void LiftoffAssembler::emit_set_if_nan(Register dst, FPURegister src,
3070                                       ValueKind kind) {
3071  UseScratchRegisterScope temps(this);
3072  Register scratch = temps.Acquire();
3073  Label not_nan;
3074  if (kind == kF32) {
3075    CompareIsNanF32(src, src);
3076  } else {
3077    DCHECK_EQ(kind, kF64);
3078    CompareIsNanF64(src, src);
3079  }
3080  BranchFalseShortF(&not_nan, USE_DELAY_SLOT);
3081  li(scratch, 1);
3082  sw(scratch, MemOperand(dst));
3083  bind(&not_nan);
3084}
3085
3086void LiftoffAssembler::emit_s128_set_if_nan(Register dst, LiftoffRegister src,
3087                                            Register tmp_gp,
3088                                            LiftoffRegister tmp_s128,
3089                                            ValueKind lane_kind) {
3090  UNIMPLEMENTED();
3091}
3092
3093void LiftoffStackSlots::Construct(int param_slots) {
3094  DCHECK_LT(0, slots_.size());
3095  SortInPushOrder();
3096  int last_stack_slot = param_slots;
3097  for (auto& slot : slots_) {
3098    const int stack_slot = slot.dst_slot_;
3099    int stack_decrement = (last_stack_slot - stack_slot) * kSystemPointerSize;
3100    DCHECK_LT(0, stack_decrement);
3101    last_stack_slot = stack_slot;
3102    const LiftoffAssembler::VarState& src = slot.src_;
3103    switch (src.loc()) {
3104      case LiftoffAssembler::VarState::kStack: {
3105        if (src.kind() == kF64) {
3106          asm_->AllocateStackSpace(stack_decrement - kDoubleSize);
3107          DCHECK_EQ(kLowWord, slot.half_);
3108          asm_->lw(kScratchReg,
3109                   liftoff::GetHalfStackSlot(slot.src_offset_, kHighWord));
3110          asm_->push(kScratchReg);
3111        } else {
3112          asm_->AllocateStackSpace(stack_decrement - kSystemPointerSize);
3113        }
3114        asm_->lw(kScratchReg,
3115                 liftoff::GetHalfStackSlot(slot.src_offset_, slot.half_));
3116        asm_->push(kScratchReg);
3117        break;
3118      }
3119      case LiftoffAssembler::VarState::kRegister: {
3120        int pushed_bytes = SlotSizeInBytes(slot);
3121        asm_->AllocateStackSpace(stack_decrement - pushed_bytes);
3122        if (src.kind() == kI64) {
3123          liftoff::push(
3124              asm_, slot.half_ == kLowWord ? src.reg().low() : src.reg().high(),
3125              kI32);
3126        } else {
3127          liftoff::push(asm_, src.reg(), src.kind());
3128        }
3129        break;
3130      }
3131      case LiftoffAssembler::VarState::kIntConst: {
3132        // The high word is the sign extension of the low word.
3133        asm_->AllocateStackSpace(stack_decrement - kSystemPointerSize);
3134        asm_->li(kScratchReg,
3135                 Operand(slot.half_ == kLowWord ? src.i32_const()
3136                                                : src.i32_const() >> 31));
3137        asm_->push(kScratchReg);
3138        break;
3139      }
3140    }
3141  }
3142}
3143
3144}  // namespace wasm
3145}  // namespace internal
3146}  // namespace v8
3147
3148#endif  // V8_WASM_BASELINE_MIPS_LIFTOFF_ASSEMBLER_MIPS_H_
3149