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