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