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