assembler-mips64.cc revision 014dc512cdd3e367bee49a713fdc5ed92584a3e5
1// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// - Neither the name of Sun Microsystems or the names of contributors may
16// be used to endorse or promote products derived from this software without
17// specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// The original source code covered by the above license above has been
32// modified significantly by Google Inc.
33// Copyright 2012 the V8 project authors. All rights reserved.
34
35#include "src/mips64/assembler-mips64.h"
36
37#if V8_TARGET_ARCH_MIPS64
38
39#include "src/base/cpu.h"
40#include "src/mips64/assembler-mips64-inl.h"
41
42namespace v8 {
43namespace internal {
44
45
46// Get the CPU features enabled by the build. For cross compilation the
47// preprocessor symbols CAN_USE_FPU_INSTRUCTIONS
48// can be defined to enable FPU instructions when building the
49// snapshot.
50static unsigned CpuFeaturesImpliedByCompiler() {
51  unsigned answer = 0;
52#ifdef CAN_USE_FPU_INSTRUCTIONS
53  answer |= 1u << FPU;
54#endif  // def CAN_USE_FPU_INSTRUCTIONS
55
56  // If the compiler is allowed to use FPU then we can use FPU too in our code
57  // generation even when generating snapshots.  This won't work for cross
58  // compilation.
59#if defined(__mips__) && defined(__mips_hard_float) && __mips_hard_float != 0
60  answer |= 1u << FPU;
61#endif
62
63  return answer;
64}
65
66
67void CpuFeatures::ProbeImpl(bool cross_compile) {
68  supported_ |= CpuFeaturesImpliedByCompiler();
69
70  // Only use statically determined features for cross compile (snapshot).
71  if (cross_compile) return;
72
73  // If the compiler is allowed to use fpu then we can use fpu too in our
74  // code generation.
75#ifndef __mips__
76  // For the simulator build, use FPU.
77  supported_ |= 1u << FPU;
78#else
79  // Probe for additional features at runtime.
80  base::CPU cpu;
81  if (cpu.has_fpu()) supported_ |= 1u << FPU;
82#endif
83}
84
85
86void CpuFeatures::PrintTarget() { }
87void CpuFeatures::PrintFeatures() { }
88
89
90int ToNumber(Register reg) {
91  DCHECK(reg.is_valid());
92  const int kNumbers[] = {
93    0,    // zero_reg
94    1,    // at
95    2,    // v0
96    3,    // v1
97    4,    // a0
98    5,    // a1
99    6,    // a2
100    7,    // a3
101    8,    // a4
102    9,    // a5
103    10,   // a6
104    11,   // a7
105    12,   // t0
106    13,   // t1
107    14,   // t2
108    15,   // t3
109    16,   // s0
110    17,   // s1
111    18,   // s2
112    19,   // s3
113    20,   // s4
114    21,   // s5
115    22,   // s6
116    23,   // s7
117    24,   // t8
118    25,   // t9
119    26,   // k0
120    27,   // k1
121    28,   // gp
122    29,   // sp
123    30,   // fp
124    31,   // ra
125  };
126  return kNumbers[reg.code()];
127}
128
129
130Register ToRegister(int num) {
131  DCHECK(num >= 0 && num < kNumRegisters);
132  const Register kRegisters[] = {
133    zero_reg,
134    at,
135    v0, v1,
136    a0, a1, a2, a3, a4, a5, a6, a7,
137    t0, t1, t2, t3,
138    s0, s1, s2, s3, s4, s5, s6, s7,
139    t8, t9,
140    k0, k1,
141    gp,
142    sp,
143    fp,
144    ra
145  };
146  return kRegisters[num];
147}
148
149
150// -----------------------------------------------------------------------------
151// Implementation of RelocInfo.
152
153const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
154                                  1 << RelocInfo::INTERNAL_REFERENCE |
155                                  1 << RelocInfo::INTERNAL_REFERENCE_ENCODED;
156
157
158bool RelocInfo::IsCodedSpecially() {
159  // The deserializer needs to know whether a pointer is specially coded.  Being
160  // specially coded on MIPS means that it is a lui/ori instruction, and that is
161  // always the case inside code objects.
162  return true;
163}
164
165
166bool RelocInfo::IsInConstantPool() {
167  return false;
168}
169
170
171// -----------------------------------------------------------------------------
172// Implementation of Operand and MemOperand.
173// See assembler-mips-inl.h for inlined constructors.
174
175Operand::Operand(Handle<Object> handle) {
176  AllowDeferredHandleDereference using_raw_address;
177  rm_ = no_reg;
178  // Verify all Objects referred by code are NOT in new space.
179  Object* obj = *handle;
180  if (obj->IsHeapObject()) {
181    DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
182    imm64_ = reinterpret_cast<intptr_t>(handle.location());
183    rmode_ = RelocInfo::EMBEDDED_OBJECT;
184  } else {
185    // No relocation needed.
186    imm64_ = reinterpret_cast<intptr_t>(obj);
187    rmode_ = RelocInfo::NONE64;
188  }
189}
190
191
192MemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) {
193  offset_ = offset;
194}
195
196
197MemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier,
198                       OffsetAddend offset_addend)
199    : Operand(rm) {
200  offset_ = unit * multiplier + offset_addend;
201}
202
203
204// -----------------------------------------------------------------------------
205// Specific instructions, constants, and masks.
206
207static const int kNegOffset = 0x00008000;
208// daddiu(sp, sp, 8) aka Pop() operation or part of Pop(r)
209// operations as post-increment of sp.
210const Instr kPopInstruction = DADDIU | (Register::kCode_sp << kRsShift) |
211                              (Register::kCode_sp << kRtShift) |
212                              (kPointerSize & kImm16Mask);  // NOLINT
213// daddiu(sp, sp, -8) part of Push(r) operation as pre-decrement of sp.
214const Instr kPushInstruction = DADDIU | (Register::kCode_sp << kRsShift) |
215                               (Register::kCode_sp << kRtShift) |
216                               (-kPointerSize & kImm16Mask);  // NOLINT
217// sd(r, MemOperand(sp, 0))
218const Instr kPushRegPattern =
219    SD | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
220//  ld(r, MemOperand(sp, 0))
221const Instr kPopRegPattern =
222    LD | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
223
224const Instr kLwRegFpOffsetPattern =
225    LW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
226
227const Instr kSwRegFpOffsetPattern =
228    SW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
229
230const Instr kLwRegFpNegOffsetPattern = LW | (Register::kCode_fp << kRsShift) |
231                                       (kNegOffset & kImm16Mask);  // NOLINT
232
233const Instr kSwRegFpNegOffsetPattern = SW | (Register::kCode_fp << kRsShift) |
234                                       (kNegOffset & kImm16Mask);  // NOLINT
235// A mask for the Rt register for push, pop, lw, sw instructions.
236const Instr kRtMask = kRtFieldMask;
237const Instr kLwSwInstrTypeMask = 0xffe00000;
238const Instr kLwSwInstrArgumentMask  = ~kLwSwInstrTypeMask;
239const Instr kLwSwOffsetMask = kImm16Mask;
240
241
242Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
243    : AssemblerBase(isolate, buffer, buffer_size),
244      recorded_ast_id_(TypeFeedbackId::None()),
245      positions_recorder_(this) {
246  reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
247
248  last_trampoline_pool_end_ = 0;
249  no_trampoline_pool_before_ = 0;
250  trampoline_pool_blocked_nesting_ = 0;
251  // We leave space (16 * kTrampolineSlotsSize)
252  // for BlockTrampolinePoolScope buffer.
253  next_buffer_check_ = FLAG_force_long_branches
254      ? kMaxInt : kMaxBranchOffset - kTrampolineSlotsSize * 16;
255  internal_trampoline_exception_ = false;
256  last_bound_pos_ = 0;
257
258  trampoline_emitted_ = FLAG_force_long_branches;
259  unbound_labels_count_ = 0;
260  block_buffer_growth_ = false;
261
262  ClearRecordedAstId();
263}
264
265
266void Assembler::GetCode(CodeDesc* desc) {
267  EmitForbiddenSlotInstruction();
268  DCHECK(pc_ <= reloc_info_writer.pos());  // No overlap.
269  // Set up code descriptor.
270  desc->buffer = buffer_;
271  desc->buffer_size = buffer_size_;
272  desc->instr_size = pc_offset();
273  desc->reloc_size =
274      static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
275  desc->origin = this;
276  desc->constant_pool_size = 0;
277}
278
279
280void Assembler::Align(int m) {
281  DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
282  EmitForbiddenSlotInstruction();
283  while ((pc_offset() & (m - 1)) != 0) {
284    nop();
285  }
286}
287
288
289void Assembler::CodeTargetAlign() {
290  // No advantage to aligning branch/call targets to more than
291  // single instruction, that I am aware of.
292  Align(4);
293}
294
295
296Register Assembler::GetRtReg(Instr instr) {
297  Register rt;
298  rt.reg_code = (instr & kRtFieldMask) >> kRtShift;
299  return rt;
300}
301
302
303Register Assembler::GetRsReg(Instr instr) {
304  Register rs;
305  rs.reg_code = (instr & kRsFieldMask) >> kRsShift;
306  return rs;
307}
308
309
310Register Assembler::GetRdReg(Instr instr) {
311  Register rd;
312  rd.reg_code = (instr & kRdFieldMask) >> kRdShift;
313  return rd;
314}
315
316
317uint32_t Assembler::GetRt(Instr instr) {
318  return (instr & kRtFieldMask) >> kRtShift;
319}
320
321
322uint32_t Assembler::GetRtField(Instr instr) {
323  return instr & kRtFieldMask;
324}
325
326
327uint32_t Assembler::GetRs(Instr instr) {
328  return (instr & kRsFieldMask) >> kRsShift;
329}
330
331
332uint32_t Assembler::GetRsField(Instr instr) {
333  return instr & kRsFieldMask;
334}
335
336
337uint32_t Assembler::GetRd(Instr instr) {
338  return  (instr & kRdFieldMask) >> kRdShift;
339}
340
341
342uint32_t Assembler::GetRdField(Instr instr) {
343  return  instr & kRdFieldMask;
344}
345
346
347uint32_t Assembler::GetSa(Instr instr) {
348  return (instr & kSaFieldMask) >> kSaShift;
349}
350
351
352uint32_t Assembler::GetSaField(Instr instr) {
353  return instr & kSaFieldMask;
354}
355
356
357uint32_t Assembler::GetOpcodeField(Instr instr) {
358  return instr & kOpcodeMask;
359}
360
361
362uint32_t Assembler::GetFunction(Instr instr) {
363  return (instr & kFunctionFieldMask) >> kFunctionShift;
364}
365
366
367uint32_t Assembler::GetFunctionField(Instr instr) {
368  return instr & kFunctionFieldMask;
369}
370
371
372uint32_t Assembler::GetImmediate16(Instr instr) {
373  return instr & kImm16Mask;
374}
375
376
377uint32_t Assembler::GetLabelConst(Instr instr) {
378  return instr & ~kImm16Mask;
379}
380
381
382bool Assembler::IsPop(Instr instr) {
383  return (instr & ~kRtMask) == kPopRegPattern;
384}
385
386
387bool Assembler::IsPush(Instr instr) {
388  return (instr & ~kRtMask) == kPushRegPattern;
389}
390
391
392bool Assembler::IsSwRegFpOffset(Instr instr) {
393  return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern);
394}
395
396
397bool Assembler::IsLwRegFpOffset(Instr instr) {
398  return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern);
399}
400
401
402bool Assembler::IsSwRegFpNegOffset(Instr instr) {
403  return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
404          kSwRegFpNegOffsetPattern);
405}
406
407
408bool Assembler::IsLwRegFpNegOffset(Instr instr) {
409  return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
410          kLwRegFpNegOffsetPattern);
411}
412
413
414// Labels refer to positions in the (to be) generated code.
415// There are bound, linked, and unused labels.
416//
417// Bound labels refer to known positions in the already
418// generated code. pos() is the position the label refers to.
419//
420// Linked labels refer to unknown positions in the code
421// to be generated; pos() is the position of the last
422// instruction using the label.
423
424// The link chain is terminated by a value in the instruction of -1,
425// which is an otherwise illegal value (branch -1 is inf loop).
426// The instruction 16-bit offset field addresses 32-bit words, but in
427// code is conv to an 18-bit value addressing bytes, hence the -4 value.
428
429const int kEndOfChain = -4;
430// Determines the end of the Jump chain (a subset of the label link chain).
431const int kEndOfJumpChain = 0;
432
433
434bool Assembler::IsBranch(Instr instr) {
435  uint32_t opcode   = GetOpcodeField(instr);
436  uint32_t rt_field = GetRtField(instr);
437  uint32_t rs_field = GetRsField(instr);
438  // Checks if the instruction is a branch.
439  bool isBranch =
440      opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ ||
441      opcode == BEQL || opcode == BNEL || opcode == BLEZL || opcode == BGTZL ||
442      (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
443                            rt_field == BLTZAL || rt_field == BGEZAL)) ||
444      (opcode == COP1 && rs_field == BC1) ||  // Coprocessor branch.
445      (opcode == COP1 && rs_field == BC1EQZ) ||
446      (opcode == COP1 && rs_field == BC1NEZ);
447  if (!isBranch && kArchVariant == kMips64r6) {
448    // All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and
449    // POP30 (BNVC, BNEC, BNEZALC) are branch ops.
450    isBranch |= opcode == POP10 || opcode == POP30 || opcode == BC ||
451                opcode == BALC ||
452                (opcode == POP66 && rs_field != 0) ||  // BEQZC
453                (opcode == POP76 && rs_field != 0);    // BNEZC
454  }
455  return isBranch;
456}
457
458
459bool Assembler::IsBc(Instr instr) {
460  uint32_t opcode = GetOpcodeField(instr);
461  // Checks if the instruction is a BC or BALC.
462  return opcode == BC || opcode == BALC;
463}
464
465
466bool Assembler::IsBzc(Instr instr) {
467  uint32_t opcode = GetOpcodeField(instr);
468  // Checks if the instruction is BEQZC or BNEZC.
469  return (opcode == POP66 && GetRsField(instr) != 0) ||
470         (opcode == POP76 && GetRsField(instr) != 0);
471}
472
473
474bool Assembler::IsEmittedConstant(Instr instr) {
475  uint32_t label_constant = GetLabelConst(instr);
476  return label_constant == 0;  // Emitted label const in reg-exp engine.
477}
478
479
480bool Assembler::IsBeq(Instr instr) {
481  return GetOpcodeField(instr) == BEQ;
482}
483
484
485bool Assembler::IsBne(Instr instr) {
486  return GetOpcodeField(instr) == BNE;
487}
488
489
490bool Assembler::IsBeqzc(Instr instr) {
491  uint32_t opcode = GetOpcodeField(instr);
492  return opcode == POP66 && GetRsField(instr) != 0;
493}
494
495
496bool Assembler::IsBnezc(Instr instr) {
497  uint32_t opcode = GetOpcodeField(instr);
498  return opcode == POP76 && GetRsField(instr) != 0;
499}
500
501
502bool Assembler::IsBeqc(Instr instr) {
503  uint32_t opcode = GetOpcodeField(instr);
504  uint32_t rs = GetRsField(instr);
505  uint32_t rt = GetRtField(instr);
506  return opcode == POP10 && rs != 0 && rs < rt;  // && rt != 0
507}
508
509
510bool Assembler::IsBnec(Instr instr) {
511  uint32_t opcode = GetOpcodeField(instr);
512  uint32_t rs = GetRsField(instr);
513  uint32_t rt = GetRtField(instr);
514  return opcode == POP30 && rs != 0 && rs < rt;  // && rt != 0
515}
516
517
518bool Assembler::IsJump(Instr instr) {
519  uint32_t opcode   = GetOpcodeField(instr);
520  uint32_t rt_field = GetRtField(instr);
521  uint32_t rd_field = GetRdField(instr);
522  uint32_t function_field = GetFunctionField(instr);
523  // Checks if the instruction is a jump.
524  return opcode == J || opcode == JAL ||
525      (opcode == SPECIAL && rt_field == 0 &&
526      ((function_field == JALR) || (rd_field == 0 && (function_field == JR))));
527}
528
529
530bool Assembler::IsJ(Instr instr) {
531  uint32_t opcode = GetOpcodeField(instr);
532  // Checks if the instruction is a jump.
533  return opcode == J;
534}
535
536
537bool Assembler::IsJal(Instr instr) {
538  return GetOpcodeField(instr) == JAL;
539}
540
541
542bool Assembler::IsJr(Instr instr) {
543  return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR;
544}
545
546
547bool Assembler::IsJalr(Instr instr) {
548  return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JALR;
549}
550
551
552bool Assembler::IsLui(Instr instr) {
553  uint32_t opcode = GetOpcodeField(instr);
554  // Checks if the instruction is a load upper immediate.
555  return opcode == LUI;
556}
557
558
559bool Assembler::IsOri(Instr instr) {
560  uint32_t opcode = GetOpcodeField(instr);
561  // Checks if the instruction is a load upper immediate.
562  return opcode == ORI;
563}
564
565
566bool Assembler::IsNop(Instr instr, unsigned int type) {
567  // See Assembler::nop(type).
568  DCHECK(type < 32);
569  uint32_t opcode = GetOpcodeField(instr);
570  uint32_t function = GetFunctionField(instr);
571  uint32_t rt = GetRt(instr);
572  uint32_t rd = GetRd(instr);
573  uint32_t sa = GetSa(instr);
574
575  // Traditional mips nop == sll(zero_reg, zero_reg, 0)
576  // When marking non-zero type, use sll(zero_reg, at, type)
577  // to avoid use of mips ssnop and ehb special encodings
578  // of the sll instruction.
579
580  Register nop_rt_reg = (type == 0) ? zero_reg : at;
581  bool ret = (opcode == SPECIAL && function == SLL &&
582              rd == static_cast<uint32_t>(ToNumber(zero_reg)) &&
583              rt == static_cast<uint32_t>(ToNumber(nop_rt_reg)) &&
584              sa == type);
585
586  return ret;
587}
588
589
590int32_t Assembler::GetBranchOffset(Instr instr) {
591  DCHECK(IsBranch(instr));
592  return (static_cast<int16_t>(instr & kImm16Mask)) << 2;
593}
594
595
596bool Assembler::IsLw(Instr instr) {
597  return (static_cast<uint32_t>(instr & kOpcodeMask) == LW);
598}
599
600
601int16_t Assembler::GetLwOffset(Instr instr) {
602  DCHECK(IsLw(instr));
603  return ((instr & kImm16Mask));
604}
605
606
607Instr Assembler::SetLwOffset(Instr instr, int16_t offset) {
608  DCHECK(IsLw(instr));
609
610  // We actually create a new lw instruction based on the original one.
611  Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask)
612      | (offset & kImm16Mask);
613
614  return temp_instr;
615}
616
617
618bool Assembler::IsSw(Instr instr) {
619  return (static_cast<uint32_t>(instr & kOpcodeMask) == SW);
620}
621
622
623Instr Assembler::SetSwOffset(Instr instr, int16_t offset) {
624  DCHECK(IsSw(instr));
625  return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
626}
627
628
629bool Assembler::IsAddImmediate(Instr instr) {
630  return ((instr & kOpcodeMask) == ADDIU || (instr & kOpcodeMask) == DADDIU);
631}
632
633
634Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
635  DCHECK(IsAddImmediate(instr));
636  return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
637}
638
639
640bool Assembler::IsAndImmediate(Instr instr) {
641  return GetOpcodeField(instr) == ANDI;
642}
643
644
645static Assembler::OffsetSize OffsetSizeInBits(Instr instr) {
646  if (kArchVariant == kMips64r6) {
647    if (Assembler::IsBc(instr)) {
648      return Assembler::OffsetSize::kOffset26;
649    } else if (Assembler::IsBzc(instr)) {
650      return Assembler::OffsetSize::kOffset21;
651    }
652  }
653  return Assembler::OffsetSize::kOffset16;
654}
655
656
657static inline int32_t AddBranchOffset(int pos, Instr instr) {
658  int bits = OffsetSizeInBits(instr);
659  const int32_t mask = (1 << bits) - 1;
660  bits = 32 - bits;
661
662  // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
663  // the compiler uses arithmetic shifts for signed integers.
664  int32_t imm = ((instr & mask) << bits) >> (bits - 2);
665
666  if (imm == kEndOfChain) {
667    // EndOfChain sentinel is returned directly, not relative to pc or pos.
668    return kEndOfChain;
669  } else {
670    return pos + Assembler::kBranchPCOffset + imm;
671  }
672}
673
674
675int Assembler::target_at(int pos, bool is_internal) {
676  if (is_internal) {
677    int64_t* p = reinterpret_cast<int64_t*>(buffer_ + pos);
678    int64_t address = *p;
679    if (address == kEndOfJumpChain) {
680      return kEndOfChain;
681    } else {
682      int64_t instr_address = reinterpret_cast<int64_t>(p);
683      DCHECK(instr_address - address < INT_MAX);
684      int delta = static_cast<int>(instr_address - address);
685      DCHECK(pos > delta);
686      return pos - delta;
687    }
688  }
689  Instr instr = instr_at(pos);
690  if ((instr & ~kImm16Mask) == 0) {
691    // Emitted label constant, not part of a branch.
692    if (instr == 0) {
693       return kEndOfChain;
694     } else {
695       int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
696       return (imm18 + pos);
697     }
698  }
699  // Check we have a branch or jump instruction.
700  DCHECK(IsBranch(instr) || IsJ(instr) || IsJal(instr) || IsLui(instr));
701  // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
702  // the compiler uses arithmetic shifts for signed integers.
703  if (IsBranch(instr)) {
704    return AddBranchOffset(pos, instr);
705  } else if (IsLui(instr)) {
706    Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
707    Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
708    Instr instr_ori2 = instr_at(pos + 3 * Assembler::kInstrSize);
709    DCHECK(IsOri(instr_ori));
710    DCHECK(IsOri(instr_ori2));
711
712    // TODO(plind) create named constants for shift values.
713    int64_t imm = static_cast<int64_t>(instr_lui & kImm16Mask) << 48;
714    imm |= static_cast<int64_t>(instr_ori & kImm16Mask) << 32;
715    imm |= static_cast<int64_t>(instr_ori2 & kImm16Mask) << 16;
716    // Sign extend address;
717    imm >>= 16;
718
719    if (imm == kEndOfJumpChain) {
720      // EndOfChain sentinel is returned directly, not relative to pc or pos.
721      return kEndOfChain;
722    } else {
723      uint64_t instr_address = reinterpret_cast<int64_t>(buffer_ + pos);
724      DCHECK(instr_address - imm < INT_MAX);
725      int delta = static_cast<int>(instr_address - imm);
726      DCHECK(pos > delta);
727      return pos - delta;
728    }
729  } else {
730    DCHECK(IsJ(instr) || IsJal(instr));
731    int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
732    if (imm28 == kEndOfJumpChain) {
733      // EndOfChain sentinel is returned directly, not relative to pc or pos.
734      return kEndOfChain;
735    } else {
736      // Sign extend 28-bit offset.
737      int32_t delta = static_cast<int32_t>((imm28 << 4) >> 4);
738      return pos + delta;
739    }
740  }
741}
742
743
744static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos,
745                                    Instr instr) {
746  int32_t bits = OffsetSizeInBits(instr);
747  int32_t imm = target_pos - (pos + Assembler::kBranchPCOffset);
748  DCHECK((imm & 3) == 0);
749  imm >>= 2;
750
751  const int32_t mask = (1 << bits) - 1;
752  instr &= ~mask;
753  DCHECK(is_intn(imm, bits));
754
755  return instr | (imm & mask);
756}
757
758
759void Assembler::target_at_put(int pos, int target_pos, bool is_internal) {
760  if (is_internal) {
761    uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos;
762    *reinterpret_cast<uint64_t*>(buffer_ + pos) = imm;
763    return;
764  }
765  Instr instr = instr_at(pos);
766  if ((instr & ~kImm16Mask) == 0) {
767    DCHECK(target_pos == kEndOfChain || target_pos >= 0);
768    // Emitted label constant, not part of a branch.
769    // Make label relative to Code* of generated Code object.
770    instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
771    return;
772  }
773
774  if (IsBranch(instr)) {
775    instr = SetBranchOffset(pos, target_pos, instr);
776    instr_at_put(pos, instr);
777  } else if (IsLui(instr)) {
778    Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
779    Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
780    Instr instr_ori2 = instr_at(pos + 3 * Assembler::kInstrSize);
781    DCHECK(IsOri(instr_ori));
782    DCHECK(IsOri(instr_ori2));
783
784    uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos;
785    DCHECK((imm & 3) == 0);
786
787    instr_lui &= ~kImm16Mask;
788    instr_ori &= ~kImm16Mask;
789    instr_ori2 &= ~kImm16Mask;
790
791    instr_at_put(pos + 0 * Assembler::kInstrSize,
792                 instr_lui | ((imm >> 32) & kImm16Mask));
793    instr_at_put(pos + 1 * Assembler::kInstrSize,
794                 instr_ori | ((imm >> 16) & kImm16Mask));
795    instr_at_put(pos + 3 * Assembler::kInstrSize,
796                 instr_ori2 | (imm & kImm16Mask));
797  } else if (IsJ(instr) || IsJal(instr)) {
798    int32_t imm28 = target_pos - pos;
799    DCHECK((imm28 & 3) == 0);
800
801    uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2);
802    DCHECK(is_uint26(imm26));
803    // Place 26-bit signed offset with markings.
804    // When code is committed it will be resolved to j/jal.
805    int32_t mark = IsJ(instr) ? kJRawMark : kJalRawMark;
806    instr_at_put(pos, mark | (imm26 & kImm26Mask));
807  } else {
808    int32_t imm28 = target_pos - pos;
809    DCHECK((imm28 & 3) == 0);
810
811    uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2);
812    DCHECK(is_uint26(imm26));
813    // Place raw 26-bit signed offset.
814    // When code is committed it will be resolved to j/jal.
815    instr &= ~kImm26Mask;
816    instr_at_put(pos, instr | (imm26 & kImm26Mask));
817  }
818}
819
820
821void Assembler::print(Label* L) {
822  if (L->is_unused()) {
823    PrintF("unused label\n");
824  } else if (L->is_bound()) {
825    PrintF("bound label to %d\n", L->pos());
826  } else if (L->is_linked()) {
827    Label l = *L;
828    PrintF("unbound label");
829    while (l.is_linked()) {
830      PrintF("@ %d ", l.pos());
831      Instr instr = instr_at(l.pos());
832      if ((instr & ~kImm16Mask) == 0) {
833        PrintF("value\n");
834      } else {
835        PrintF("%d\n", instr);
836      }
837      next(&l, internal_reference_positions_.find(l.pos()) !=
838                   internal_reference_positions_.end());
839    }
840  } else {
841    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
842  }
843}
844
845
846void Assembler::bind_to(Label* L, int pos) {
847  DCHECK(0 <= pos && pos <= pc_offset());  // Must have valid binding position.
848  int trampoline_pos = kInvalidSlotPos;
849  bool is_internal = false;
850  if (L->is_linked() && !trampoline_emitted_) {
851    unbound_labels_count_--;
852    next_buffer_check_ += kTrampolineSlotsSize;
853  }
854
855  while (L->is_linked()) {
856    int fixup_pos = L->pos();
857    int dist = pos - fixup_pos;
858    is_internal = internal_reference_positions_.find(fixup_pos) !=
859                  internal_reference_positions_.end();
860    next(L, is_internal);  // Call next before overwriting link with target at
861                           // fixup_pos.
862    Instr instr = instr_at(fixup_pos);
863    if (is_internal) {
864      target_at_put(fixup_pos, pos, is_internal);
865    } else {
866      if (IsBranch(instr)) {
867        int branch_offset = BranchOffset(instr);
868        if (dist > branch_offset) {
869          if (trampoline_pos == kInvalidSlotPos) {
870            trampoline_pos = get_trampoline_entry(fixup_pos);
871            CHECK(trampoline_pos != kInvalidSlotPos);
872          }
873          CHECK((trampoline_pos - fixup_pos) <= branch_offset);
874          target_at_put(fixup_pos, trampoline_pos, false);
875          fixup_pos = trampoline_pos;
876          dist = pos - fixup_pos;
877        }
878        target_at_put(fixup_pos, pos, false);
879      } else {
880        DCHECK(IsJ(instr) || IsJal(instr) || IsLui(instr) ||
881               IsEmittedConstant(instr));
882        target_at_put(fixup_pos, pos, false);
883      }
884    }
885  }
886  L->bind_to(pos);
887
888  // Keep track of the last bound label so we don't eliminate any instructions
889  // before a bound label.
890  if (pos > last_bound_pos_)
891    last_bound_pos_ = pos;
892}
893
894
895void Assembler::bind(Label* L) {
896  DCHECK(!L->is_bound());  // Label can only be bound once.
897  bind_to(L, pc_offset());
898}
899
900
901void Assembler::next(Label* L, bool is_internal) {
902  DCHECK(L->is_linked());
903  int link = target_at(L->pos(), is_internal);
904  if (link == kEndOfChain) {
905    L->Unuse();
906  } else {
907    DCHECK(link >= 0);
908    L->link_to(link);
909  }
910}
911
912
913bool Assembler::is_near(Label* L) {
914  DCHECK(L->is_bound());
915  return pc_offset() - L->pos() < kMaxBranchOffset - 4 * kInstrSize;
916}
917
918
919bool Assembler::is_near(Label* L, OffsetSize bits) {
920  if (L == nullptr || !L->is_bound()) return true;
921  return ((pc_offset() - L->pos()) <
922          (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize);
923}
924
925
926bool Assembler::is_near_branch(Label* L) {
927  DCHECK(L->is_bound());
928  return kArchVariant == kMips64r6 ? is_near_r6(L) : is_near_pre_r6(L);
929}
930
931
932int Assembler::BranchOffset(Instr instr) {
933  // At pre-R6 and for other R6 branches the offset is 16 bits.
934  int bits = OffsetSize::kOffset16;
935
936  if (kArchVariant == kMips64r6) {
937    uint32_t opcode = GetOpcodeField(instr);
938    switch (opcode) {
939      // Checks BC or BALC.
940      case BC:
941      case BALC:
942        bits = OffsetSize::kOffset26;
943        break;
944
945      // Checks BEQZC or BNEZC.
946      case POP66:
947      case POP76:
948        if (GetRsField(instr) != 0) bits = OffsetSize::kOffset21;
949        break;
950      default:
951        break;
952    }
953  }
954
955  return (1 << (bits + 2 - 1)) - 1;
956}
957
958
959// We have to use a temporary register for things that can be relocated even
960// if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
961// space.  There is no guarantee that the relocated location can be similarly
962// encoded.
963bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
964  return !RelocInfo::IsNone(rmode);
965}
966
967void Assembler::GenInstrRegister(Opcode opcode,
968                                 Register rs,
969                                 Register rt,
970                                 Register rd,
971                                 uint16_t sa,
972                                 SecondaryField func) {
973  DCHECK(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
974  Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
975      | (rd.code() << kRdShift) | (sa << kSaShift) | func;
976  emit(instr);
977}
978
979
980void Assembler::GenInstrRegister(Opcode opcode,
981                                 Register rs,
982                                 Register rt,
983                                 uint16_t msb,
984                                 uint16_t lsb,
985                                 SecondaryField func) {
986  DCHECK(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb));
987  Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
988      | (msb << kRdShift) | (lsb << kSaShift) | func;
989  emit(instr);
990}
991
992
993void Assembler::GenInstrRegister(Opcode opcode,
994                                 SecondaryField fmt,
995                                 FPURegister ft,
996                                 FPURegister fs,
997                                 FPURegister fd,
998                                 SecondaryField func) {
999  DCHECK(fd.is_valid() && fs.is_valid() && ft.is_valid());
1000  Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
1001      | (fd.code() << kFdShift) | func;
1002  emit(instr);
1003}
1004
1005
1006void Assembler::GenInstrRegister(Opcode opcode,
1007                                 FPURegister fr,
1008                                 FPURegister ft,
1009                                 FPURegister fs,
1010                                 FPURegister fd,
1011                                 SecondaryField func) {
1012  DCHECK(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid());
1013  Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift)
1014      | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
1015  emit(instr);
1016}
1017
1018
1019void Assembler::GenInstrRegister(Opcode opcode,
1020                                 SecondaryField fmt,
1021                                 Register rt,
1022                                 FPURegister fs,
1023                                 FPURegister fd,
1024                                 SecondaryField func) {
1025  DCHECK(fd.is_valid() && fs.is_valid() && rt.is_valid());
1026  Instr instr = opcode | fmt | (rt.code() << kRtShift)
1027      | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
1028  emit(instr);
1029}
1030
1031
1032void Assembler::GenInstrRegister(Opcode opcode,
1033                                 SecondaryField fmt,
1034                                 Register rt,
1035                                 FPUControlRegister fs,
1036                                 SecondaryField func) {
1037  DCHECK(fs.is_valid() && rt.is_valid());
1038  Instr instr =
1039      opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
1040  emit(instr);
1041}
1042
1043
1044// Instructions with immediate value.
1045// Registers are in the order of the instruction encoding, from left to right.
1046void Assembler::GenInstrImmediate(Opcode opcode, Register rs, Register rt,
1047                                  int32_t j,
1048                                  CompactBranchType is_compact_branch) {
1049  DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
1050  Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
1051      | (j & kImm16Mask);
1052  emit(instr, is_compact_branch);
1053}
1054
1055
1056void Assembler::GenInstrImmediate(Opcode opcode, Register rs, SecondaryField SF,
1057                                  int32_t j,
1058                                  CompactBranchType is_compact_branch) {
1059  DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j)));
1060  Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
1061  emit(instr, is_compact_branch);
1062}
1063
1064
1065void Assembler::GenInstrImmediate(Opcode opcode, Register rs, FPURegister ft,
1066                                  int32_t j,
1067                                  CompactBranchType is_compact_branch) {
1068  DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
1069  Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
1070      | (j & kImm16Mask);
1071  emit(instr, is_compact_branch);
1072}
1073
1074
1075void Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t offset21,
1076                                  CompactBranchType is_compact_branch) {
1077  DCHECK(rs.is_valid() && (is_int21(offset21)));
1078  Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask);
1079  emit(instr, is_compact_branch);
1080}
1081
1082
1083void Assembler::GenInstrImmediate(Opcode opcode, Register rs,
1084                                  uint32_t offset21) {
1085  DCHECK(rs.is_valid() && (is_uint21(offset21)));
1086  Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask);
1087  emit(instr);
1088}
1089
1090
1091void Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26,
1092                                  CompactBranchType is_compact_branch) {
1093  DCHECK(is_int26(offset26));
1094  Instr instr = opcode | (offset26 & kImm26Mask);
1095  emit(instr, is_compact_branch);
1096}
1097
1098
1099void Assembler::GenInstrJump(Opcode opcode,
1100                             uint32_t address) {
1101  BlockTrampolinePoolScope block_trampoline_pool(this);
1102  DCHECK(is_uint26(address));
1103  Instr instr = opcode | address;
1104  emit(instr);
1105  BlockTrampolinePoolFor(1);  // For associated delay slot.
1106}
1107
1108
1109// Returns the next free trampoline entry.
1110int32_t Assembler::get_trampoline_entry(int32_t pos) {
1111  int32_t trampoline_entry = kInvalidSlotPos;
1112  if (!internal_trampoline_exception_) {
1113    if (trampoline_.start() > pos) {
1114     trampoline_entry = trampoline_.take_slot();
1115    }
1116
1117    if (kInvalidSlotPos == trampoline_entry) {
1118      internal_trampoline_exception_ = true;
1119    }
1120  }
1121  return trampoline_entry;
1122}
1123
1124
1125uint64_t Assembler::jump_address(Label* L) {
1126  int64_t target_pos;
1127  if (L->is_bound()) {
1128    target_pos = L->pos();
1129  } else {
1130    if (L->is_linked()) {
1131      target_pos = L->pos();  // L's link.
1132      L->link_to(pc_offset());
1133    } else {
1134      L->link_to(pc_offset());
1135      return kEndOfJumpChain;
1136    }
1137  }
1138  uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos;
1139  DCHECK((imm & 3) == 0);
1140
1141  return imm;
1142}
1143
1144
1145uint64_t Assembler::jump_offset(Label* L) {
1146  int64_t target_pos;
1147  int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0;
1148
1149  if (L->is_bound()) {
1150    target_pos = L->pos();
1151  } else {
1152    if (L->is_linked()) {
1153      target_pos = L->pos();  // L's link.
1154      L->link_to(pc_offset() + pad);
1155    } else {
1156      L->link_to(pc_offset() + pad);
1157      return kEndOfJumpChain;
1158    }
1159  }
1160  int64_t imm = target_pos - (pc_offset() + pad);
1161  DCHECK((imm & 3) == 0);
1162
1163  return static_cast<uint64_t>(imm);
1164}
1165
1166
1167int32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) {
1168  int32_t target_pos;
1169  int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0;
1170
1171  if (L->is_bound()) {
1172    target_pos = L->pos();
1173  } else {
1174    if (L->is_linked()) {
1175      target_pos = L->pos();
1176      L->link_to(pc_offset() + pad);
1177    } else {
1178      L->link_to(pc_offset() + pad);
1179      if (!trampoline_emitted_) {
1180        unbound_labels_count_++;
1181        next_buffer_check_ -= kTrampolineSlotsSize;
1182      }
1183      return kEndOfChain;
1184    }
1185  }
1186
1187  int32_t offset = target_pos - (pc_offset() + kBranchPCOffset + pad);
1188  DCHECK(is_intn(offset, bits + 2));
1189  DCHECK((offset & 3) == 0);
1190
1191  return offset;
1192}
1193
1194
1195void Assembler::label_at_put(Label* L, int at_offset) {
1196  int target_pos;
1197  if (L->is_bound()) {
1198    target_pos = L->pos();
1199    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
1200  } else {
1201    if (L->is_linked()) {
1202      target_pos = L->pos();  // L's link.
1203      int32_t imm18 = target_pos - at_offset;
1204      DCHECK((imm18 & 3) == 0);
1205      int32_t imm16 = imm18 >> 2;
1206      DCHECK(is_int16(imm16));
1207      instr_at_put(at_offset, (imm16 & kImm16Mask));
1208    } else {
1209      target_pos = kEndOfChain;
1210      instr_at_put(at_offset, 0);
1211      if (!trampoline_emitted_) {
1212        unbound_labels_count_++;
1213        next_buffer_check_ -= kTrampolineSlotsSize;
1214      }
1215    }
1216    L->link_to(at_offset);
1217  }
1218}
1219
1220
1221//------- Branch and jump instructions --------
1222
1223void Assembler::b(int16_t offset) {
1224  beq(zero_reg, zero_reg, offset);
1225}
1226
1227
1228void Assembler::bal(int16_t offset) {
1229  positions_recorder()->WriteRecordedPositions();
1230  bgezal(zero_reg, offset);
1231}
1232
1233
1234void Assembler::bc(int32_t offset) {
1235  DCHECK(kArchVariant == kMips64r6);
1236  GenInstrImmediate(BC, offset, CompactBranchType::COMPACT_BRANCH);
1237}
1238
1239
1240void Assembler::balc(int32_t offset) {
1241  DCHECK(kArchVariant == kMips64r6);
1242  positions_recorder()->WriteRecordedPositions();
1243  GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH);
1244}
1245
1246
1247void Assembler::beq(Register rs, Register rt, int16_t offset) {
1248  BlockTrampolinePoolScope block_trampoline_pool(this);
1249  GenInstrImmediate(BEQ, rs, rt, offset);
1250  BlockTrampolinePoolFor(1);  // For associated delay slot.
1251}
1252
1253
1254void Assembler::bgez(Register rs, int16_t offset) {
1255  BlockTrampolinePoolScope block_trampoline_pool(this);
1256  GenInstrImmediate(REGIMM, rs, BGEZ, offset);
1257  BlockTrampolinePoolFor(1);  // For associated delay slot.
1258}
1259
1260
1261void Assembler::bgezc(Register rt, int16_t offset) {
1262  DCHECK(kArchVariant == kMips64r6);
1263  DCHECK(!(rt.is(zero_reg)));
1264  GenInstrImmediate(BLEZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1265}
1266
1267
1268void Assembler::bgeuc(Register rs, Register rt, int16_t offset) {
1269  DCHECK(kArchVariant == kMips64r6);
1270  DCHECK(!(rs.is(zero_reg)));
1271  DCHECK(!(rt.is(zero_reg)));
1272  DCHECK(rs.code() != rt.code());
1273  GenInstrImmediate(BLEZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1274}
1275
1276
1277void Assembler::bgec(Register rs, Register rt, int16_t offset) {
1278  DCHECK(kArchVariant == kMips64r6);
1279  DCHECK(!(rs.is(zero_reg)));
1280  DCHECK(!(rt.is(zero_reg)));
1281  DCHECK(rs.code() != rt.code());
1282  GenInstrImmediate(BLEZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1283}
1284
1285
1286void Assembler::bgezal(Register rs, int16_t offset) {
1287  DCHECK(kArchVariant != kMips64r6 || rs.is(zero_reg));
1288  BlockTrampolinePoolScope block_trampoline_pool(this);
1289  positions_recorder()->WriteRecordedPositions();
1290  GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
1291  BlockTrampolinePoolFor(1);  // For associated delay slot.
1292}
1293
1294
1295void Assembler::bgtz(Register rs, int16_t offset) {
1296  BlockTrampolinePoolScope block_trampoline_pool(this);
1297  GenInstrImmediate(BGTZ, rs, zero_reg, offset);
1298  BlockTrampolinePoolFor(1);  // For associated delay slot.
1299}
1300
1301
1302void Assembler::bgtzc(Register rt, int16_t offset) {
1303  DCHECK(kArchVariant == kMips64r6);
1304  DCHECK(!(rt.is(zero_reg)));
1305  GenInstrImmediate(BGTZL, zero_reg, rt, offset,
1306                    CompactBranchType::COMPACT_BRANCH);
1307}
1308
1309
1310void Assembler::blez(Register rs, int16_t offset) {
1311  BlockTrampolinePoolScope block_trampoline_pool(this);
1312  GenInstrImmediate(BLEZ, rs, zero_reg, offset);
1313  BlockTrampolinePoolFor(1);  // For associated delay slot.
1314}
1315
1316
1317void Assembler::blezc(Register rt, int16_t offset) {
1318  DCHECK(kArchVariant == kMips64r6);
1319  DCHECK(!(rt.is(zero_reg)));
1320  GenInstrImmediate(BLEZL, zero_reg, rt, offset,
1321                    CompactBranchType::COMPACT_BRANCH);
1322}
1323
1324
1325void Assembler::bltzc(Register rt, int16_t offset) {
1326  DCHECK(kArchVariant == kMips64r6);
1327  DCHECK(!rt.is(zero_reg));
1328  GenInstrImmediate(BGTZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1329}
1330
1331
1332void Assembler::bltuc(Register rs, Register rt, int16_t offset) {
1333  DCHECK(kArchVariant == kMips64r6);
1334  DCHECK(!(rs.is(zero_reg)));
1335  DCHECK(!(rt.is(zero_reg)));
1336  DCHECK(rs.code() != rt.code());
1337  GenInstrImmediate(BGTZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1338}
1339
1340
1341void Assembler::bltc(Register rs, Register rt, int16_t offset) {
1342  DCHECK(kArchVariant == kMips64r6);
1343  DCHECK(!rs.is(zero_reg));
1344  DCHECK(!rt.is(zero_reg));
1345  DCHECK(rs.code() != rt.code());
1346  GenInstrImmediate(BGTZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1347}
1348
1349
1350void Assembler::bltz(Register rs, int16_t offset) {
1351  BlockTrampolinePoolScope block_trampoline_pool(this);
1352  GenInstrImmediate(REGIMM, rs, BLTZ, offset);
1353  BlockTrampolinePoolFor(1);  // For associated delay slot.
1354}
1355
1356
1357void Assembler::bltzal(Register rs, int16_t offset) {
1358  DCHECK(kArchVariant != kMips64r6 || rs.is(zero_reg));
1359  BlockTrampolinePoolScope block_trampoline_pool(this);
1360  positions_recorder()->WriteRecordedPositions();
1361  GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
1362  BlockTrampolinePoolFor(1);  // For associated delay slot.
1363}
1364
1365
1366void Assembler::bne(Register rs, Register rt, int16_t offset) {
1367  BlockTrampolinePoolScope block_trampoline_pool(this);
1368  GenInstrImmediate(BNE, rs, rt, offset);
1369  BlockTrampolinePoolFor(1);  // For associated delay slot.
1370}
1371
1372
1373void Assembler::bovc(Register rs, Register rt, int16_t offset) {
1374  DCHECK(kArchVariant == kMips64r6);
1375  DCHECK(!(rs.is(zero_reg)));
1376  DCHECK(rs.code() >= rt.code());
1377  GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1378}
1379
1380
1381void Assembler::bnvc(Register rs, Register rt, int16_t offset) {
1382  DCHECK(kArchVariant == kMips64r6);
1383  DCHECK(!(rs.is(zero_reg)));
1384  DCHECK(rs.code() >= rt.code());
1385  GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1386}
1387
1388
1389void Assembler::blezalc(Register rt, int16_t offset) {
1390  DCHECK(kArchVariant == kMips64r6);
1391  DCHECK(!(rt.is(zero_reg)));
1392  positions_recorder()->WriteRecordedPositions();
1393  GenInstrImmediate(BLEZ, zero_reg, rt, offset,
1394                    CompactBranchType::COMPACT_BRANCH);
1395}
1396
1397
1398void Assembler::bgezalc(Register rt, int16_t offset) {
1399  DCHECK(kArchVariant == kMips64r6);
1400  DCHECK(!(rt.is(zero_reg)));
1401  positions_recorder()->WriteRecordedPositions();
1402  GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1403}
1404
1405
1406void Assembler::bgezall(Register rs, int16_t offset) {
1407  DCHECK(kArchVariant != kMips64r6);
1408  DCHECK(!(rs.is(zero_reg)));
1409  BlockTrampolinePoolScope block_trampoline_pool(this);
1410  positions_recorder()->WriteRecordedPositions();
1411  GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
1412  BlockTrampolinePoolFor(1);  // For associated delay slot.
1413}
1414
1415
1416void Assembler::bltzalc(Register rt, int16_t offset) {
1417  DCHECK(kArchVariant == kMips64r6);
1418  DCHECK(!(rt.is(zero_reg)));
1419  positions_recorder()->WriteRecordedPositions();
1420  GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1421}
1422
1423
1424void Assembler::bgtzalc(Register rt, int16_t offset) {
1425  DCHECK(kArchVariant == kMips64r6);
1426  DCHECK(!(rt.is(zero_reg)));
1427  positions_recorder()->WriteRecordedPositions();
1428  GenInstrImmediate(BGTZ, zero_reg, rt, offset,
1429                    CompactBranchType::COMPACT_BRANCH);
1430}
1431
1432
1433void Assembler::beqzalc(Register rt, int16_t offset) {
1434  DCHECK(kArchVariant == kMips64r6);
1435  DCHECK(!(rt.is(zero_reg)));
1436  positions_recorder()->WriteRecordedPositions();
1437  GenInstrImmediate(ADDI, zero_reg, rt, offset,
1438                    CompactBranchType::COMPACT_BRANCH);
1439}
1440
1441
1442void Assembler::bnezalc(Register rt, int16_t offset) {
1443  DCHECK(kArchVariant == kMips64r6);
1444  DCHECK(!(rt.is(zero_reg)));
1445  positions_recorder()->WriteRecordedPositions();
1446  GenInstrImmediate(DADDI, zero_reg, rt, offset,
1447                    CompactBranchType::COMPACT_BRANCH);
1448}
1449
1450
1451void Assembler::beqc(Register rs, Register rt, int16_t offset) {
1452  DCHECK(kArchVariant == kMips64r6);
1453  DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1454  if (rs.code() < rt.code()) {
1455    GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1456  } else {
1457    GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1458  }
1459}
1460
1461
1462void Assembler::beqzc(Register rs, int32_t offset) {
1463  DCHECK(kArchVariant == kMips64r6);
1464  DCHECK(!(rs.is(zero_reg)));
1465  GenInstrImmediate(POP66, rs, offset, CompactBranchType::COMPACT_BRANCH);
1466}
1467
1468
1469void Assembler::bnec(Register rs, Register rt, int16_t offset) {
1470  DCHECK(kArchVariant == kMips64r6);
1471  DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1472  if (rs.code() < rt.code()) {
1473    GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1474  } else {
1475    GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1476  }
1477}
1478
1479
1480void Assembler::bnezc(Register rs, int32_t offset) {
1481  DCHECK(kArchVariant == kMips64r6);
1482  DCHECK(!(rs.is(zero_reg)));
1483  GenInstrImmediate(POP76, rs, offset, CompactBranchType::COMPACT_BRANCH);
1484}
1485
1486
1487void Assembler::j(int64_t target) {
1488  BlockTrampolinePoolScope block_trampoline_pool(this);
1489  GenInstrJump(J, static_cast<uint32_t>(target >> 2) & kImm26Mask);
1490  BlockTrampolinePoolFor(1);  // For associated delay slot.
1491}
1492
1493
1494void Assembler::j(Label* target) {
1495  uint64_t imm = jump_offset(target);
1496  if (target->is_bound()) {
1497    BlockTrampolinePoolScope block_trampoline_pool(this);
1498    GenInstrJump(static_cast<Opcode>(kJRawMark),
1499                 static_cast<uint32_t>(imm >> 2) & kImm26Mask);
1500    BlockTrampolinePoolFor(1);  // For associated delay slot.
1501  } else {
1502    j(imm);
1503  }
1504}
1505
1506
1507void Assembler::jal(Label* target) {
1508  uint64_t imm = jump_offset(target);
1509  if (target->is_bound()) {
1510    BlockTrampolinePoolScope block_trampoline_pool(this);
1511    positions_recorder()->WriteRecordedPositions();
1512    GenInstrJump(static_cast<Opcode>(kJalRawMark),
1513                 static_cast<uint32_t>(imm >> 2) & kImm26Mask);
1514    BlockTrampolinePoolFor(1);  // For associated delay slot.
1515  } else {
1516    jal(imm);
1517  }
1518}
1519
1520
1521void Assembler::jr(Register rs) {
1522  if (kArchVariant != kMips64r6) {
1523    BlockTrampolinePoolScope block_trampoline_pool(this);
1524    if (rs.is(ra)) {
1525      positions_recorder()->WriteRecordedPositions();
1526    }
1527    GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
1528    BlockTrampolinePoolFor(1);  // For associated delay slot.
1529  } else {
1530    jalr(rs, zero_reg);
1531  }
1532}
1533
1534
1535void Assembler::jal(int64_t target) {
1536  BlockTrampolinePoolScope block_trampoline_pool(this);
1537  positions_recorder()->WriteRecordedPositions();
1538  GenInstrJump(JAL, static_cast<uint32_t>(target >> 2) & kImm26Mask);
1539  BlockTrampolinePoolFor(1);  // For associated delay slot.
1540}
1541
1542
1543void Assembler::jalr(Register rs, Register rd) {
1544  DCHECK(rs.code() != rd.code());
1545  BlockTrampolinePoolScope block_trampoline_pool(this);
1546  positions_recorder()->WriteRecordedPositions();
1547  GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
1548  BlockTrampolinePoolFor(1);  // For associated delay slot.
1549}
1550
1551
1552void Assembler::jic(Register rt, int16_t offset) {
1553  DCHECK(kArchVariant == kMips64r6);
1554  GenInstrImmediate(POP66, zero_reg, rt, offset);
1555}
1556
1557
1558void Assembler::jialc(Register rt, int16_t offset) {
1559  DCHECK(kArchVariant == kMips64r6);
1560  positions_recorder()->WriteRecordedPositions();
1561  GenInstrImmediate(POP76, zero_reg, rt, offset);
1562}
1563
1564
1565// -------Data-processing-instructions---------
1566
1567// Arithmetic.
1568
1569void Assembler::addu(Register rd, Register rs, Register rt) {
1570  GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
1571}
1572
1573
1574void Assembler::addiu(Register rd, Register rs, int32_t j) {
1575  GenInstrImmediate(ADDIU, rs, rd, j);
1576}
1577
1578
1579void Assembler::subu(Register rd, Register rs, Register rt) {
1580  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
1581}
1582
1583
1584void Assembler::mul(Register rd, Register rs, Register rt) {
1585  if (kArchVariant == kMips64r6) {
1586      GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH);
1587  } else {
1588      GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
1589  }
1590}
1591
1592
1593void Assembler::muh(Register rd, Register rs, Register rt) {
1594  DCHECK(kArchVariant == kMips64r6);
1595  GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH);
1596}
1597
1598
1599void Assembler::mulu(Register rd, Register rs, Register rt) {
1600  DCHECK(kArchVariant == kMips64r6);
1601  GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH_U);
1602}
1603
1604
1605void Assembler::muhu(Register rd, Register rs, Register rt) {
1606  DCHECK(kArchVariant == kMips64r6);
1607  GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH_U);
1608}
1609
1610
1611void Assembler::dmul(Register rd, Register rs, Register rt) {
1612  DCHECK(kArchVariant == kMips64r6);
1613  GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, D_MUL_MUH);
1614}
1615
1616
1617void Assembler::dmuh(Register rd, Register rs, Register rt) {
1618  DCHECK(kArchVariant == kMips64r6);
1619  GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, D_MUL_MUH);
1620}
1621
1622
1623void Assembler::dmulu(Register rd, Register rs, Register rt) {
1624  DCHECK(kArchVariant == kMips64r6);
1625  GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, D_MUL_MUH_U);
1626}
1627
1628
1629void Assembler::dmuhu(Register rd, Register rs, Register rt) {
1630  DCHECK(kArchVariant == kMips64r6);
1631  GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, D_MUL_MUH_U);
1632}
1633
1634
1635void Assembler::mult(Register rs, Register rt) {
1636  DCHECK(kArchVariant != kMips64r6);
1637  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
1638}
1639
1640
1641void Assembler::multu(Register rs, Register rt) {
1642  DCHECK(kArchVariant != kMips64r6);
1643  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
1644}
1645
1646
1647void Assembler::daddiu(Register rd, Register rs, int32_t j) {
1648  GenInstrImmediate(DADDIU, rs, rd, j);
1649}
1650
1651
1652void Assembler::div(Register rs, Register rt) {
1653  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
1654}
1655
1656
1657void Assembler::div(Register rd, Register rs, Register rt) {
1658  DCHECK(kArchVariant == kMips64r6);
1659  GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD);
1660}
1661
1662
1663void Assembler::mod(Register rd, Register rs, Register rt) {
1664  DCHECK(kArchVariant == kMips64r6);
1665  GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD);
1666}
1667
1668
1669void Assembler::divu(Register rs, Register rt) {
1670  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
1671}
1672
1673
1674void Assembler::divu(Register rd, Register rs, Register rt) {
1675  DCHECK(kArchVariant == kMips64r6);
1676  GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD_U);
1677}
1678
1679
1680void Assembler::modu(Register rd, Register rs, Register rt) {
1681  DCHECK(kArchVariant == kMips64r6);
1682  GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD_U);
1683}
1684
1685
1686void Assembler::daddu(Register rd, Register rs, Register rt) {
1687  GenInstrRegister(SPECIAL, rs, rt, rd, 0, DADDU);
1688}
1689
1690
1691void Assembler::dsubu(Register rd, Register rs, Register rt) {
1692  GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSUBU);
1693}
1694
1695
1696void Assembler::dmult(Register rs, Register rt) {
1697  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULT);
1698}
1699
1700
1701void Assembler::dmultu(Register rs, Register rt) {
1702  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULTU);
1703}
1704
1705
1706void Assembler::ddiv(Register rs, Register rt) {
1707  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIV);
1708}
1709
1710
1711void Assembler::ddiv(Register rd, Register rs, Register rt) {
1712  DCHECK(kArchVariant == kMips64r6);
1713  GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, D_DIV_MOD);
1714}
1715
1716
1717void Assembler::dmod(Register rd, Register rs, Register rt) {
1718  DCHECK(kArchVariant == kMips64r6);
1719  GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, D_DIV_MOD);
1720}
1721
1722
1723void Assembler::ddivu(Register rs, Register rt) {
1724  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIVU);
1725}
1726
1727
1728void Assembler::ddivu(Register rd, Register rs, Register rt) {
1729  DCHECK(kArchVariant == kMips64r6);
1730  GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, D_DIV_MOD_U);
1731}
1732
1733
1734void Assembler::dmodu(Register rd, Register rs, Register rt) {
1735  DCHECK(kArchVariant == kMips64r6);
1736  GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, D_DIV_MOD_U);
1737}
1738
1739
1740// Logical.
1741
1742void Assembler::and_(Register rd, Register rs, Register rt) {
1743  GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
1744}
1745
1746
1747void Assembler::andi(Register rt, Register rs, int32_t j) {
1748  DCHECK(is_uint16(j));
1749  GenInstrImmediate(ANDI, rs, rt, j);
1750}
1751
1752
1753void Assembler::or_(Register rd, Register rs, Register rt) {
1754  GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
1755}
1756
1757
1758void Assembler::ori(Register rt, Register rs, int32_t j) {
1759  DCHECK(is_uint16(j));
1760  GenInstrImmediate(ORI, rs, rt, j);
1761}
1762
1763
1764void Assembler::xor_(Register rd, Register rs, Register rt) {
1765  GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
1766}
1767
1768
1769void Assembler::xori(Register rt, Register rs, int32_t j) {
1770  DCHECK(is_uint16(j));
1771  GenInstrImmediate(XORI, rs, rt, j);
1772}
1773
1774
1775void Assembler::nor(Register rd, Register rs, Register rt) {
1776  GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
1777}
1778
1779
1780// Shifts.
1781void Assembler::sll(Register rd,
1782                    Register rt,
1783                    uint16_t sa,
1784                    bool coming_from_nop) {
1785  // Don't allow nop instructions in the form sll zero_reg, zero_reg to be
1786  // generated using the sll instruction. They must be generated using
1787  // nop(int/NopMarkerTypes) or MarkCode(int/NopMarkerTypes) pseudo
1788  // instructions.
1789  DCHECK(coming_from_nop || !(rd.is(zero_reg) && rt.is(zero_reg)));
1790  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SLL);
1791}
1792
1793
1794void Assembler::sllv(Register rd, Register rt, Register rs) {
1795  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
1796}
1797
1798
1799void Assembler::srl(Register rd, Register rt, uint16_t sa) {
1800  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRL);
1801}
1802
1803
1804void Assembler::srlv(Register rd, Register rt, Register rs) {
1805  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
1806}
1807
1808
1809void Assembler::sra(Register rd, Register rt, uint16_t sa) {
1810  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRA);
1811}
1812
1813
1814void Assembler::srav(Register rd, Register rt, Register rs) {
1815  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
1816}
1817
1818
1819void Assembler::rotr(Register rd, Register rt, uint16_t sa) {
1820  // Should be called via MacroAssembler::Ror.
1821  DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
1822  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
1823  Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
1824      | (rd.code() << kRdShift) | (sa << kSaShift) | SRL;
1825  emit(instr);
1826}
1827
1828
1829void Assembler::rotrv(Register rd, Register rt, Register rs) {
1830  // Should be called via MacroAssembler::Ror.
1831  DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
1832  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
1833  Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
1834     | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV;
1835  emit(instr);
1836}
1837
1838
1839void Assembler::dsll(Register rd, Register rt, uint16_t sa) {
1840  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSLL);
1841}
1842
1843
1844void Assembler::dsllv(Register rd, Register rt, Register rs) {
1845  GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSLLV);
1846}
1847
1848
1849void Assembler::dsrl(Register rd, Register rt, uint16_t sa) {
1850  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRL);
1851}
1852
1853
1854void Assembler::dsrlv(Register rd, Register rt, Register rs) {
1855  GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRLV);
1856}
1857
1858
1859void Assembler::drotr(Register rd, Register rt, uint16_t sa) {
1860  DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
1861  Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
1862      | (rd.code() << kRdShift) | (sa << kSaShift) | DSRL;
1863  emit(instr);
1864}
1865
1866
1867void Assembler::drotrv(Register rd, Register rt, Register rs) {
1868  DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid() );
1869  Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
1870      | (rd.code() << kRdShift) | (1 << kSaShift) | DSRLV;
1871  emit(instr);
1872}
1873
1874
1875void Assembler::dsra(Register rd, Register rt, uint16_t sa) {
1876  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRA);
1877}
1878
1879
1880void Assembler::dsrav(Register rd, Register rt, Register rs) {
1881  GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRAV);
1882}
1883
1884
1885void Assembler::dsll32(Register rd, Register rt, uint16_t sa) {
1886  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSLL32);
1887}
1888
1889
1890void Assembler::dsrl32(Register rd, Register rt, uint16_t sa) {
1891  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRL32);
1892}
1893
1894
1895void Assembler::dsra32(Register rd, Register rt, uint16_t sa) {
1896  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRA32);
1897}
1898
1899
1900void Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) {
1901  DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
1902  DCHECK(sa < 5 && sa > 0);
1903  DCHECK(kArchVariant == kMips64r6);
1904  Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) |
1905                (rd.code() << kRdShift) | (sa - 1) << kSaShift | LSA;
1906  emit(instr);
1907}
1908
1909
1910void Assembler::dlsa(Register rd, Register rt, Register rs, uint8_t sa) {
1911  DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
1912  DCHECK(sa < 5 && sa > 0);
1913  DCHECK(kArchVariant == kMips64r6);
1914  Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) |
1915                (rd.code() << kRdShift) | (sa - 1) << kSaShift | DLSA;
1916  emit(instr);
1917}
1918
1919
1920// ------------Memory-instructions-------------
1921
1922// Helper for base-reg + offset, when offset is larger than int16.
1923void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) {
1924  DCHECK(!src.rm().is(at));
1925  DCHECK(is_int32(src.offset_));
1926  daddiu(at, zero_reg, (src.offset_ >> kLuiShift) & kImm16Mask);
1927  dsll(at, at, kLuiShift);
1928  ori(at, at, src.offset_ & kImm16Mask);  // Load 32-bit offset.
1929  daddu(at, at, src.rm());  // Add base register.
1930}
1931
1932
1933void Assembler::lb(Register rd, const MemOperand& rs) {
1934  if (is_int16(rs.offset_)) {
1935    GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
1936  } else {  // Offset > 16 bits, use multiple instructions to load.
1937    LoadRegPlusOffsetToAt(rs);
1938    GenInstrImmediate(LB, at, rd, 0);  // Equiv to lb(rd, MemOperand(at, 0));
1939  }
1940}
1941
1942
1943void Assembler::lbu(Register rd, const MemOperand& rs) {
1944  if (is_int16(rs.offset_)) {
1945    GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
1946  } else {  // Offset > 16 bits, use multiple instructions to load.
1947    LoadRegPlusOffsetToAt(rs);
1948    GenInstrImmediate(LBU, at, rd, 0);  // Equiv to lbu(rd, MemOperand(at, 0));
1949  }
1950}
1951
1952
1953void Assembler::lh(Register rd, const MemOperand& rs) {
1954  if (is_int16(rs.offset_)) {
1955    GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
1956  } else {  // Offset > 16 bits, use multiple instructions to load.
1957    LoadRegPlusOffsetToAt(rs);
1958    GenInstrImmediate(LH, at, rd, 0);  // Equiv to lh(rd, MemOperand(at, 0));
1959  }
1960}
1961
1962
1963void Assembler::lhu(Register rd, const MemOperand& rs) {
1964  if (is_int16(rs.offset_)) {
1965    GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
1966  } else {  // Offset > 16 bits, use multiple instructions to load.
1967    LoadRegPlusOffsetToAt(rs);
1968    GenInstrImmediate(LHU, at, rd, 0);  // Equiv to lhu(rd, MemOperand(at, 0));
1969  }
1970}
1971
1972
1973void Assembler::lw(Register rd, const MemOperand& rs) {
1974  if (is_int16(rs.offset_)) {
1975    GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
1976  } else {  // Offset > 16 bits, use multiple instructions to load.
1977    LoadRegPlusOffsetToAt(rs);
1978    GenInstrImmediate(LW, at, rd, 0);  // Equiv to lw(rd, MemOperand(at, 0));
1979  }
1980}
1981
1982
1983void Assembler::lwu(Register rd, const MemOperand& rs) {
1984  if (is_int16(rs.offset_)) {
1985    GenInstrImmediate(LWU, rs.rm(), rd, rs.offset_);
1986  } else {  // Offset > 16 bits, use multiple instructions to load.
1987    LoadRegPlusOffsetToAt(rs);
1988    GenInstrImmediate(LWU, at, rd, 0);  // Equiv to lwu(rd, MemOperand(at, 0));
1989  }
1990}
1991
1992
1993void Assembler::lwl(Register rd, const MemOperand& rs) {
1994  GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
1995}
1996
1997
1998void Assembler::lwr(Register rd, const MemOperand& rs) {
1999  GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
2000}
2001
2002
2003void Assembler::sb(Register rd, const MemOperand& rs) {
2004  if (is_int16(rs.offset_)) {
2005    GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
2006  } else {  // Offset > 16 bits, use multiple instructions to store.
2007    LoadRegPlusOffsetToAt(rs);
2008    GenInstrImmediate(SB, at, rd, 0);  // Equiv to sb(rd, MemOperand(at, 0));
2009  }
2010}
2011
2012
2013void Assembler::sh(Register rd, const MemOperand& rs) {
2014  if (is_int16(rs.offset_)) {
2015    GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
2016  } else {  // Offset > 16 bits, use multiple instructions to store.
2017    LoadRegPlusOffsetToAt(rs);
2018    GenInstrImmediate(SH, at, rd, 0);  // Equiv to sh(rd, MemOperand(at, 0));
2019  }
2020}
2021
2022
2023void Assembler::sw(Register rd, const MemOperand& rs) {
2024  if (is_int16(rs.offset_)) {
2025    GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
2026  } else {  // Offset > 16 bits, use multiple instructions to store.
2027    LoadRegPlusOffsetToAt(rs);
2028    GenInstrImmediate(SW, at, rd, 0);  // Equiv to sw(rd, MemOperand(at, 0));
2029  }
2030}
2031
2032
2033void Assembler::swl(Register rd, const MemOperand& rs) {
2034  GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
2035}
2036
2037
2038void Assembler::swr(Register rd, const MemOperand& rs) {
2039  GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
2040}
2041
2042
2043void Assembler::lui(Register rd, int32_t j) {
2044  DCHECK(is_uint16(j));
2045  GenInstrImmediate(LUI, zero_reg, rd, j);
2046}
2047
2048
2049void Assembler::aui(Register rt, Register rs, int32_t j) {
2050  // This instruction uses same opcode as 'lui'. The difference in encoding is
2051  // 'lui' has zero reg. for rs field.
2052  DCHECK(is_uint16(j));
2053  GenInstrImmediate(LUI, rs, rt, j);
2054}
2055
2056
2057void Assembler::daui(Register rt, Register rs, int32_t j) {
2058  DCHECK(is_uint16(j));
2059  DCHECK(!rs.is(zero_reg));
2060  GenInstrImmediate(DAUI, rs, rt, j);
2061}
2062
2063
2064void Assembler::dahi(Register rs, int32_t j) {
2065  DCHECK(is_uint16(j));
2066  GenInstrImmediate(REGIMM, rs, DAHI, j);
2067}
2068
2069
2070void Assembler::dati(Register rs, int32_t j) {
2071  DCHECK(is_uint16(j));
2072  GenInstrImmediate(REGIMM, rs, DATI, j);
2073}
2074
2075
2076void Assembler::ldl(Register rd, const MemOperand& rs) {
2077  GenInstrImmediate(LDL, rs.rm(), rd, rs.offset_);
2078}
2079
2080
2081void Assembler::ldr(Register rd, const MemOperand& rs) {
2082  GenInstrImmediate(LDR, rs.rm(), rd, rs.offset_);
2083}
2084
2085
2086void Assembler::sdl(Register rd, const MemOperand& rs) {
2087  GenInstrImmediate(SDL, rs.rm(), rd, rs.offset_);
2088}
2089
2090
2091void Assembler::sdr(Register rd, const MemOperand& rs) {
2092  GenInstrImmediate(SDR, rs.rm(), rd, rs.offset_);
2093}
2094
2095
2096void Assembler::ld(Register rd, const MemOperand& rs) {
2097  if (is_int16(rs.offset_)) {
2098    GenInstrImmediate(LD, rs.rm(), rd, rs.offset_);
2099  } else {  // Offset > 16 bits, use multiple instructions to load.
2100    LoadRegPlusOffsetToAt(rs);
2101    GenInstrImmediate(LD, at, rd, 0);  // Equiv to lw(rd, MemOperand(at, 0));
2102  }
2103}
2104
2105
2106void Assembler::sd(Register rd, const MemOperand& rs) {
2107  if (is_int16(rs.offset_)) {
2108    GenInstrImmediate(SD, rs.rm(), rd, rs.offset_);
2109  } else {  // Offset > 16 bits, use multiple instructions to store.
2110    LoadRegPlusOffsetToAt(rs);
2111    GenInstrImmediate(SD, at, rd, 0);  // Equiv to sw(rd, MemOperand(at, 0));
2112  }
2113}
2114
2115
2116// ---------PC-Relative instructions-----------
2117
2118void Assembler::addiupc(Register rs, int32_t imm19) {
2119  DCHECK(kArchVariant == kMips64r6);
2120  DCHECK(rs.is_valid() && is_int19(imm19));
2121  uint32_t imm21 = ADDIUPC << kImm19Bits | (imm19 & kImm19Mask);
2122  GenInstrImmediate(PCREL, rs, imm21);
2123}
2124
2125
2126void Assembler::lwpc(Register rs, int32_t offset19) {
2127  DCHECK(kArchVariant == kMips64r6);
2128  DCHECK(rs.is_valid() && is_int19(offset19));
2129  uint32_t imm21 = LWPC << kImm19Bits | (offset19 & kImm19Mask);
2130  GenInstrImmediate(PCREL, rs, imm21);
2131}
2132
2133
2134void Assembler::lwupc(Register rs, int32_t offset19) {
2135  DCHECK(kArchVariant == kMips64r6);
2136  DCHECK(rs.is_valid() && is_int19(offset19));
2137  uint32_t imm21 = LWUPC << kImm19Bits | (offset19 & kImm19Mask);
2138  GenInstrImmediate(PCREL, rs, imm21);
2139}
2140
2141
2142void Assembler::ldpc(Register rs, int32_t offset18) {
2143  DCHECK(kArchVariant == kMips64r6);
2144  DCHECK(rs.is_valid() && is_int18(offset18));
2145  uint32_t imm21 = LDPC << kImm18Bits | (offset18 & kImm18Mask);
2146  GenInstrImmediate(PCREL, rs, imm21);
2147}
2148
2149
2150void Assembler::auipc(Register rs, int16_t imm16) {
2151  DCHECK(kArchVariant == kMips64r6);
2152  DCHECK(rs.is_valid());
2153  uint32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask);
2154  GenInstrImmediate(PCREL, rs, imm21);
2155}
2156
2157
2158void Assembler::aluipc(Register rs, int16_t imm16) {
2159  DCHECK(kArchVariant == kMips64r6);
2160  DCHECK(rs.is_valid());
2161  uint32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask);
2162  GenInstrImmediate(PCREL, rs, imm21);
2163}
2164
2165
2166// -------------Misc-instructions--------------
2167
2168// Break / Trap instructions.
2169void Assembler::break_(uint32_t code, bool break_as_stop) {
2170  DCHECK((code & ~0xfffff) == 0);
2171  // We need to invalidate breaks that could be stops as well because the
2172  // simulator expects a char pointer after the stop instruction.
2173  // See constants-mips.h for explanation.
2174  DCHECK((break_as_stop &&
2175          code <= kMaxStopCode &&
2176          code > kMaxWatchpointCode) ||
2177         (!break_as_stop &&
2178          (code > kMaxStopCode ||
2179           code <= kMaxWatchpointCode)));
2180  Instr break_instr = SPECIAL | BREAK | (code << 6);
2181  emit(break_instr);
2182}
2183
2184
2185void Assembler::stop(const char* msg, uint32_t code) {
2186  DCHECK(code > kMaxWatchpointCode);
2187  DCHECK(code <= kMaxStopCode);
2188#if defined(V8_HOST_ARCH_MIPS) || defined(V8_HOST_ARCH_MIPS64)
2189  break_(0x54321);
2190#else  // V8_HOST_ARCH_MIPS
2191  BlockTrampolinePoolFor(3);
2192  // The Simulator will handle the stop instruction and get the message address.
2193  // On MIPS stop() is just a special kind of break_().
2194  break_(code, true);
2195  emit(reinterpret_cast<uint64_t>(msg));
2196#endif
2197}
2198
2199
2200void Assembler::tge(Register rs, Register rt, uint16_t code) {
2201  DCHECK(is_uint10(code));
2202  Instr instr = SPECIAL | TGE | rs.code() << kRsShift
2203      | rt.code() << kRtShift | code << 6;
2204  emit(instr);
2205}
2206
2207
2208void Assembler::tgeu(Register rs, Register rt, uint16_t code) {
2209  DCHECK(is_uint10(code));
2210  Instr instr = SPECIAL | TGEU | rs.code() << kRsShift
2211      | rt.code() << kRtShift | code << 6;
2212  emit(instr);
2213}
2214
2215
2216void Assembler::tlt(Register rs, Register rt, uint16_t code) {
2217  DCHECK(is_uint10(code));
2218  Instr instr =
2219      SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
2220  emit(instr);
2221}
2222
2223
2224void Assembler::tltu(Register rs, Register rt, uint16_t code) {
2225  DCHECK(is_uint10(code));
2226  Instr instr =
2227      SPECIAL | TLTU | rs.code() << kRsShift
2228      | rt.code() << kRtShift | code << 6;
2229  emit(instr);
2230}
2231
2232
2233void Assembler::teq(Register rs, Register rt, uint16_t code) {
2234  DCHECK(is_uint10(code));
2235  Instr instr =
2236      SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
2237  emit(instr);
2238}
2239
2240
2241void Assembler::tne(Register rs, Register rt, uint16_t code) {
2242  DCHECK(is_uint10(code));
2243  Instr instr =
2244      SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
2245  emit(instr);
2246}
2247
2248
2249// Move from HI/LO register.
2250
2251void Assembler::mfhi(Register rd) {
2252  GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
2253}
2254
2255
2256void Assembler::mflo(Register rd) {
2257  GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
2258}
2259
2260
2261// Set on less than instructions.
2262void Assembler::slt(Register rd, Register rs, Register rt) {
2263  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
2264}
2265
2266
2267void Assembler::sltu(Register rd, Register rs, Register rt) {
2268  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
2269}
2270
2271
2272void Assembler::slti(Register rt, Register rs, int32_t j) {
2273  GenInstrImmediate(SLTI, rs, rt, j);
2274}
2275
2276
2277void Assembler::sltiu(Register rt, Register rs, int32_t j) {
2278  GenInstrImmediate(SLTIU, rs, rt, j);
2279}
2280
2281
2282// Conditional move.
2283void Assembler::movz(Register rd, Register rs, Register rt) {
2284  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ);
2285}
2286
2287
2288void Assembler::movn(Register rd, Register rs, Register rt) {
2289  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
2290}
2291
2292
2293void Assembler::movt(Register rd, Register rs, uint16_t cc) {
2294  Register rt;
2295  rt.reg_code = (cc & 0x0007) << 2 | 1;
2296  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
2297}
2298
2299
2300void Assembler::movf(Register rd, Register rs, uint16_t cc) {
2301  Register rt;
2302  rt.reg_code = (cc & 0x0007) << 2 | 0;
2303  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
2304}
2305
2306
2307void Assembler::min_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2308  min(S, fd, fs, ft);
2309}
2310
2311
2312void Assembler::min_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2313  min(D, fd, fs, ft);
2314}
2315
2316
2317void Assembler::max_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2318  max(S, fd, fs, ft);
2319}
2320
2321
2322void Assembler::max_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2323  max(D, fd, fs, ft);
2324}
2325
2326
2327void Assembler::mina_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2328  mina(S, fd, fs, ft);
2329}
2330
2331
2332void Assembler::mina_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2333  mina(D, fd, fs, ft);
2334}
2335
2336
2337void Assembler::maxa_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2338  maxa(S, fd, fs, ft);
2339}
2340
2341
2342void Assembler::maxa_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2343  maxa(D, fd, fs, ft);
2344}
2345
2346
2347void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister fs,
2348                    FPURegister ft) {
2349  DCHECK(kArchVariant == kMips64r6);
2350  DCHECK((fmt == D) || (fmt == S));
2351  GenInstrRegister(COP1, fmt, ft, fs, fd, MAX);
2352}
2353
2354
2355void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs,
2356                    FPURegister ft) {
2357  DCHECK(kArchVariant == kMips64r6);
2358  DCHECK((fmt == D) || (fmt == S));
2359  GenInstrRegister(COP1, fmt, ft, fs, fd, MIN);
2360}
2361
2362
2363// GPR.
2364void Assembler::seleqz(Register rd, Register rs, Register rt) {
2365  DCHECK(kArchVariant == kMips64r6);
2366  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELEQZ_S);
2367}
2368
2369
2370// GPR.
2371void Assembler::selnez(Register rd, Register rs, Register rt) {
2372  DCHECK(kArchVariant == kMips64r6);
2373  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELNEZ_S);
2374}
2375
2376
2377// Bit twiddling.
2378void Assembler::clz(Register rd, Register rs) {
2379  if (kArchVariant != kMips64r6) {
2380    // Clz instr requires same GPR number in 'rd' and 'rt' fields.
2381    GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
2382  } else {
2383    GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, CLZ_R6);
2384  }
2385}
2386
2387
2388void Assembler::dclz(Register rd, Register rs) {
2389  if (kArchVariant != kMips64r6) {
2390    // dclz instr requires same GPR number in 'rd' and 'rt' fields.
2391    GenInstrRegister(SPECIAL2, rs, rd, rd, 0, DCLZ);
2392  } else {
2393    GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, DCLZ_R6);
2394  }
2395}
2396
2397
2398void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
2399  // Should be called via MacroAssembler::Ins.
2400  // Ins instr has 'rt' field as dest, and two uint5: msb, lsb.
2401  DCHECK((kArchVariant == kMips64r2) || (kArchVariant == kMips64r6));
2402  GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS);
2403}
2404
2405
2406void Assembler::dins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
2407  // Should be called via MacroAssembler::Dins.
2408  // Dext instr has 'rt' field as dest, and two uint5: msb, lsb.
2409  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2410  GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, DINS);
2411}
2412
2413
2414void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
2415  // Should be called via MacroAssembler::Ext.
2416  // Ext instr has 'rt' field as dest, and two uint5: msb, lsb.
2417  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2418  GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT);
2419}
2420
2421
2422void Assembler::dext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
2423  // Should be called via MacroAssembler::Dext.
2424  // Dext instr has 'rt' field as dest, and two uint5: msb, lsb.
2425  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2426  GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, DEXT);
2427}
2428
2429
2430void Assembler::dextm(Register rt, Register rs, uint16_t pos, uint16_t size) {
2431  // Should be called via MacroAssembler::Dextm.
2432  // Dextm instr has 'rt' field as dest, and two uint5: msb, lsb.
2433  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2434  GenInstrRegister(SPECIAL3, rs, rt, size - 1 - 32, pos, DEXTM);
2435}
2436
2437
2438void Assembler::dextu(Register rt, Register rs, uint16_t pos, uint16_t size) {
2439  // Should be called via MacroAssembler::Dextu.
2440  // Dext instr has 'rt' field as dest, and two uint5: msb, lsb.
2441  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2442  GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos - 32, DEXTU);
2443}
2444
2445
2446void Assembler::bitswap(Register rd, Register rt) {
2447  DCHECK(kArchVariant == kMips64r6);
2448  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, BSHFL);
2449}
2450
2451
2452void Assembler::dbitswap(Register rd, Register rt) {
2453  DCHECK(kArchVariant == kMips64r6);
2454  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, DBSHFL);
2455}
2456
2457
2458void Assembler::pref(int32_t hint, const MemOperand& rs) {
2459  DCHECK(is_uint5(hint) && is_uint16(rs.offset_));
2460  Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift)
2461      | (rs.offset_);
2462  emit(instr);
2463}
2464
2465
2466void Assembler::align(Register rd, Register rs, Register rt, uint8_t bp) {
2467  DCHECK(kArchVariant == kMips64r6);
2468  DCHECK(is_uint3(bp));
2469  uint16_t sa = (ALIGN << kBp2Bits) | bp;
2470  GenInstrRegister(SPECIAL3, rs, rt, rd, sa, BSHFL);
2471}
2472
2473
2474void Assembler::dalign(Register rd, Register rs, Register rt, uint8_t bp) {
2475  DCHECK(kArchVariant == kMips64r6);
2476  DCHECK(is_uint3(bp));
2477  uint16_t sa = (DALIGN << kBp3Bits) | bp;
2478  GenInstrRegister(SPECIAL3, rs, rt, rd, sa, DBSHFL);
2479}
2480
2481
2482// --------Coprocessor-instructions----------------
2483
2484// Load, store, move.
2485void Assembler::lwc1(FPURegister fd, const MemOperand& src) {
2486  if (is_int16(src.offset_)) {
2487    GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
2488  } else {  // Offset > 16 bits, use multiple instructions to load.
2489    LoadRegPlusOffsetToAt(src);
2490    GenInstrImmediate(LWC1, at, fd, 0);
2491  }
2492}
2493
2494
2495void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
2496  DCHECK(!src.rm().is(at));
2497  if (is_int16(src.offset_)) {
2498    GenInstrImmediate(LDC1, src.rm(), fd, src.offset_);
2499  } else {  // Offset > 16 bits, use multiple instructions to load.
2500    LoadRegPlusOffsetToAt(src);
2501    GenInstrImmediate(LDC1, at, fd, 0);
2502  }
2503}
2504
2505
2506void Assembler::swc1(FPURegister fd, const MemOperand& src) {
2507  if (is_int16(src.offset_)) {
2508    GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
2509  } else {  // Offset > 16 bits, use multiple instructions to load.
2510    LoadRegPlusOffsetToAt(src);
2511    GenInstrImmediate(SWC1, at, fd, 0);
2512  }
2513}
2514
2515
2516void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
2517  DCHECK(!src.rm().is(at));
2518  if (is_int16(src.offset_)) {
2519    GenInstrImmediate(SDC1, src.rm(), fd, src.offset_);
2520  } else {  // Offset > 16 bits, use multiple instructions to load.
2521    LoadRegPlusOffsetToAt(src);
2522    GenInstrImmediate(SDC1, at, fd, 0);
2523  }
2524}
2525
2526
2527void Assembler::mtc1(Register rt, FPURegister fs) {
2528  GenInstrRegister(COP1, MTC1, rt, fs, f0);
2529}
2530
2531
2532void Assembler::mthc1(Register rt, FPURegister fs) {
2533  GenInstrRegister(COP1, MTHC1, rt, fs, f0);
2534}
2535
2536
2537void Assembler::dmtc1(Register rt, FPURegister fs) {
2538  GenInstrRegister(COP1, DMTC1, rt, fs, f0);
2539}
2540
2541
2542void Assembler::mfc1(Register rt, FPURegister fs) {
2543  GenInstrRegister(COP1, MFC1, rt, fs, f0);
2544}
2545
2546
2547void Assembler::mfhc1(Register rt, FPURegister fs) {
2548  GenInstrRegister(COP1, MFHC1, rt, fs, f0);
2549}
2550
2551
2552void Assembler::dmfc1(Register rt, FPURegister fs) {
2553  GenInstrRegister(COP1, DMFC1, rt, fs, f0);
2554}
2555
2556
2557void Assembler::ctc1(Register rt, FPUControlRegister fs) {
2558  GenInstrRegister(COP1, CTC1, rt, fs);
2559}
2560
2561
2562void Assembler::cfc1(Register rt, FPUControlRegister fs) {
2563  GenInstrRegister(COP1, CFC1, rt, fs);
2564}
2565
2566
2567void Assembler::DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
2568  uint64_t i;
2569  memcpy(&i, &d, 8);
2570
2571  *lo = i & 0xffffffff;
2572  *hi = i >> 32;
2573}
2574
2575
2576void Assembler::sel(SecondaryField fmt, FPURegister fd, FPURegister fs,
2577                    FPURegister ft) {
2578  DCHECK(kArchVariant == kMips64r6);
2579  DCHECK((fmt == D) || (fmt == S));
2580
2581  GenInstrRegister(COP1, fmt, ft, fs, fd, SEL);
2582}
2583
2584
2585void Assembler::sel_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2586  sel(S, fd, fs, ft);
2587}
2588
2589
2590void Assembler::sel_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2591  sel(D, fd, fs, ft);
2592}
2593
2594
2595// FPR.
2596void Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
2597                       FPURegister ft) {
2598  DCHECK((fmt == D) || (fmt == S));
2599  GenInstrRegister(COP1, fmt, ft, fs, fd, SELEQZ_C);
2600}
2601
2602
2603void Assembler::seleqz_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2604  seleqz(D, fd, fs, ft);
2605}
2606
2607
2608void Assembler::seleqz_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2609  seleqz(S, fd, fs, ft);
2610}
2611
2612
2613void Assembler::selnez_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2614  selnez(D, fd, fs, ft);
2615}
2616
2617
2618void Assembler::selnez_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2619  selnez(S, fd, fs, ft);
2620}
2621
2622
2623void Assembler::movz_s(FPURegister fd, FPURegister fs, Register rt) {
2624  DCHECK(kArchVariant == kMips64r2);
2625  GenInstrRegister(COP1, S, rt, fs, fd, MOVZ_C);
2626}
2627
2628
2629void Assembler::movz_d(FPURegister fd, FPURegister fs, Register rt) {
2630  DCHECK(kArchVariant == kMips64r2);
2631  GenInstrRegister(COP1, D, rt, fs, fd, MOVZ_C);
2632}
2633
2634
2635void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
2636  DCHECK(kArchVariant == kMips64r2);
2637  FPURegister ft;
2638  ft.reg_code = (cc & 0x0007) << 2 | 1;
2639  GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
2640}
2641
2642
2643void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
2644  DCHECK(kArchVariant == kMips64r2);
2645  FPURegister ft;
2646  ft.reg_code = (cc & 0x0007) << 2 | 1;
2647  GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
2648}
2649
2650
2651void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
2652  DCHECK(kArchVariant == kMips64r2);
2653  FPURegister ft;
2654  ft.reg_code = (cc & 0x0007) << 2 | 0;
2655  GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
2656}
2657
2658
2659void Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) {
2660  DCHECK(kArchVariant == kMips64r2);
2661  FPURegister ft;
2662  ft.reg_code = (cc & 0x0007) << 2 | 0;
2663  GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
2664}
2665
2666
2667void Assembler::movn_s(FPURegister fd, FPURegister fs, Register rt) {
2668  DCHECK(kArchVariant == kMips64r2);
2669  GenInstrRegister(COP1, S, rt, fs, fd, MOVN_C);
2670}
2671
2672
2673void Assembler::movn_d(FPURegister fd, FPURegister fs, Register rt) {
2674  DCHECK(kArchVariant == kMips64r2);
2675  GenInstrRegister(COP1, D, rt, fs, fd, MOVN_C);
2676}
2677
2678
2679// FPR.
2680void Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
2681                       FPURegister ft) {
2682  DCHECK(kArchVariant == kMips64r6);
2683  DCHECK((fmt == D) || (fmt == S));
2684  GenInstrRegister(COP1, fmt, ft, fs, fd, SELNEZ_C);
2685}
2686
2687
2688// Arithmetic.
2689
2690void Assembler::add_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2691  GenInstrRegister(COP1, S, ft, fs, fd, ADD_D);
2692}
2693
2694
2695void Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2696  GenInstrRegister(COP1, D, ft, fs, fd, ADD_D);
2697}
2698
2699
2700void Assembler::sub_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2701  GenInstrRegister(COP1, S, ft, fs, fd, SUB_D);
2702}
2703
2704
2705void Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2706  GenInstrRegister(COP1, D, ft, fs, fd, SUB_D);
2707}
2708
2709
2710void Assembler::mul_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2711  GenInstrRegister(COP1, S, ft, fs, fd, MUL_D);
2712}
2713
2714
2715void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2716  GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
2717}
2718
2719
2720void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
2721    FPURegister ft) {
2722  GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D);
2723}
2724
2725
2726void Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2727  GenInstrRegister(COP1, S, ft, fs, fd, DIV_D);
2728}
2729
2730
2731void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2732  GenInstrRegister(COP1, D, ft, fs, fd, DIV_D);
2733}
2734
2735
2736void Assembler::abs_s(FPURegister fd, FPURegister fs) {
2737  GenInstrRegister(COP1, S, f0, fs, fd, ABS_D);
2738}
2739
2740
2741void Assembler::abs_d(FPURegister fd, FPURegister fs) {
2742  GenInstrRegister(COP1, D, f0, fs, fd, ABS_D);
2743}
2744
2745
2746void Assembler::mov_d(FPURegister fd, FPURegister fs) {
2747  GenInstrRegister(COP1, D, f0, fs, fd, MOV_D);
2748}
2749
2750
2751void Assembler::mov_s(FPURegister fd, FPURegister fs) {
2752  GenInstrRegister(COP1, S, f0, fs, fd, MOV_S);
2753}
2754
2755
2756void Assembler::neg_s(FPURegister fd, FPURegister fs) {
2757  GenInstrRegister(COP1, S, f0, fs, fd, NEG_D);
2758}
2759
2760
2761void Assembler::neg_d(FPURegister fd, FPURegister fs) {
2762  GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
2763}
2764
2765
2766void Assembler::sqrt_s(FPURegister fd, FPURegister fs) {
2767  GenInstrRegister(COP1, S, f0, fs, fd, SQRT_D);
2768}
2769
2770
2771void Assembler::sqrt_d(FPURegister fd, FPURegister fs) {
2772  GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D);
2773}
2774
2775
2776void Assembler::rsqrt_s(FPURegister fd, FPURegister fs) {
2777  GenInstrRegister(COP1, S, f0, fs, fd, RSQRT_S);
2778}
2779
2780
2781void Assembler::rsqrt_d(FPURegister fd, FPURegister fs) {
2782  GenInstrRegister(COP1, D, f0, fs, fd, RSQRT_D);
2783}
2784
2785
2786void Assembler::recip_d(FPURegister fd, FPURegister fs) {
2787  GenInstrRegister(COP1, D, f0, fs, fd, RECIP_D);
2788}
2789
2790
2791void Assembler::recip_s(FPURegister fd, FPURegister fs) {
2792  GenInstrRegister(COP1, S, f0, fs, fd, RECIP_S);
2793}
2794
2795
2796// Conversions.
2797void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
2798  GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
2799}
2800
2801
2802void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
2803  GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
2804}
2805
2806
2807void Assembler::trunc_w_s(FPURegister fd, FPURegister fs) {
2808  GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S);
2809}
2810
2811
2812void Assembler::trunc_w_d(FPURegister fd, FPURegister fs) {
2813  GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D);
2814}
2815
2816
2817void Assembler::round_w_s(FPURegister fd, FPURegister fs) {
2818  GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S);
2819}
2820
2821
2822void Assembler::round_w_d(FPURegister fd, FPURegister fs) {
2823  GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D);
2824}
2825
2826
2827void Assembler::floor_w_s(FPURegister fd, FPURegister fs) {
2828  GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S);
2829}
2830
2831
2832void Assembler::floor_w_d(FPURegister fd, FPURegister fs) {
2833  GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D);
2834}
2835
2836
2837void Assembler::ceil_w_s(FPURegister fd, FPURegister fs) {
2838  GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S);
2839}
2840
2841
2842void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) {
2843  GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D);
2844}
2845
2846
2847void Assembler::rint_s(FPURegister fd, FPURegister fs) { rint(S, fd, fs); }
2848
2849
2850void Assembler::rint_d(FPURegister fd, FPURegister fs) { rint(D, fd, fs); }
2851
2852
2853void Assembler::rint(SecondaryField fmt, FPURegister fd, FPURegister fs) {
2854  DCHECK(kArchVariant == kMips64r6);
2855  GenInstrRegister(COP1, fmt, f0, fs, fd, RINT);
2856}
2857
2858
2859void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
2860  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2861  GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
2862}
2863
2864
2865void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
2866  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2867  GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
2868}
2869
2870
2871void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) {
2872  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2873  GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S);
2874}
2875
2876
2877void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) {
2878  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2879  GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D);
2880}
2881
2882
2883void Assembler::round_l_s(FPURegister fd, FPURegister fs) {
2884  GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S);
2885}
2886
2887
2888void Assembler::round_l_d(FPURegister fd, FPURegister fs) {
2889  GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D);
2890}
2891
2892
2893void Assembler::floor_l_s(FPURegister fd, FPURegister fs) {
2894  GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S);
2895}
2896
2897
2898void Assembler::floor_l_d(FPURegister fd, FPURegister fs) {
2899  GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D);
2900}
2901
2902
2903void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) {
2904  GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S);
2905}
2906
2907
2908void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
2909  GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D);
2910}
2911
2912
2913void Assembler::class_s(FPURegister fd, FPURegister fs) {
2914  DCHECK(kArchVariant == kMips64r6);
2915  GenInstrRegister(COP1, S, f0, fs, fd, CLASS_S);
2916}
2917
2918
2919void Assembler::class_d(FPURegister fd, FPURegister fs) {
2920  DCHECK(kArchVariant == kMips64r6);
2921  GenInstrRegister(COP1, D, f0, fs, fd, CLASS_D);
2922}
2923
2924
2925void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs,
2926                     FPURegister ft) {
2927  DCHECK(kArchVariant == kMips64r6);
2928  DCHECK((fmt == D) || (fmt == S));
2929  GenInstrRegister(COP1, fmt, ft, fs, fd, MINA);
2930}
2931
2932
2933void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister fs,
2934                     FPURegister ft) {
2935  DCHECK(kArchVariant == kMips64r6);
2936  DCHECK((fmt == D) || (fmt == S));
2937  GenInstrRegister(COP1, fmt, ft, fs, fd, MAXA);
2938}
2939
2940
2941void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
2942  GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
2943}
2944
2945
2946void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
2947  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2948  GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
2949}
2950
2951
2952void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
2953  GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
2954}
2955
2956
2957void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
2958  GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
2959}
2960
2961
2962void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
2963  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
2964  GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
2965}
2966
2967
2968void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
2969  GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
2970}
2971
2972
2973// Conditions for >= MIPSr6.
2974void Assembler::cmp(FPUCondition cond, SecondaryField fmt,
2975    FPURegister fd, FPURegister fs, FPURegister ft) {
2976  DCHECK(kArchVariant == kMips64r6);
2977  DCHECK((fmt & ~(31 << kRsShift)) == 0);
2978  Instr instr = COP1 | fmt | ft.code() << kFtShift |
2979      fs.code() << kFsShift | fd.code() << kFdShift | (0 << 5) | cond;
2980  emit(instr);
2981}
2982
2983
2984void Assembler::cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs,
2985                      FPURegister ft) {
2986  cmp(cond, W, fd, fs, ft);
2987}
2988
2989void Assembler::cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs,
2990                      FPURegister ft) {
2991  cmp(cond, L, fd, fs, ft);
2992}
2993
2994
2995void Assembler::bc1eqz(int16_t offset, FPURegister ft) {
2996  DCHECK(kArchVariant == kMips64r6);
2997  Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask);
2998  emit(instr);
2999}
3000
3001
3002void Assembler::bc1nez(int16_t offset, FPURegister ft) {
3003  DCHECK(kArchVariant == kMips64r6);
3004  Instr instr = COP1 | BC1NEZ | ft.code() << kFtShift | (offset & kImm16Mask);
3005  emit(instr);
3006}
3007
3008
3009// Conditions for < MIPSr6.
3010void Assembler::c(FPUCondition cond, SecondaryField fmt,
3011    FPURegister fs, FPURegister ft, uint16_t cc) {
3012  DCHECK(kArchVariant != kMips64r6);
3013  DCHECK(is_uint3(cc));
3014  DCHECK(fmt == S || fmt == D);
3015  DCHECK((fmt & ~(31 << kRsShift)) == 0);
3016  Instr instr = COP1 | fmt | ft.code() << kFtShift | fs.code() << kFsShift
3017      | cc << 8 | 3 << 4 | cond;
3018  emit(instr);
3019}
3020
3021
3022void Assembler::c_s(FPUCondition cond, FPURegister fs, FPURegister ft,
3023                    uint16_t cc) {
3024  c(cond, S, fs, ft, cc);
3025}
3026
3027
3028void Assembler::c_d(FPUCondition cond, FPURegister fs, FPURegister ft,
3029                    uint16_t cc) {
3030  c(cond, D, fs, ft, cc);
3031}
3032
3033
3034void Assembler::fcmp(FPURegister src1, const double src2,
3035      FPUCondition cond) {
3036  DCHECK(src2 == 0.0);
3037  mtc1(zero_reg, f14);
3038  cvt_d_w(f14, f14);
3039  c(cond, D, src1, f14, 0);
3040}
3041
3042
3043void Assembler::bc1f(int16_t offset, uint16_t cc) {
3044  DCHECK(is_uint3(cc));
3045  Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
3046  emit(instr);
3047}
3048
3049
3050void Assembler::bc1t(int16_t offset, uint16_t cc) {
3051  DCHECK(is_uint3(cc));
3052  Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
3053  emit(instr);
3054}
3055
3056
3057int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
3058                                         intptr_t pc_delta) {
3059  if (RelocInfo::IsInternalReference(rmode)) {
3060    int64_t* p = reinterpret_cast<int64_t*>(pc);
3061    if (*p == kEndOfJumpChain) {
3062      return 0;  // Number of instructions patched.
3063    }
3064    *p += pc_delta;
3065    return 2;  // Number of instructions patched.
3066  }
3067  Instr instr = instr_at(pc);
3068  DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode));
3069  if (IsLui(instr)) {
3070    Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize);
3071    Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize);
3072    Instr instr_ori2 = instr_at(pc + 3 * Assembler::kInstrSize);
3073    DCHECK(IsOri(instr_ori));
3074    DCHECK(IsOri(instr_ori2));
3075    // TODO(plind): symbolic names for the shifts.
3076    int64_t imm = (instr_lui & static_cast<int64_t>(kImm16Mask)) << 48;
3077    imm |= (instr_ori & static_cast<int64_t>(kImm16Mask)) << 32;
3078    imm |= (instr_ori2 & static_cast<int64_t>(kImm16Mask)) << 16;
3079    // Sign extend address.
3080    imm >>= 16;
3081
3082    if (imm == kEndOfJumpChain) {
3083      return 0;  // Number of instructions patched.
3084    }
3085    imm += pc_delta;
3086    DCHECK((imm & 3) == 0);
3087
3088    instr_lui &= ~kImm16Mask;
3089    instr_ori &= ~kImm16Mask;
3090    instr_ori2 &= ~kImm16Mask;
3091
3092    instr_at_put(pc + 0 * Assembler::kInstrSize,
3093                 instr_lui | ((imm >> 32) & kImm16Mask));
3094    instr_at_put(pc + 1 * Assembler::kInstrSize,
3095                 instr_ori | (imm >> 16 & kImm16Mask));
3096    instr_at_put(pc + 3 * Assembler::kInstrSize,
3097                 instr_ori2 | (imm & kImm16Mask));
3098    return 4;  // Number of instructions patched.
3099  } else if (IsJ(instr) || IsJal(instr)) {
3100    // Regular j/jal relocation.
3101    uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
3102    imm28 += pc_delta;
3103    imm28 &= kImm28Mask;
3104    instr &= ~kImm26Mask;
3105    DCHECK((imm28 & 3) == 0);
3106    uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2);
3107    instr_at_put(pc, instr | (imm26 & kImm26Mask));
3108    return 1;  // Number of instructions patched.
3109  } else {
3110    DCHECK(((instr & kJumpRawMask) == kJRawMark) ||
3111           ((instr & kJumpRawMask) == kJalRawMark));
3112    // Unbox raw offset and emit j/jal.
3113    int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
3114    // Sign extend 28-bit offset to 32-bit.
3115    imm28 = (imm28 << 4) >> 4;
3116    uint64_t target =
3117        static_cast<int64_t>(imm28) + reinterpret_cast<uint64_t>(pc);
3118    target &= kImm28Mask;
3119    DCHECK((imm28 & 3) == 0);
3120    uint32_t imm26 = static_cast<uint32_t>(target >> 2);
3121    // Check markings whether to emit j or jal.
3122    uint32_t unbox = (instr & kJRawMark) ? J : JAL;
3123    instr_at_put(pc, unbox | (imm26 & kImm26Mask));
3124    return 1;  // Number of instructions patched.
3125  }
3126}
3127
3128
3129void Assembler::GrowBuffer() {
3130  if (!own_buffer_) FATAL("external code buffer is too small");
3131
3132  // Compute new buffer size.
3133  CodeDesc desc;  // The new buffer.
3134  if (buffer_size_ < 1 * MB) {
3135    desc.buffer_size = 2*buffer_size_;
3136  } else {
3137    desc.buffer_size = buffer_size_ + 1*MB;
3138  }
3139  CHECK_GT(desc.buffer_size, 0);  // No overflow.
3140
3141  // Set up new buffer.
3142  desc.buffer = NewArray<byte>(desc.buffer_size);
3143  desc.origin = this;
3144
3145  desc.instr_size = pc_offset();
3146  desc.reloc_size =
3147      static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
3148
3149  // Copy the data.
3150  intptr_t pc_delta = desc.buffer - buffer_;
3151  intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
3152      (buffer_ + buffer_size_);
3153  MemMove(desc.buffer, buffer_, desc.instr_size);
3154  MemMove(reloc_info_writer.pos() + rc_delta,
3155              reloc_info_writer.pos(), desc.reloc_size);
3156
3157  // Switch buffers.
3158  DeleteArray(buffer_);
3159  buffer_ = desc.buffer;
3160  buffer_size_ = desc.buffer_size;
3161  pc_ += pc_delta;
3162  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
3163                               reloc_info_writer.last_pc() + pc_delta);
3164
3165  // Relocate runtime entries.
3166  for (RelocIterator it(desc); !it.done(); it.next()) {
3167    RelocInfo::Mode rmode = it.rinfo()->rmode();
3168    if (rmode == RelocInfo::INTERNAL_REFERENCE) {
3169      byte* p = reinterpret_cast<byte*>(it.rinfo()->pc());
3170      RelocateInternalReference(rmode, p, pc_delta);
3171    }
3172  }
3173  DCHECK(!overflow());
3174}
3175
3176
3177void Assembler::db(uint8_t data) {
3178  CheckForEmitInForbiddenSlot();
3179  EmitHelper(data);
3180}
3181
3182
3183void Assembler::dd(uint32_t data) {
3184  CheckForEmitInForbiddenSlot();
3185  EmitHelper(data);
3186}
3187
3188
3189void Assembler::dq(uint64_t data) {
3190  CheckForEmitInForbiddenSlot();
3191  EmitHelper(data);
3192}
3193
3194
3195void Assembler::dd(Label* label) {
3196  uint64_t data;
3197  CheckForEmitInForbiddenSlot();
3198  if (label->is_bound()) {
3199    data = reinterpret_cast<uint64_t>(buffer_ + label->pos());
3200  } else {
3201    data = jump_address(label);
3202    internal_reference_positions_.insert(label->pos());
3203  }
3204  RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
3205  EmitHelper(data);
3206}
3207
3208
3209void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3210  // We do not try to reuse pool constants.
3211  RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
3212  if (rmode >= RelocInfo::COMMENT &&
3213      rmode <= RelocInfo::DEBUG_BREAK_SLOT_AT_CALL) {
3214    // Adjust code for new modes.
3215    DCHECK(RelocInfo::IsDebugBreakSlot(rmode)
3216           || RelocInfo::IsComment(rmode)
3217           || RelocInfo::IsPosition(rmode));
3218    // These modes do not need an entry in the constant pool.
3219  }
3220  if (!RelocInfo::IsNone(rinfo.rmode())) {
3221    // Don't record external references unless the heap will be serialized.
3222    if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
3223        !serializer_enabled() && !emit_debug_code()) {
3224      return;
3225    }
3226    DCHECK(buffer_space() >= kMaxRelocSize);  // Too late to grow buffer here.
3227    if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
3228      RelocInfo reloc_info_with_ast_id(isolate(), pc_, rmode,
3229                                       RecordedAstId().ToInt(), NULL);
3230      ClearRecordedAstId();
3231      reloc_info_writer.Write(&reloc_info_with_ast_id);
3232    } else {
3233      reloc_info_writer.Write(&rinfo);
3234    }
3235  }
3236}
3237
3238
3239void Assembler::BlockTrampolinePoolFor(int instructions) {
3240  CheckTrampolinePoolQuick(instructions);
3241  BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
3242}
3243
3244
3245void Assembler::CheckTrampolinePool() {
3246  // Some small sequences of instructions must not be broken up by the
3247  // insertion of a trampoline pool; such sequences are protected by setting
3248  // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
3249  // which are both checked here. Also, recursive calls to CheckTrampolinePool
3250  // are blocked by trampoline_pool_blocked_nesting_.
3251  if ((trampoline_pool_blocked_nesting_ > 0) ||
3252      (pc_offset() < no_trampoline_pool_before_)) {
3253    // Emission is currently blocked; make sure we try again as soon as
3254    // possible.
3255    if (trampoline_pool_blocked_nesting_ > 0) {
3256      next_buffer_check_ = pc_offset() + kInstrSize;
3257    } else {
3258      next_buffer_check_ = no_trampoline_pool_before_;
3259    }
3260    return;
3261  }
3262
3263  DCHECK(!trampoline_emitted_);
3264  DCHECK(unbound_labels_count_ >= 0);
3265  if (unbound_labels_count_ > 0) {
3266    // First we emit jump (2 instructions), then we emit trampoline pool.
3267    { BlockTrampolinePoolScope block_trampoline_pool(this);
3268      Label after_pool;
3269      if (kArchVariant == kMips64r6) {
3270        bc(&after_pool);
3271      } else {
3272        b(&after_pool);
3273        nop();
3274      }
3275
3276      EmitForbiddenSlotInstruction();
3277      int pool_start = pc_offset();
3278      for (int i = 0; i < unbound_labels_count_; i++) {
3279        { BlockGrowBufferScope block_buf_growth(this);
3280          // Buffer growth (and relocation) must be blocked for internal
3281          // references until associated instructions are emitted and available
3282          // to be patched.
3283          RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
3284          j(&after_pool);
3285        }
3286        nop();
3287      }
3288      bind(&after_pool);
3289      trampoline_ = Trampoline(pool_start, unbound_labels_count_);
3290
3291      trampoline_emitted_ = true;
3292      // As we are only going to emit trampoline once, we need to prevent any
3293      // further emission.
3294      next_buffer_check_ = kMaxInt;
3295    }
3296  } else {
3297    // Number of branches to unbound label at this point is zero, so we can
3298    // move next buffer check to maximum.
3299    next_buffer_check_ = pc_offset() +
3300        kMaxBranchOffset - kTrampolineSlotsSize * 16;
3301  }
3302  return;
3303}
3304
3305
3306Address Assembler::target_address_at(Address pc) {
3307  Instr instr0 = instr_at(pc);
3308  Instr instr1 = instr_at(pc + 1 * kInstrSize);
3309  Instr instr3 = instr_at(pc + 3 * kInstrSize);
3310
3311  // Interpret 4 instructions for address generated by li: See listing in
3312  // Assembler::set_target_address_at() just below.
3313  if ((GetOpcodeField(instr0) == LUI) && (GetOpcodeField(instr1) == ORI) &&
3314      (GetOpcodeField(instr3) == ORI)) {
3315    // Assemble the 48 bit value.
3316     int64_t addr  = static_cast<int64_t>(
3317          ((uint64_t)(GetImmediate16(instr0)) << 32) |
3318          ((uint64_t)(GetImmediate16(instr1)) << 16) |
3319          ((uint64_t)(GetImmediate16(instr3))));
3320
3321    // Sign extend to get canonical address.
3322    addr = (addr << 16) >> 16;
3323    return reinterpret_cast<Address>(addr);
3324  }
3325  // We should never get here, force a bad address if we do.
3326  UNREACHABLE();
3327  return (Address)0x0;
3328}
3329
3330
3331// MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32
3332// qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap
3333// snapshot generated on ia32, the resulting MIPS sNaN must be quieted.
3334// OS::nan_value() returns a qNaN.
3335void Assembler::QuietNaN(HeapObject* object) {
3336  HeapNumber::cast(object)->set_value(std::numeric_limits<double>::quiet_NaN());
3337}
3338
3339
3340// On Mips64, a target address is stored in a 4-instruction sequence:
3341//    0: lui(rd, (j.imm64_ >> 32) & kImm16Mask);
3342//    1: ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
3343//    2: dsll(rd, rd, 16);
3344//    3: ori(rd, rd, j.imm32_ & kImm16Mask);
3345//
3346// Patching the address must replace all the lui & ori instructions,
3347// and flush the i-cache.
3348//
3349// There is an optimization below, which emits a nop when the address
3350// fits in just 16 bits. This is unlikely to help, and should be benchmarked,
3351// and possibly removed.
3352void Assembler::set_target_address_at(Isolate* isolate, Address pc,
3353                                      Address target,
3354                                      ICacheFlushMode icache_flush_mode) {
3355// There is an optimization where only 4 instructions are used to load address
3356// in code on MIP64 because only 48-bits of address is effectively used.
3357// It relies on fact the upper [63:48] bits are not used for virtual address
3358// translation and they have to be set according to value of bit 47 in order
3359// get canonical address.
3360  Instr instr1 = instr_at(pc + kInstrSize);
3361  uint32_t rt_code = GetRt(instr1);
3362  uint32_t* p = reinterpret_cast<uint32_t*>(pc);
3363  uint64_t itarget = reinterpret_cast<uint64_t>(target);
3364
3365#ifdef DEBUG
3366  // Check we have the result from a li macro-instruction.
3367  Instr instr0 = instr_at(pc);
3368  Instr instr3 = instr_at(pc + kInstrSize * 3);
3369  CHECK((GetOpcodeField(instr0) == LUI && GetOpcodeField(instr1) == ORI &&
3370         GetOpcodeField(instr3) == ORI));
3371#endif
3372
3373  // Must use 4 instructions to insure patchable code.
3374  // lui rt, upper-16.
3375  // ori rt, rt, lower-16.
3376  // dsll rt, rt, 16.
3377  // ori rt rt, lower-16.
3378  *p = LUI | (rt_code << kRtShift) | ((itarget >> 32) & kImm16Mask);
3379  *(p + 1) = ORI | (rt_code << kRtShift) | (rt_code << kRsShift)
3380      | ((itarget >> 16) & kImm16Mask);
3381  *(p + 3) = ORI | (rt_code << kRsShift) | (rt_code << kRtShift)
3382      | (itarget & kImm16Mask);
3383
3384  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
3385    Assembler::FlushICache(isolate, pc, 4 * Assembler::kInstrSize);
3386  }
3387}
3388
3389
3390}  // namespace internal
3391}  // namespace v8
3392
3393#endif  // V8_TARGET_ARCH_MIPS64
3394