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