Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / src / mips / assembler-mips.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_MIPS
39
40 #include "src/base/cpu.h"
41 #include "src/mips/assembler-mips-inl.h"
42 #include "src/serialize.h"
43
44 namespace v8 {
45 namespace internal {
46
47 // Get the CPU features enabled by the build. For cross compilation the
48 // preprocessor symbols CAN_USE_FPU_INSTRUCTIONS
49 // can be defined to enable FPU instructions when building the
50 // snapshot.
51 static unsigned CpuFeaturesImpliedByCompiler() {
52   unsigned answer = 0;
53 #ifdef CAN_USE_FPU_INSTRUCTIONS
54   answer |= 1u << FPU;
55 #endif  // def CAN_USE_FPU_INSTRUCTIONS
56
57   // If the compiler is allowed to use FPU then we can use FPU too in our code
58   // generation even when generating snapshots.  This won't work for cross
59   // compilation.
60 #if defined(__mips__) && defined(__mips_hard_float) && __mips_hard_float != 0
61   answer |= 1u << FPU;
62 #endif
63
64   return answer;
65 }
66
67
68 const char* DoubleRegister::AllocationIndexToString(int index) {
69   DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
70   const char* const names[] = {
71     "f0",
72     "f2",
73     "f4",
74     "f6",
75     "f8",
76     "f10",
77     "f12",
78     "f14",
79     "f16",
80     "f18",
81     "f20",
82     "f22",
83     "f24",
84     "f26"
85   };
86   return names[index];
87 }
88
89
90 void CpuFeatures::ProbeImpl(bool cross_compile) {
91   supported_ |= CpuFeaturesImpliedByCompiler();
92
93   // Only use statically determined features for cross compile (snapshot).
94   if (cross_compile) return;
95
96   // If the compiler is allowed to use fpu then we can use fpu too in our
97   // code generation.
98 #ifndef __mips__
99   // For the simulator build, use FPU.
100   supported_ |= 1u << FPU;
101 #else
102   // Probe for additional features at runtime.
103   base::CPU cpu;
104   if (cpu.has_fpu()) supported_ |= 1u << FPU;
105 #endif
106 }
107
108
109 void CpuFeatures::PrintTarget() { }
110 void CpuFeatures::PrintFeatures() { }
111
112
113 int ToNumber(Register reg) {
114   DCHECK(reg.is_valid());
115   const int kNumbers[] = {
116     0,    // zero_reg
117     1,    // at
118     2,    // v0
119     3,    // v1
120     4,    // a0
121     5,    // a1
122     6,    // a2
123     7,    // a3
124     8,    // t0
125     9,    // t1
126     10,   // t2
127     11,   // t3
128     12,   // t4
129     13,   // t5
130     14,   // t6
131     15,   // t7
132     16,   // s0
133     17,   // s1
134     18,   // s2
135     19,   // s3
136     20,   // s4
137     21,   // s5
138     22,   // s6
139     23,   // s7
140     24,   // t8
141     25,   // t9
142     26,   // k0
143     27,   // k1
144     28,   // gp
145     29,   // sp
146     30,   // fp
147     31,   // ra
148   };
149   return kNumbers[reg.code()];
150 }
151
152
153 Register ToRegister(int num) {
154   DCHECK(num >= 0 && num < kNumRegisters);
155   const Register kRegisters[] = {
156     zero_reg,
157     at,
158     v0, v1,
159     a0, a1, a2, a3,
160     t0, t1, t2, t3, t4, t5, t6, t7,
161     s0, s1, s2, s3, s4, s5, s6, s7,
162     t8, t9,
163     k0, k1,
164     gp,
165     sp,
166     fp,
167     ra
168   };
169   return kRegisters[num];
170 }
171
172
173 // -----------------------------------------------------------------------------
174 // Implementation of RelocInfo.
175
176 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
177                                   1 << RelocInfo::INTERNAL_REFERENCE;
178
179
180 bool RelocInfo::IsCodedSpecially() {
181   // The deserializer needs to know whether a pointer is specially coded.  Being
182   // specially coded on MIPS means that it is a lui/ori instruction, and that is
183   // always the case inside code objects.
184   return true;
185 }
186
187
188 bool RelocInfo::IsInConstantPool() {
189   return false;
190 }
191
192
193 // Patch the code at the current address with the supplied instructions.
194 void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
195   Instr* pc = reinterpret_cast<Instr*>(pc_);
196   Instr* instr = reinterpret_cast<Instr*>(instructions);
197   for (int i = 0; i < instruction_count; i++) {
198     *(pc + i) = *(instr + i);
199   }
200
201   // Indicate that code has changed.
202   CpuFeatures::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
203 }
204
205
206 // Patch the code at the current PC with a call to the target address.
207 // Additional guard instructions can be added if required.
208 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
209   // Patch the code at the current address with a call to the target.
210   UNIMPLEMENTED_MIPS();
211 }
212
213
214 // -----------------------------------------------------------------------------
215 // Implementation of Operand and MemOperand.
216 // See assembler-mips-inl.h for inlined constructors.
217
218 Operand::Operand(Handle<Object> handle) {
219   AllowDeferredHandleDereference using_raw_address;
220   rm_ = no_reg;
221   // Verify all Objects referred by code are NOT in new space.
222   Object* obj = *handle;
223   if (obj->IsHeapObject()) {
224     DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
225     imm32_ = reinterpret_cast<intptr_t>(handle.location());
226     rmode_ = RelocInfo::EMBEDDED_OBJECT;
227   } else {
228     // No relocation needed.
229     imm32_ = reinterpret_cast<intptr_t>(obj);
230     rmode_ = RelocInfo::NONE32;
231   }
232 }
233
234
235 MemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) {
236   offset_ = offset;
237 }
238
239
240 MemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier,
241                        OffsetAddend offset_addend) : Operand(rm) {
242   offset_ = unit * multiplier + offset_addend;
243 }
244
245
246 // -----------------------------------------------------------------------------
247 // Specific instructions, constants, and masks.
248
249 static const int kNegOffset = 0x00008000;
250 // addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
251 // operations as post-increment of sp.
252 const Instr kPopInstruction = ADDIU | (kRegister_sp_Code << kRsShift)
253       | (kRegister_sp_Code << kRtShift)
254       | (kPointerSize & kImm16Mask);  // NOLINT
255 // addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
256 const Instr kPushInstruction = ADDIU | (kRegister_sp_Code << kRsShift)
257       | (kRegister_sp_Code << kRtShift)
258       | (-kPointerSize & kImm16Mask);  // NOLINT
259 // sw(r, MemOperand(sp, 0))
260 const Instr kPushRegPattern = SW | (kRegister_sp_Code << kRsShift)
261       | (0 & kImm16Mask);  // NOLINT
262 //  lw(r, MemOperand(sp, 0))
263 const Instr kPopRegPattern = LW | (kRegister_sp_Code << kRsShift)
264       | (0 & kImm16Mask);  // NOLINT
265
266 const Instr kLwRegFpOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
267       | (0 & kImm16Mask);  // NOLINT
268
269 const Instr kSwRegFpOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
270       | (0 & kImm16Mask);  // NOLINT
271
272 const Instr kLwRegFpNegOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
273       | (kNegOffset & kImm16Mask);  // NOLINT
274
275 const Instr kSwRegFpNegOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
276       | (kNegOffset & kImm16Mask);  // NOLINT
277 // A mask for the Rt register for push, pop, lw, sw instructions.
278 const Instr kRtMask = kRtFieldMask;
279 const Instr kLwSwInstrTypeMask = 0xffe00000;
280 const Instr kLwSwInstrArgumentMask  = ~kLwSwInstrTypeMask;
281 const Instr kLwSwOffsetMask = kImm16Mask;
282
283
284 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
285     : AssemblerBase(isolate, buffer, buffer_size),
286       recorded_ast_id_(TypeFeedbackId::None()),
287       positions_recorder_(this) {
288   reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
289
290   last_trampoline_pool_end_ = 0;
291   no_trampoline_pool_before_ = 0;
292   trampoline_pool_blocked_nesting_ = 0;
293   // We leave space (16 * kTrampolineSlotsSize)
294   // for BlockTrampolinePoolScope buffer.
295   next_buffer_check_ = FLAG_force_long_branches
296       ? kMaxInt : kMaxBranchOffset - kTrampolineSlotsSize * 16;
297   internal_trampoline_exception_ = false;
298   last_bound_pos_ = 0;
299
300   trampoline_emitted_ = FLAG_force_long_branches;
301   unbound_labels_count_ = 0;
302   block_buffer_growth_ = false;
303
304   ClearRecordedAstId();
305 }
306
307
308 void Assembler::GetCode(CodeDesc* desc) {
309   DCHECK(pc_ <= reloc_info_writer.pos());  // No overlap.
310   // Set up code descriptor.
311   desc->buffer = buffer_;
312   desc->buffer_size = buffer_size_;
313   desc->instr_size = pc_offset();
314   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
315   desc->origin = this;
316 }
317
318
319 void Assembler::Align(int m) {
320   DCHECK(m >= 4 && IsPowerOf2(m));
321   while ((pc_offset() & (m - 1)) != 0) {
322     nop();
323   }
324 }
325
326
327 void Assembler::CodeTargetAlign() {
328   // No advantage to aligning branch/call targets to more than
329   // single instruction, that I am aware of.
330   Align(4);
331 }
332
333
334 Register Assembler::GetRtReg(Instr instr) {
335   Register rt;
336   rt.code_ = (instr & kRtFieldMask) >> kRtShift;
337   return rt;
338 }
339
340
341 Register Assembler::GetRsReg(Instr instr) {
342   Register rs;
343   rs.code_ = (instr & kRsFieldMask) >> kRsShift;
344   return rs;
345 }
346
347
348 Register Assembler::GetRdReg(Instr instr) {
349   Register rd;
350   rd.code_ = (instr & kRdFieldMask) >> kRdShift;
351   return rd;
352 }
353
354
355 uint32_t Assembler::GetRt(Instr instr) {
356   return (instr & kRtFieldMask) >> kRtShift;
357 }
358
359
360 uint32_t Assembler::GetRtField(Instr instr) {
361   return instr & kRtFieldMask;
362 }
363
364
365 uint32_t Assembler::GetRs(Instr instr) {
366   return (instr & kRsFieldMask) >> kRsShift;
367 }
368
369
370 uint32_t Assembler::GetRsField(Instr instr) {
371   return instr & kRsFieldMask;
372 }
373
374
375 uint32_t Assembler::GetRd(Instr instr) {
376   return  (instr & kRdFieldMask) >> kRdShift;
377 }
378
379
380 uint32_t Assembler::GetRdField(Instr instr) {
381   return  instr & kRdFieldMask;
382 }
383
384
385 uint32_t Assembler::GetSa(Instr instr) {
386   return (instr & kSaFieldMask) >> kSaShift;
387 }
388
389
390 uint32_t Assembler::GetSaField(Instr instr) {
391   return instr & kSaFieldMask;
392 }
393
394
395 uint32_t Assembler::GetOpcodeField(Instr instr) {
396   return instr & kOpcodeMask;
397 }
398
399
400 uint32_t Assembler::GetFunction(Instr instr) {
401   return (instr & kFunctionFieldMask) >> kFunctionShift;
402 }
403
404
405 uint32_t Assembler::GetFunctionField(Instr instr) {
406   return instr & kFunctionFieldMask;
407 }
408
409
410 uint32_t Assembler::GetImmediate16(Instr instr) {
411   return instr & kImm16Mask;
412 }
413
414
415 uint32_t Assembler::GetLabelConst(Instr instr) {
416   return instr & ~kImm16Mask;
417 }
418
419
420 bool Assembler::IsPop(Instr instr) {
421   return (instr & ~kRtMask) == kPopRegPattern;
422 }
423
424
425 bool Assembler::IsPush(Instr instr) {
426   return (instr & ~kRtMask) == kPushRegPattern;
427 }
428
429
430 bool Assembler::IsSwRegFpOffset(Instr instr) {
431   return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern);
432 }
433
434
435 bool Assembler::IsLwRegFpOffset(Instr instr) {
436   return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern);
437 }
438
439
440 bool Assembler::IsSwRegFpNegOffset(Instr instr) {
441   return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
442           kSwRegFpNegOffsetPattern);
443 }
444
445
446 bool Assembler::IsLwRegFpNegOffset(Instr instr) {
447   return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
448           kLwRegFpNegOffsetPattern);
449 }
450
451
452 // Labels refer to positions in the (to be) generated code.
453 // There are bound, linked, and unused labels.
454 //
455 // Bound labels refer to known positions in the already
456 // generated code. pos() is the position the label refers to.
457 //
458 // Linked labels refer to unknown positions in the code
459 // to be generated; pos() is the position of the last
460 // instruction using the label.
461
462 // The link chain is terminated by a value in the instruction of -1,
463 // which is an otherwise illegal value (branch -1 is inf loop).
464 // The instruction 16-bit offset field addresses 32-bit words, but in
465 // code is conv to an 18-bit value addressing bytes, hence the -4 value.
466
467 const int kEndOfChain = -4;
468 // Determines the end of the Jump chain (a subset of the label link chain).
469 const int kEndOfJumpChain = 0;
470
471
472 bool Assembler::IsBranch(Instr instr) {
473   uint32_t opcode   = GetOpcodeField(instr);
474   uint32_t rt_field = GetRtField(instr);
475   uint32_t rs_field = GetRsField(instr);
476   // Checks if the instruction is a branch.
477   return opcode == BEQ ||
478       opcode == BNE ||
479       opcode == BLEZ ||
480       opcode == BGTZ ||
481       opcode == BEQL ||
482       opcode == BNEL ||
483       opcode == BLEZL ||
484       opcode == BGTZL ||
485       (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
486                             rt_field == BLTZAL || rt_field == BGEZAL)) ||
487       (opcode == COP1 && rs_field == BC1);  // Coprocessor branch.
488 }
489
490
491 bool Assembler::IsEmittedConstant(Instr instr) {
492   uint32_t label_constant = GetLabelConst(instr);
493   return label_constant == 0;  // Emitted label const in reg-exp engine.
494 }
495
496
497 bool Assembler::IsBeq(Instr instr) {
498   return GetOpcodeField(instr) == BEQ;
499 }
500
501
502 bool Assembler::IsBne(Instr instr) {
503   return GetOpcodeField(instr) == BNE;
504 }
505
506
507 bool Assembler::IsJump(Instr instr) {
508   uint32_t opcode   = GetOpcodeField(instr);
509   uint32_t rt_field = GetRtField(instr);
510   uint32_t rd_field = GetRdField(instr);
511   uint32_t function_field = GetFunctionField(instr);
512   // Checks if the instruction is a jump.
513   return opcode == J || opcode == JAL ||
514       (opcode == SPECIAL && rt_field == 0 &&
515       ((function_field == JALR) || (rd_field == 0 && (function_field == JR))));
516 }
517
518
519 bool Assembler::IsJ(Instr instr) {
520   uint32_t opcode = GetOpcodeField(instr);
521   // Checks if the instruction is a jump.
522   return opcode == J;
523 }
524
525
526 bool Assembler::IsJal(Instr instr) {
527   return GetOpcodeField(instr) == JAL;
528 }
529
530
531 bool Assembler::IsJr(Instr instr) {
532   return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR;
533 }
534
535
536 bool Assembler::IsJalr(Instr instr) {
537   return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JALR;
538 }
539
540
541 bool Assembler::IsLui(Instr instr) {
542   uint32_t opcode = GetOpcodeField(instr);
543   // Checks if the instruction is a load upper immediate.
544   return opcode == LUI;
545 }
546
547
548 bool Assembler::IsOri(Instr instr) {
549   uint32_t opcode = GetOpcodeField(instr);
550   // Checks if the instruction is a load upper immediate.
551   return opcode == ORI;
552 }
553
554
555 bool Assembler::IsNop(Instr instr, unsigned int type) {
556   // See Assembler::nop(type).
557   DCHECK(type < 32);
558   uint32_t opcode = GetOpcodeField(instr);
559   uint32_t function = GetFunctionField(instr);
560   uint32_t rt = GetRt(instr);
561   uint32_t rd = GetRd(instr);
562   uint32_t sa = GetSa(instr);
563
564   // Traditional mips nop == sll(zero_reg, zero_reg, 0)
565   // When marking non-zero type, use sll(zero_reg, at, type)
566   // to avoid use of mips ssnop and ehb special encodings
567   // of the sll instruction.
568
569   Register nop_rt_reg = (type == 0) ? zero_reg : at;
570   bool ret = (opcode == SPECIAL && function == SLL &&
571               rd == static_cast<uint32_t>(ToNumber(zero_reg)) &&
572               rt == static_cast<uint32_t>(ToNumber(nop_rt_reg)) &&
573               sa == type);
574
575   return ret;
576 }
577
578
579 int32_t Assembler::GetBranchOffset(Instr instr) {
580   DCHECK(IsBranch(instr));
581   return (static_cast<int16_t>(instr & kImm16Mask)) << 2;
582 }
583
584
585 bool Assembler::IsLw(Instr instr) {
586   return ((instr & kOpcodeMask) == LW);
587 }
588
589
590 int16_t Assembler::GetLwOffset(Instr instr) {
591   DCHECK(IsLw(instr));
592   return ((instr & kImm16Mask));
593 }
594
595
596 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) {
597   DCHECK(IsLw(instr));
598
599   // We actually create a new lw instruction based on the original one.
600   Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask)
601       | (offset & kImm16Mask);
602
603   return temp_instr;
604 }
605
606
607 bool Assembler::IsSw(Instr instr) {
608   return ((instr & kOpcodeMask) == SW);
609 }
610
611
612 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) {
613   DCHECK(IsSw(instr));
614   return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
615 }
616
617
618 bool Assembler::IsAddImmediate(Instr instr) {
619   return ((instr & kOpcodeMask) == ADDIU);
620 }
621
622
623 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
624   DCHECK(IsAddImmediate(instr));
625   return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
626 }
627
628
629 bool Assembler::IsAndImmediate(Instr instr) {
630   return GetOpcodeField(instr) == ANDI;
631 }
632
633
634 int Assembler::target_at(int32_t pos) {
635   Instr instr = instr_at(pos);
636   if ((instr & ~kImm16Mask) == 0) {
637     // Emitted label constant, not part of a branch.
638     if (instr == 0) {
639        return kEndOfChain;
640      } else {
641        int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
642        return (imm18 + pos);
643      }
644   }
645   // Check we have a branch or jump instruction.
646   DCHECK(IsBranch(instr) || IsJ(instr) || IsLui(instr));
647   // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
648   // the compiler uses arithmectic shifts for signed integers.
649   if (IsBranch(instr)) {
650     int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
651
652     if (imm18 == kEndOfChain) {
653       // EndOfChain sentinel is returned directly, not relative to pc or pos.
654       return kEndOfChain;
655     } else {
656       return pos + kBranchPCOffset + imm18;
657     }
658   } else if (IsLui(instr)) {
659     Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
660     Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
661     DCHECK(IsOri(instr_ori));
662     int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
663     imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
664
665     if (imm == kEndOfJumpChain) {
666       // EndOfChain sentinel is returned directly, not relative to pc or pos.
667       return kEndOfChain;
668     } else {
669       uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
670       int32_t delta = instr_address - imm;
671       DCHECK(pos > delta);
672       return pos - delta;
673     }
674   } else {
675     int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
676     if (imm28 == kEndOfJumpChain) {
677       // EndOfChain sentinel is returned directly, not relative to pc or pos.
678       return kEndOfChain;
679     } else {
680       uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
681       instr_address &= kImm28Mask;
682       int32_t delta = instr_address - imm28;
683       DCHECK(pos > delta);
684       return pos - delta;
685     }
686   }
687 }
688
689
690 void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
691   Instr instr = instr_at(pos);
692   if ((instr & ~kImm16Mask) == 0) {
693     DCHECK(target_pos == kEndOfChain || target_pos >= 0);
694     // Emitted label constant, not part of a branch.
695     // Make label relative to Code* of generated Code object.
696     instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
697     return;
698   }
699
700   DCHECK(IsBranch(instr) || IsJ(instr) || IsLui(instr));
701   if (IsBranch(instr)) {
702     int32_t imm18 = target_pos - (pos + kBranchPCOffset);
703     DCHECK((imm18 & 3) == 0);
704
705     instr &= ~kImm16Mask;
706     int32_t imm16 = imm18 >> 2;
707     DCHECK(is_int16(imm16));
708
709     instr_at_put(pos, instr | (imm16 & kImm16Mask));
710   } else if (IsLui(instr)) {
711     Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
712     Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
713     DCHECK(IsOri(instr_ori));
714     uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
715     DCHECK((imm & 3) == 0);
716
717     instr_lui &= ~kImm16Mask;
718     instr_ori &= ~kImm16Mask;
719
720     instr_at_put(pos + 0 * Assembler::kInstrSize,
721                  instr_lui | ((imm & kHiMask) >> kLuiShift));
722     instr_at_put(pos + 1 * Assembler::kInstrSize,
723                  instr_ori | (imm & kImm16Mask));
724   } else {
725     uint32_t imm28 = reinterpret_cast<uint32_t>(buffer_) + target_pos;
726     imm28 &= kImm28Mask;
727     DCHECK((imm28 & 3) == 0);
728
729     instr &= ~kImm26Mask;
730     uint32_t imm26 = imm28 >> 2;
731     DCHECK(is_uint26(imm26));
732
733     instr_at_put(pos, instr | (imm26 & kImm26Mask));
734   }
735 }
736
737
738 void Assembler::print(Label* L) {
739   if (L->is_unused()) {
740     PrintF("unused label\n");
741   } else if (L->is_bound()) {
742     PrintF("bound label to %d\n", L->pos());
743   } else if (L->is_linked()) {
744     Label l = *L;
745     PrintF("unbound label");
746     while (l.is_linked()) {
747       PrintF("@ %d ", l.pos());
748       Instr instr = instr_at(l.pos());
749       if ((instr & ~kImm16Mask) == 0) {
750         PrintF("value\n");
751       } else {
752         PrintF("%d\n", instr);
753       }
754       next(&l);
755     }
756   } else {
757     PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
758   }
759 }
760
761
762 void Assembler::bind_to(Label* L, int pos) {
763   DCHECK(0 <= pos && pos <= pc_offset());  // Must have valid binding position.
764   int32_t trampoline_pos = kInvalidSlotPos;
765   if (L->is_linked() && !trampoline_emitted_) {
766     unbound_labels_count_--;
767     next_buffer_check_ += kTrampolineSlotsSize;
768   }
769
770   while (L->is_linked()) {
771     int32_t fixup_pos = L->pos();
772     int32_t dist = pos - fixup_pos;
773     next(L);  // Call next before overwriting link with target at fixup_pos.
774     Instr instr = instr_at(fixup_pos);
775     if (IsBranch(instr)) {
776       if (dist > kMaxBranchOffset) {
777         if (trampoline_pos == kInvalidSlotPos) {
778           trampoline_pos = get_trampoline_entry(fixup_pos);
779           CHECK(trampoline_pos != kInvalidSlotPos);
780         }
781         DCHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
782         target_at_put(fixup_pos, trampoline_pos);
783         fixup_pos = trampoline_pos;
784         dist = pos - fixup_pos;
785       }
786       target_at_put(fixup_pos, pos);
787     } else {
788       DCHECK(IsJ(instr) || IsLui(instr) || IsEmittedConstant(instr));
789       target_at_put(fixup_pos, pos);
790     }
791   }
792   L->bind_to(pos);
793
794   // Keep track of the last bound label so we don't eliminate any instructions
795   // before a bound label.
796   if (pos > last_bound_pos_)
797     last_bound_pos_ = pos;
798 }
799
800
801 void Assembler::bind(Label* L) {
802   DCHECK(!L->is_bound());  // Label can only be bound once.
803   bind_to(L, pc_offset());
804 }
805
806
807 void Assembler::next(Label* L) {
808   DCHECK(L->is_linked());
809   int link = target_at(L->pos());
810   if (link == kEndOfChain) {
811     L->Unuse();
812   } else {
813     DCHECK(link >= 0);
814     L->link_to(link);
815   }
816 }
817
818
819 bool Assembler::is_near(Label* L) {
820   if (L->is_bound()) {
821     return ((pc_offset() - L->pos()) < kMaxBranchOffset - 4 * kInstrSize);
822   }
823   return false;
824 }
825
826
827 // We have to use a temporary register for things that can be relocated even
828 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
829 // space.  There is no guarantee that the relocated location can be similarly
830 // encoded.
831 bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
832   return !RelocInfo::IsNone(rmode);
833 }
834
835 void Assembler::GenInstrRegister(Opcode opcode,
836                                  Register rs,
837                                  Register rt,
838                                  Register rd,
839                                  uint16_t sa,
840                                  SecondaryField func) {
841   DCHECK(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
842   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
843       | (rd.code() << kRdShift) | (sa << kSaShift) | func;
844   emit(instr);
845 }
846
847
848 void Assembler::GenInstrRegister(Opcode opcode,
849                                  Register rs,
850                                  Register rt,
851                                  uint16_t msb,
852                                  uint16_t lsb,
853                                  SecondaryField func) {
854   DCHECK(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb));
855   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
856       | (msb << kRdShift) | (lsb << kSaShift) | func;
857   emit(instr);
858 }
859
860
861 void Assembler::GenInstrRegister(Opcode opcode,
862                                  SecondaryField fmt,
863                                  FPURegister ft,
864                                  FPURegister fs,
865                                  FPURegister fd,
866                                  SecondaryField func) {
867   DCHECK(fd.is_valid() && fs.is_valid() && ft.is_valid());
868   Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
869       | (fd.code() << kFdShift) | func;
870   emit(instr);
871 }
872
873
874 void Assembler::GenInstrRegister(Opcode opcode,
875                                  FPURegister fr,
876                                  FPURegister ft,
877                                  FPURegister fs,
878                                  FPURegister fd,
879                                  SecondaryField func) {
880   DCHECK(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid());
881   Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift)
882       | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
883   emit(instr);
884 }
885
886
887 void Assembler::GenInstrRegister(Opcode opcode,
888                                  SecondaryField fmt,
889                                  Register rt,
890                                  FPURegister fs,
891                                  FPURegister fd,
892                                  SecondaryField func) {
893   DCHECK(fd.is_valid() && fs.is_valid() && rt.is_valid());
894   Instr instr = opcode | fmt | (rt.code() << kRtShift)
895       | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
896   emit(instr);
897 }
898
899
900 void Assembler::GenInstrRegister(Opcode opcode,
901                                  SecondaryField fmt,
902                                  Register rt,
903                                  FPUControlRegister fs,
904                                  SecondaryField func) {
905   DCHECK(fs.is_valid() && rt.is_valid());
906   Instr instr =
907       opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
908   emit(instr);
909 }
910
911
912 // Instructions with immediate value.
913 // Registers are in the order of the instruction encoding, from left to right.
914 void Assembler::GenInstrImmediate(Opcode opcode,
915                                   Register rs,
916                                   Register rt,
917                                   int32_t j) {
918   DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
919   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
920       | (j & kImm16Mask);
921   emit(instr);
922 }
923
924
925 void Assembler::GenInstrImmediate(Opcode opcode,
926                                   Register rs,
927                                   SecondaryField SF,
928                                   int32_t j) {
929   DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j)));
930   Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
931   emit(instr);
932 }
933
934
935 void Assembler::GenInstrImmediate(Opcode opcode,
936                                   Register rs,
937                                   FPURegister ft,
938                                   int32_t j) {
939   DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
940   Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
941       | (j & kImm16Mask);
942   emit(instr);
943 }
944
945
946 void Assembler::GenInstrJump(Opcode opcode,
947                              uint32_t address) {
948   BlockTrampolinePoolScope block_trampoline_pool(this);
949   DCHECK(is_uint26(address));
950   Instr instr = opcode | address;
951   emit(instr);
952   BlockTrampolinePoolFor(1);  // For associated delay slot.
953 }
954
955
956 // Returns the next free trampoline entry.
957 int32_t Assembler::get_trampoline_entry(int32_t pos) {
958   int32_t trampoline_entry = kInvalidSlotPos;
959
960   if (!internal_trampoline_exception_) {
961     if (trampoline_.start() > pos) {
962      trampoline_entry = trampoline_.take_slot();
963     }
964
965     if (kInvalidSlotPos == trampoline_entry) {
966       internal_trampoline_exception_ = true;
967     }
968   }
969   return trampoline_entry;
970 }
971
972
973 uint32_t Assembler::jump_address(Label* L) {
974   int32_t target_pos;
975
976   if (L->is_bound()) {
977     target_pos = L->pos();
978   } else {
979     if (L->is_linked()) {
980       target_pos = L->pos();  // L's link.
981       L->link_to(pc_offset());
982     } else {
983       L->link_to(pc_offset());
984       return kEndOfJumpChain;
985     }
986   }
987
988   uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
989   DCHECK((imm & 3) == 0);
990
991   return imm;
992 }
993
994
995 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
996   int32_t target_pos;
997
998   if (L->is_bound()) {
999     target_pos = L->pos();
1000   } else {
1001     if (L->is_linked()) {
1002       target_pos = L->pos();
1003       L->link_to(pc_offset());
1004     } else {
1005       L->link_to(pc_offset());
1006       if (!trampoline_emitted_) {
1007         unbound_labels_count_++;
1008         next_buffer_check_ -= kTrampolineSlotsSize;
1009       }
1010       return kEndOfChain;
1011     }
1012   }
1013
1014   int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
1015   DCHECK((offset & 3) == 0);
1016   DCHECK(is_int16(offset >> 2));
1017
1018   return offset;
1019 }
1020
1021
1022 void Assembler::label_at_put(Label* L, int at_offset) {
1023   int target_pos;
1024   if (L->is_bound()) {
1025     target_pos = L->pos();
1026     instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
1027   } else {
1028     if (L->is_linked()) {
1029       target_pos = L->pos();  // L's link.
1030       int32_t imm18 = target_pos - at_offset;
1031       DCHECK((imm18 & 3) == 0);
1032       int32_t imm16 = imm18 >> 2;
1033       DCHECK(is_int16(imm16));
1034       instr_at_put(at_offset, (imm16 & kImm16Mask));
1035     } else {
1036       target_pos = kEndOfChain;
1037       instr_at_put(at_offset, 0);
1038       if (!trampoline_emitted_) {
1039         unbound_labels_count_++;
1040         next_buffer_check_ -= kTrampolineSlotsSize;
1041       }
1042     }
1043     L->link_to(at_offset);
1044   }
1045 }
1046
1047
1048 //------- Branch and jump instructions --------
1049
1050 void Assembler::b(int16_t offset) {
1051   beq(zero_reg, zero_reg, offset);
1052 }
1053
1054
1055 void Assembler::bal(int16_t offset) {
1056   positions_recorder()->WriteRecordedPositions();
1057   bgezal(zero_reg, offset);
1058 }
1059
1060
1061 void Assembler::beq(Register rs, Register rt, int16_t offset) {
1062   BlockTrampolinePoolScope block_trampoline_pool(this);
1063   GenInstrImmediate(BEQ, rs, rt, offset);
1064   BlockTrampolinePoolFor(1);  // For associated delay slot.
1065 }
1066
1067
1068 void Assembler::bgez(Register rs, int16_t offset) {
1069   BlockTrampolinePoolScope block_trampoline_pool(this);
1070   GenInstrImmediate(REGIMM, rs, BGEZ, offset);
1071   BlockTrampolinePoolFor(1);  // For associated delay slot.
1072 }
1073
1074
1075 void Assembler::bgezal(Register rs, int16_t offset) {
1076   BlockTrampolinePoolScope block_trampoline_pool(this);
1077   positions_recorder()->WriteRecordedPositions();
1078   GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
1079   BlockTrampolinePoolFor(1);  // For associated delay slot.
1080 }
1081
1082
1083 void Assembler::bgtz(Register rs, int16_t offset) {
1084   BlockTrampolinePoolScope block_trampoline_pool(this);
1085   GenInstrImmediate(BGTZ, rs, zero_reg, offset);
1086   BlockTrampolinePoolFor(1);  // For associated delay slot.
1087 }
1088
1089
1090 void Assembler::blez(Register rs, int16_t offset) {
1091   BlockTrampolinePoolScope block_trampoline_pool(this);
1092   GenInstrImmediate(BLEZ, rs, zero_reg, offset);
1093   BlockTrampolinePoolFor(1);  // For associated delay slot.
1094 }
1095
1096
1097 void Assembler::bltz(Register rs, int16_t offset) {
1098   BlockTrampolinePoolScope block_trampoline_pool(this);
1099   GenInstrImmediate(REGIMM, rs, BLTZ, offset);
1100   BlockTrampolinePoolFor(1);  // For associated delay slot.
1101 }
1102
1103
1104 void Assembler::bltzal(Register rs, int16_t offset) {
1105   BlockTrampolinePoolScope block_trampoline_pool(this);
1106   positions_recorder()->WriteRecordedPositions();
1107   GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
1108   BlockTrampolinePoolFor(1);  // For associated delay slot.
1109 }
1110
1111
1112 void Assembler::bne(Register rs, Register rt, int16_t offset) {
1113   BlockTrampolinePoolScope block_trampoline_pool(this);
1114   GenInstrImmediate(BNE, rs, rt, offset);
1115   BlockTrampolinePoolFor(1);  // For associated delay slot.
1116 }
1117
1118
1119 void Assembler::j(int32_t target) {
1120 #if DEBUG
1121   // Get pc of delay slot.
1122   uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
1123   bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
1124                   (kImm26Bits + kImmFieldShift)) == 0;
1125   DCHECK(in_range && ((target & 3) == 0));
1126 #endif
1127   GenInstrJump(J, target >> 2);
1128 }
1129
1130
1131 void Assembler::jr(Register rs) {
1132   BlockTrampolinePoolScope block_trampoline_pool(this);
1133   if (rs.is(ra)) {
1134     positions_recorder()->WriteRecordedPositions();
1135   }
1136   GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
1137   BlockTrampolinePoolFor(1);  // For associated delay slot.
1138 }
1139
1140
1141 void Assembler::jal(int32_t target) {
1142 #ifdef DEBUG
1143   // Get pc of delay slot.
1144   uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
1145   bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
1146                   (kImm26Bits + kImmFieldShift)) == 0;
1147   DCHECK(in_range && ((target & 3) == 0));
1148 #endif
1149   positions_recorder()->WriteRecordedPositions();
1150   GenInstrJump(JAL, target >> 2);
1151 }
1152
1153
1154 void Assembler::jalr(Register rs, Register rd) {
1155   BlockTrampolinePoolScope block_trampoline_pool(this);
1156   positions_recorder()->WriteRecordedPositions();
1157   GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
1158   BlockTrampolinePoolFor(1);  // For associated delay slot.
1159 }
1160
1161
1162 void Assembler::j_or_jr(int32_t target, Register rs) {
1163   // Get pc of delay slot.
1164   uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
1165   bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
1166                   (kImm26Bits + kImmFieldShift)) == 0;
1167   if (in_range) {
1168       j(target);
1169   } else {
1170       jr(t9);
1171   }
1172 }
1173
1174
1175 void Assembler::jal_or_jalr(int32_t target, Register rs) {
1176   // Get pc of delay slot.
1177   uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
1178   bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
1179                   (kImm26Bits+kImmFieldShift)) == 0;
1180   if (in_range) {
1181       jal(target);
1182   } else {
1183       jalr(t9);
1184   }
1185 }
1186
1187
1188 // -------Data-processing-instructions---------
1189
1190 // Arithmetic.
1191
1192 void Assembler::addu(Register rd, Register rs, Register rt) {
1193   GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
1194 }
1195
1196
1197 void Assembler::addiu(Register rd, Register rs, int32_t j) {
1198   GenInstrImmediate(ADDIU, rs, rd, j);
1199 }
1200
1201
1202 void Assembler::subu(Register rd, Register rs, Register rt) {
1203   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
1204 }
1205
1206
1207 void Assembler::mul(Register rd, Register rs, Register rt) {
1208   GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
1209 }
1210
1211
1212 void Assembler::mult(Register rs, Register rt) {
1213   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
1214 }
1215
1216
1217 void Assembler::multu(Register rs, Register rt) {
1218   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
1219 }
1220
1221
1222 void Assembler::div(Register rs, Register rt) {
1223   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
1224 }
1225
1226
1227 void Assembler::divu(Register rs, Register rt) {
1228   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
1229 }
1230
1231
1232 // Logical.
1233
1234 void Assembler::and_(Register rd, Register rs, Register rt) {
1235   GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
1236 }
1237
1238
1239 void Assembler::andi(Register rt, Register rs, int32_t j) {
1240   DCHECK(is_uint16(j));
1241   GenInstrImmediate(ANDI, rs, rt, j);
1242 }
1243
1244
1245 void Assembler::or_(Register rd, Register rs, Register rt) {
1246   GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
1247 }
1248
1249
1250 void Assembler::ori(Register rt, Register rs, int32_t j) {
1251   DCHECK(is_uint16(j));
1252   GenInstrImmediate(ORI, rs, rt, j);
1253 }
1254
1255
1256 void Assembler::xor_(Register rd, Register rs, Register rt) {
1257   GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
1258 }
1259
1260
1261 void Assembler::xori(Register rt, Register rs, int32_t j) {
1262   DCHECK(is_uint16(j));
1263   GenInstrImmediate(XORI, rs, rt, j);
1264 }
1265
1266
1267 void Assembler::nor(Register rd, Register rs, Register rt) {
1268   GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
1269 }
1270
1271
1272 // Shifts.
1273 void Assembler::sll(Register rd,
1274                     Register rt,
1275                     uint16_t sa,
1276                     bool coming_from_nop) {
1277   // Don't allow nop instructions in the form sll zero_reg, zero_reg to be
1278   // generated using the sll instruction. They must be generated using
1279   // nop(int/NopMarkerTypes) or MarkCode(int/NopMarkerTypes) pseudo
1280   // instructions.
1281   DCHECK(coming_from_nop || !(rd.is(zero_reg) && rt.is(zero_reg)));
1282   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SLL);
1283 }
1284
1285
1286 void Assembler::sllv(Register rd, Register rt, Register rs) {
1287   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
1288 }
1289
1290
1291 void Assembler::srl(Register rd, Register rt, uint16_t sa) {
1292   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRL);
1293 }
1294
1295
1296 void Assembler::srlv(Register rd, Register rt, Register rs) {
1297   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
1298 }
1299
1300
1301 void Assembler::sra(Register rd, Register rt, uint16_t sa) {
1302   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRA);
1303 }
1304
1305
1306 void Assembler::srav(Register rd, Register rt, Register rs) {
1307   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
1308 }
1309
1310
1311 void Assembler::rotr(Register rd, Register rt, uint16_t sa) {
1312   // Should be called via MacroAssembler::Ror.
1313   DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
1314   DCHECK(kArchVariant == kMips32r2);
1315   Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
1316       | (rd.code() << kRdShift) | (sa << kSaShift) | SRL;
1317   emit(instr);
1318 }
1319
1320
1321 void Assembler::rotrv(Register rd, Register rt, Register rs) {
1322   // Should be called via MacroAssembler::Ror.
1323   DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid() );
1324   DCHECK(kArchVariant == kMips32r2);
1325   Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
1326      | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV;
1327   emit(instr);
1328 }
1329
1330
1331 // ------------Memory-instructions-------------
1332
1333 // Helper for base-reg + offset, when offset is larger than int16.
1334 void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) {
1335   DCHECK(!src.rm().is(at));
1336   lui(at, (src.offset_ >> kLuiShift) & kImm16Mask);
1337   ori(at, at, src.offset_ & kImm16Mask);  // Load 32-bit offset.
1338   addu(at, at, src.rm());  // Add base register.
1339 }
1340
1341
1342 void Assembler::lb(Register rd, const MemOperand& rs) {
1343   if (is_int16(rs.offset_)) {
1344     GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
1345   } else {  // Offset > 16 bits, use multiple instructions to load.
1346     LoadRegPlusOffsetToAt(rs);
1347     GenInstrImmediate(LB, at, rd, 0);  // Equiv to lb(rd, MemOperand(at, 0));
1348   }
1349 }
1350
1351
1352 void Assembler::lbu(Register rd, const MemOperand& rs) {
1353   if (is_int16(rs.offset_)) {
1354     GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
1355   } else {  // Offset > 16 bits, use multiple instructions to load.
1356     LoadRegPlusOffsetToAt(rs);
1357     GenInstrImmediate(LBU, at, rd, 0);  // Equiv to lbu(rd, MemOperand(at, 0));
1358   }
1359 }
1360
1361
1362 void Assembler::lh(Register rd, const MemOperand& rs) {
1363   if (is_int16(rs.offset_)) {
1364     GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
1365   } else {  // Offset > 16 bits, use multiple instructions to load.
1366     LoadRegPlusOffsetToAt(rs);
1367     GenInstrImmediate(LH, at, rd, 0);  // Equiv to lh(rd, MemOperand(at, 0));
1368   }
1369 }
1370
1371
1372 void Assembler::lhu(Register rd, const MemOperand& rs) {
1373   if (is_int16(rs.offset_)) {
1374     GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
1375   } else {  // Offset > 16 bits, use multiple instructions to load.
1376     LoadRegPlusOffsetToAt(rs);
1377     GenInstrImmediate(LHU, at, rd, 0);  // Equiv to lhu(rd, MemOperand(at, 0));
1378   }
1379 }
1380
1381
1382 void Assembler::lw(Register rd, const MemOperand& rs) {
1383   if (is_int16(rs.offset_)) {
1384     GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
1385   } else {  // Offset > 16 bits, use multiple instructions to load.
1386     LoadRegPlusOffsetToAt(rs);
1387     GenInstrImmediate(LW, at, rd, 0);  // Equiv to lw(rd, MemOperand(at, 0));
1388   }
1389 }
1390
1391
1392 void Assembler::lwl(Register rd, const MemOperand& rs) {
1393   GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
1394 }
1395
1396
1397 void Assembler::lwr(Register rd, const MemOperand& rs) {
1398   GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
1399 }
1400
1401
1402 void Assembler::sb(Register rd, const MemOperand& rs) {
1403   if (is_int16(rs.offset_)) {
1404     GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
1405   } else {  // Offset > 16 bits, use multiple instructions to store.
1406     LoadRegPlusOffsetToAt(rs);
1407     GenInstrImmediate(SB, at, rd, 0);  // Equiv to sb(rd, MemOperand(at, 0));
1408   }
1409 }
1410
1411
1412 void Assembler::sh(Register rd, const MemOperand& rs) {
1413   if (is_int16(rs.offset_)) {
1414     GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
1415   } else {  // Offset > 16 bits, use multiple instructions to store.
1416     LoadRegPlusOffsetToAt(rs);
1417     GenInstrImmediate(SH, at, rd, 0);  // Equiv to sh(rd, MemOperand(at, 0));
1418   }
1419 }
1420
1421
1422 void Assembler::sw(Register rd, const MemOperand& rs) {
1423   if (is_int16(rs.offset_)) {
1424     GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
1425   } else {  // Offset > 16 bits, use multiple instructions to store.
1426     LoadRegPlusOffsetToAt(rs);
1427     GenInstrImmediate(SW, at, rd, 0);  // Equiv to sw(rd, MemOperand(at, 0));
1428   }
1429 }
1430
1431
1432 void Assembler::swl(Register rd, const MemOperand& rs) {
1433   GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
1434 }
1435
1436
1437 void Assembler::swr(Register rd, const MemOperand& rs) {
1438   GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
1439 }
1440
1441
1442 void Assembler::lui(Register rd, int32_t j) {
1443   DCHECK(is_uint16(j));
1444   GenInstrImmediate(LUI, zero_reg, rd, j);
1445 }
1446
1447
1448 // -------------Misc-instructions--------------
1449
1450 // Break / Trap instructions.
1451 void Assembler::break_(uint32_t code, bool break_as_stop) {
1452   DCHECK((code & ~0xfffff) == 0);
1453   // We need to invalidate breaks that could be stops as well because the
1454   // simulator expects a char pointer after the stop instruction.
1455   // See constants-mips.h for explanation.
1456   DCHECK((break_as_stop &&
1457           code <= kMaxStopCode &&
1458           code > kMaxWatchpointCode) ||
1459          (!break_as_stop &&
1460           (code > kMaxStopCode ||
1461            code <= kMaxWatchpointCode)));
1462   Instr break_instr = SPECIAL | BREAK | (code << 6);
1463   emit(break_instr);
1464 }
1465
1466
1467 void Assembler::stop(const char* msg, uint32_t code) {
1468   DCHECK(code > kMaxWatchpointCode);
1469   DCHECK(code <= kMaxStopCode);
1470 #if V8_HOST_ARCH_MIPS
1471   break_(0x54321);
1472 #else  // V8_HOST_ARCH_MIPS
1473   BlockTrampolinePoolFor(2);
1474   // The Simulator will handle the stop instruction and get the message address.
1475   // On MIPS stop() is just a special kind of break_().
1476   break_(code, true);
1477   emit(reinterpret_cast<Instr>(msg));
1478 #endif
1479 }
1480
1481
1482 void Assembler::tge(Register rs, Register rt, uint16_t code) {
1483   DCHECK(is_uint10(code));
1484   Instr instr = SPECIAL | TGE | rs.code() << kRsShift
1485       | rt.code() << kRtShift | code << 6;
1486   emit(instr);
1487 }
1488
1489
1490 void Assembler::tgeu(Register rs, Register rt, uint16_t code) {
1491   DCHECK(is_uint10(code));
1492   Instr instr = SPECIAL | TGEU | rs.code() << kRsShift
1493       | rt.code() << kRtShift | code << 6;
1494   emit(instr);
1495 }
1496
1497
1498 void Assembler::tlt(Register rs, Register rt, uint16_t code) {
1499   DCHECK(is_uint10(code));
1500   Instr instr =
1501       SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
1502   emit(instr);
1503 }
1504
1505
1506 void Assembler::tltu(Register rs, Register rt, uint16_t code) {
1507   DCHECK(is_uint10(code));
1508   Instr instr =
1509       SPECIAL | TLTU | rs.code() << kRsShift
1510       | rt.code() << kRtShift | code << 6;
1511   emit(instr);
1512 }
1513
1514
1515 void Assembler::teq(Register rs, Register rt, uint16_t code) {
1516   DCHECK(is_uint10(code));
1517   Instr instr =
1518       SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
1519   emit(instr);
1520 }
1521
1522
1523 void Assembler::tne(Register rs, Register rt, uint16_t code) {
1524   DCHECK(is_uint10(code));
1525   Instr instr =
1526       SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
1527   emit(instr);
1528 }
1529
1530
1531 // Move from HI/LO register.
1532
1533 void Assembler::mfhi(Register rd) {
1534   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
1535 }
1536
1537
1538 void Assembler::mflo(Register rd) {
1539   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
1540 }
1541
1542
1543 // Set on less than instructions.
1544 void Assembler::slt(Register rd, Register rs, Register rt) {
1545   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
1546 }
1547
1548
1549 void Assembler::sltu(Register rd, Register rs, Register rt) {
1550   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
1551 }
1552
1553
1554 void Assembler::slti(Register rt, Register rs, int32_t j) {
1555   GenInstrImmediate(SLTI, rs, rt, j);
1556 }
1557
1558
1559 void Assembler::sltiu(Register rt, Register rs, int32_t j) {
1560   GenInstrImmediate(SLTIU, rs, rt, j);
1561 }
1562
1563
1564 // Conditional move.
1565 void Assembler::movz(Register rd, Register rs, Register rt) {
1566   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ);
1567 }
1568
1569
1570 void Assembler::movn(Register rd, Register rs, Register rt) {
1571   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
1572 }
1573
1574
1575 void Assembler::movt(Register rd, Register rs, uint16_t cc) {
1576   Register rt;
1577   rt.code_ = (cc & 0x0007) << 2 | 1;
1578   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
1579 }
1580
1581
1582 void Assembler::movf(Register rd, Register rs, uint16_t cc) {
1583   Register rt;
1584   rt.code_ = (cc & 0x0007) << 2 | 0;
1585   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
1586 }
1587
1588
1589 // Bit twiddling.
1590 void Assembler::clz(Register rd, Register rs) {
1591   // Clz instr requires same GPR number in 'rd' and 'rt' fields.
1592   GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
1593 }
1594
1595
1596 void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
1597   // Should be called via MacroAssembler::Ins.
1598   // Ins instr has 'rt' field as dest, and two uint5: msb, lsb.
1599   DCHECK(kArchVariant == kMips32r2);
1600   GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS);
1601 }
1602
1603
1604 void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
1605   // Should be called via MacroAssembler::Ext.
1606   // Ext instr has 'rt' field as dest, and two uint5: msb, lsb.
1607   DCHECK(kArchVariant == kMips32r2);
1608   GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT);
1609 }
1610
1611
1612 void Assembler::pref(int32_t hint, const MemOperand& rs) {
1613   DCHECK(kArchVariant != kLoongson);
1614   DCHECK(is_uint5(hint) && is_uint16(rs.offset_));
1615   Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift)
1616       | (rs.offset_);
1617   emit(instr);
1618 }
1619
1620
1621 // --------Coprocessor-instructions----------------
1622
1623 // Load, store, move.
1624 void Assembler::lwc1(FPURegister fd, const MemOperand& src) {
1625   GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
1626 }
1627
1628
1629 void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
1630   // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
1631   // load to two 32-bit loads.
1632   GenInstrImmediate(LWC1, src.rm(), fd, src.offset_ +
1633       Register::kMantissaOffset);
1634   FPURegister nextfpreg;
1635   nextfpreg.setcode(fd.code() + 1);
1636   GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ +
1637       Register::kExponentOffset);
1638 }
1639
1640
1641 void Assembler::swc1(FPURegister fd, const MemOperand& src) {
1642   GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
1643 }
1644
1645
1646 void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
1647   // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
1648   // store to two 32-bit stores.
1649   GenInstrImmediate(SWC1, src.rm(), fd, src.offset_ +
1650       Register::kMantissaOffset);
1651   FPURegister nextfpreg;
1652   nextfpreg.setcode(fd.code() + 1);
1653   GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ +
1654       Register::kExponentOffset);
1655 }
1656
1657
1658 void Assembler::mtc1(Register rt, FPURegister fs) {
1659   GenInstrRegister(COP1, MTC1, rt, fs, f0);
1660 }
1661
1662
1663 void Assembler::mfc1(Register rt, FPURegister fs) {
1664   GenInstrRegister(COP1, MFC1, rt, fs, f0);
1665 }
1666
1667
1668 void Assembler::ctc1(Register rt, FPUControlRegister fs) {
1669   GenInstrRegister(COP1, CTC1, rt, fs);
1670 }
1671
1672
1673 void Assembler::cfc1(Register rt, FPUControlRegister fs) {
1674   GenInstrRegister(COP1, CFC1, rt, fs);
1675 }
1676
1677
1678 void Assembler::DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
1679   uint64_t i;
1680   memcpy(&i, &d, 8);
1681
1682   *lo = i & 0xffffffff;
1683   *hi = i >> 32;
1684 }
1685
1686
1687 // Arithmetic.
1688
1689 void Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
1690   GenInstrRegister(COP1, D, ft, fs, fd, ADD_D);
1691 }
1692
1693
1694 void Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) {
1695   GenInstrRegister(COP1, D, ft, fs, fd, SUB_D);
1696 }
1697
1698
1699 void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
1700   GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
1701 }
1702
1703
1704 void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
1705     FPURegister ft) {
1706   GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D);
1707 }
1708
1709
1710 void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) {
1711   GenInstrRegister(COP1, D, ft, fs, fd, DIV_D);
1712 }
1713
1714
1715 void Assembler::abs_d(FPURegister fd, FPURegister fs) {
1716   GenInstrRegister(COP1, D, f0, fs, fd, ABS_D);
1717 }
1718
1719
1720 void Assembler::mov_d(FPURegister fd, FPURegister fs) {
1721   GenInstrRegister(COP1, D, f0, fs, fd, MOV_D);
1722 }
1723
1724
1725 void Assembler::neg_d(FPURegister fd, FPURegister fs) {
1726   GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
1727 }
1728
1729
1730 void Assembler::sqrt_d(FPURegister fd, FPURegister fs) {
1731   GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D);
1732 }
1733
1734
1735 // Conversions.
1736
1737 void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
1738   GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
1739 }
1740
1741
1742 void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
1743   GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
1744 }
1745
1746
1747 void Assembler::trunc_w_s(FPURegister fd, FPURegister fs) {
1748   GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S);
1749 }
1750
1751
1752 void Assembler::trunc_w_d(FPURegister fd, FPURegister fs) {
1753   GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D);
1754 }
1755
1756
1757 void Assembler::round_w_s(FPURegister fd, FPURegister fs) {
1758   GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S);
1759 }
1760
1761
1762 void Assembler::round_w_d(FPURegister fd, FPURegister fs) {
1763   GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D);
1764 }
1765
1766
1767 void Assembler::floor_w_s(FPURegister fd, FPURegister fs) {
1768   GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S);
1769 }
1770
1771
1772 void Assembler::floor_w_d(FPURegister fd, FPURegister fs) {
1773   GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D);
1774 }
1775
1776
1777 void Assembler::ceil_w_s(FPURegister fd, FPURegister fs) {
1778   GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S);
1779 }
1780
1781
1782 void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) {
1783   GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D);
1784 }
1785
1786
1787 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
1788   DCHECK(kArchVariant == kMips32r2);
1789   GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
1790 }
1791
1792
1793 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
1794   DCHECK(kArchVariant == kMips32r2);
1795   GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
1796 }
1797
1798
1799 void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) {
1800   DCHECK(kArchVariant == kMips32r2);
1801   GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S);
1802 }
1803
1804
1805 void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) {
1806   DCHECK(kArchVariant == kMips32r2);
1807   GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D);
1808 }
1809
1810
1811 void Assembler::round_l_s(FPURegister fd, FPURegister fs) {
1812   GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S);
1813 }
1814
1815
1816 void Assembler::round_l_d(FPURegister fd, FPURegister fs) {
1817   GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D);
1818 }
1819
1820
1821 void Assembler::floor_l_s(FPURegister fd, FPURegister fs) {
1822   GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S);
1823 }
1824
1825
1826 void Assembler::floor_l_d(FPURegister fd, FPURegister fs) {
1827   GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D);
1828 }
1829
1830
1831 void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) {
1832   GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S);
1833 }
1834
1835
1836 void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
1837   GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D);
1838 }
1839
1840
1841 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
1842   GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
1843 }
1844
1845
1846 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
1847   DCHECK(kArchVariant == kMips32r2);
1848   GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
1849 }
1850
1851
1852 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
1853   GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
1854 }
1855
1856
1857 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
1858   GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
1859 }
1860
1861
1862 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
1863   DCHECK(kArchVariant == kMips32r2);
1864   GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
1865 }
1866
1867
1868 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
1869   GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
1870 }
1871
1872
1873 // Conditions.
1874 void Assembler::c(FPUCondition cond, SecondaryField fmt,
1875     FPURegister fs, FPURegister ft, uint16_t cc) {
1876   DCHECK(is_uint3(cc));
1877   DCHECK((fmt & ~(31 << kRsShift)) == 0);
1878   Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
1879       | cc << 8 | 3 << 4 | cond;
1880   emit(instr);
1881 }
1882
1883
1884 void Assembler::fcmp(FPURegister src1, const double src2,
1885       FPUCondition cond) {
1886   DCHECK(src2 == 0.0);
1887   mtc1(zero_reg, f14);
1888   cvt_d_w(f14, f14);
1889   c(cond, D, src1, f14, 0);
1890 }
1891
1892
1893 void Assembler::bc1f(int16_t offset, uint16_t cc) {
1894   DCHECK(is_uint3(cc));
1895   Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
1896   emit(instr);
1897 }
1898
1899
1900 void Assembler::bc1t(int16_t offset, uint16_t cc) {
1901   DCHECK(is_uint3(cc));
1902   Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
1903   emit(instr);
1904 }
1905
1906
1907 // Debugging.
1908 void Assembler::RecordJSReturn() {
1909   positions_recorder()->WriteRecordedPositions();
1910   CheckBuffer();
1911   RecordRelocInfo(RelocInfo::JS_RETURN);
1912 }
1913
1914
1915 void Assembler::RecordDebugBreakSlot() {
1916   positions_recorder()->WriteRecordedPositions();
1917   CheckBuffer();
1918   RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
1919 }
1920
1921
1922 void Assembler::RecordComment(const char* msg) {
1923   if (FLAG_code_comments) {
1924     CheckBuffer();
1925     RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
1926   }
1927 }
1928
1929
1930 int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) {
1931   Instr instr = instr_at(pc);
1932   DCHECK(IsJ(instr) || IsLui(instr));
1933   if (IsLui(instr)) {
1934     Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize);
1935     Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize);
1936     DCHECK(IsOri(instr_ori));
1937     int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
1938     imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
1939     if (imm == kEndOfJumpChain) {
1940       return 0;  // Number of instructions patched.
1941     }
1942     imm += pc_delta;
1943     DCHECK((imm & 3) == 0);
1944
1945     instr_lui &= ~kImm16Mask;
1946     instr_ori &= ~kImm16Mask;
1947
1948     instr_at_put(pc + 0 * Assembler::kInstrSize,
1949                  instr_lui | ((imm >> kLuiShift) & kImm16Mask));
1950     instr_at_put(pc + 1 * Assembler::kInstrSize,
1951                  instr_ori | (imm & kImm16Mask));
1952     return 2;  // Number of instructions patched.
1953   } else {
1954     uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
1955     if (static_cast<int32_t>(imm28) == kEndOfJumpChain) {
1956       return 0;  // Number of instructions patched.
1957     }
1958     imm28 += pc_delta;
1959     imm28 &= kImm28Mask;
1960     DCHECK((imm28 & 3) == 0);
1961
1962     instr &= ~kImm26Mask;
1963     uint32_t imm26 = imm28 >> 2;
1964     DCHECK(is_uint26(imm26));
1965
1966     instr_at_put(pc, instr | (imm26 & kImm26Mask));
1967     return 1;  // Number of instructions patched.
1968   }
1969 }
1970
1971
1972 void Assembler::GrowBuffer() {
1973   if (!own_buffer_) FATAL("external code buffer is too small");
1974
1975   // Compute new buffer size.
1976   CodeDesc desc;  // The new buffer.
1977   if (buffer_size_ < 1 * MB) {
1978     desc.buffer_size = 2*buffer_size_;
1979   } else {
1980     desc.buffer_size = buffer_size_ + 1*MB;
1981   }
1982   CHECK_GT(desc.buffer_size, 0);  // No overflow.
1983
1984   // Set up new buffer.
1985   desc.buffer = NewArray<byte>(desc.buffer_size);
1986
1987   desc.instr_size = pc_offset();
1988   desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
1989
1990   // Copy the data.
1991   int pc_delta = desc.buffer - buffer_;
1992   int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
1993   MemMove(desc.buffer, buffer_, desc.instr_size);
1994   MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
1995           desc.reloc_size);
1996
1997   // Switch buffers.
1998   DeleteArray(buffer_);
1999   buffer_ = desc.buffer;
2000   buffer_size_ = desc.buffer_size;
2001   pc_ += pc_delta;
2002   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2003                                reloc_info_writer.last_pc() + pc_delta);
2004
2005   // Relocate runtime entries.
2006   for (RelocIterator it(desc); !it.done(); it.next()) {
2007     RelocInfo::Mode rmode = it.rinfo()->rmode();
2008     if (rmode == RelocInfo::INTERNAL_REFERENCE) {
2009       byte* p = reinterpret_cast<byte*>(it.rinfo()->pc());
2010       RelocateInternalReference(p, pc_delta);
2011     }
2012   }
2013
2014   DCHECK(!overflow());
2015 }
2016
2017
2018 void Assembler::db(uint8_t data) {
2019   CheckBuffer();
2020   *reinterpret_cast<uint8_t*>(pc_) = data;
2021   pc_ += sizeof(uint8_t);
2022 }
2023
2024
2025 void Assembler::dd(uint32_t data) {
2026   CheckBuffer();
2027   *reinterpret_cast<uint32_t*>(pc_) = data;
2028   pc_ += sizeof(uint32_t);
2029 }
2030
2031
2032 void Assembler::emit_code_stub_address(Code* stub) {
2033   CheckBuffer();
2034   *reinterpret_cast<uint32_t*>(pc_) =
2035       reinterpret_cast<uint32_t>(stub->instruction_start());
2036   pc_ += sizeof(uint32_t);
2037 }
2038
2039
2040 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2041   // We do not try to reuse pool constants.
2042   RelocInfo rinfo(pc_, rmode, data, NULL);
2043   if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
2044     // Adjust code for new modes.
2045     DCHECK(RelocInfo::IsDebugBreakSlot(rmode)
2046            || RelocInfo::IsJSReturn(rmode)
2047            || RelocInfo::IsComment(rmode)
2048            || RelocInfo::IsPosition(rmode));
2049     // These modes do not need an entry in the constant pool.
2050   }
2051   if (!RelocInfo::IsNone(rinfo.rmode())) {
2052     // Don't record external references unless the heap will be serialized.
2053     if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
2054         !serializer_enabled() && !emit_debug_code()) {
2055       return;
2056     }
2057     DCHECK(buffer_space() >= kMaxRelocSize);  // Too late to grow buffer here.
2058     if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
2059       RelocInfo reloc_info_with_ast_id(pc_,
2060                                        rmode,
2061                                        RecordedAstId().ToInt(),
2062                                        NULL);
2063       ClearRecordedAstId();
2064       reloc_info_writer.Write(&reloc_info_with_ast_id);
2065     } else {
2066       reloc_info_writer.Write(&rinfo);
2067     }
2068   }
2069 }
2070
2071
2072 void Assembler::BlockTrampolinePoolFor(int instructions) {
2073   BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
2074 }
2075
2076
2077 void Assembler::CheckTrampolinePool() {
2078   // Some small sequences of instructions must not be broken up by the
2079   // insertion of a trampoline pool; such sequences are protected by setting
2080   // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
2081   // which are both checked here. Also, recursive calls to CheckTrampolinePool
2082   // are blocked by trampoline_pool_blocked_nesting_.
2083   if ((trampoline_pool_blocked_nesting_ > 0) ||
2084       (pc_offset() < no_trampoline_pool_before_)) {
2085     // Emission is currently blocked; make sure we try again as soon as
2086     // possible.
2087     if (trampoline_pool_blocked_nesting_ > 0) {
2088       next_buffer_check_ = pc_offset() + kInstrSize;
2089     } else {
2090       next_buffer_check_ = no_trampoline_pool_before_;
2091     }
2092     return;
2093   }
2094
2095   DCHECK(!trampoline_emitted_);
2096   DCHECK(unbound_labels_count_ >= 0);
2097   if (unbound_labels_count_ > 0) {
2098     // First we emit jump (2 instructions), then we emit trampoline pool.
2099     { BlockTrampolinePoolScope block_trampoline_pool(this);
2100       Label after_pool;
2101       b(&after_pool);
2102       nop();
2103
2104       int pool_start = pc_offset();
2105       for (int i = 0; i < unbound_labels_count_; i++) {
2106         uint32_t imm32;
2107         imm32 = jump_address(&after_pool);
2108         { BlockGrowBufferScope block_buf_growth(this);
2109           // Buffer growth (and relocation) must be blocked for internal
2110           // references until associated instructions are emitted and available
2111           // to be patched.
2112           RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
2113           lui(at, (imm32 & kHiMask) >> kLuiShift);
2114           ori(at, at, (imm32 & kImm16Mask));
2115         }
2116         jr(at);
2117         nop();
2118       }
2119       bind(&after_pool);
2120       trampoline_ = Trampoline(pool_start, unbound_labels_count_);
2121
2122       trampoline_emitted_ = true;
2123       // As we are only going to emit trampoline once, we need to prevent any
2124       // further emission.
2125       next_buffer_check_ = kMaxInt;
2126     }
2127   } else {
2128     // Number of branches to unbound label at this point is zero, so we can
2129     // move next buffer check to maximum.
2130     next_buffer_check_ = pc_offset() +
2131         kMaxBranchOffset - kTrampolineSlotsSize * 16;
2132   }
2133   return;
2134 }
2135
2136
2137 Address Assembler::target_address_at(Address pc) {
2138   Instr instr1 = instr_at(pc);
2139   Instr instr2 = instr_at(pc + kInstrSize);
2140   // Interpret 2 instructions generated by li: lui/ori
2141   if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) {
2142     // Assemble the 32 bit value.
2143     return reinterpret_cast<Address>(
2144         (GetImmediate16(instr1) << 16) | GetImmediate16(instr2));
2145   }
2146
2147   // We should never get here, force a bad address if we do.
2148   UNREACHABLE();
2149   return (Address)0x0;
2150 }
2151
2152
2153 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32
2154 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap
2155 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted.
2156 // OS::nan_value() returns a qNaN.
2157 void Assembler::QuietNaN(HeapObject* object) {
2158   HeapNumber::cast(object)->set_value(base::OS::nan_value());
2159 }
2160
2161
2162 // On Mips, a target address is stored in a lui/ori instruction pair, each
2163 // of which load 16 bits of the 32-bit address to a register.
2164 // Patching the address must replace both instr, and flush the i-cache.
2165 //
2166 // There is an optimization below, which emits a nop when the address
2167 // fits in just 16 bits. This is unlikely to help, and should be benchmarked,
2168 // and possibly removed.
2169 void Assembler::set_target_address_at(Address pc,
2170                                       Address target,
2171                                       ICacheFlushMode icache_flush_mode) {
2172   Instr instr2 = instr_at(pc + kInstrSize);
2173   uint32_t rt_code = GetRtField(instr2);
2174   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
2175   uint32_t itarget = reinterpret_cast<uint32_t>(target);
2176
2177 #ifdef DEBUG
2178   // Check we have the result from a li macro-instruction, using instr pair.
2179   Instr instr1 = instr_at(pc);
2180   CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI));
2181 #endif
2182
2183   // Must use 2 instructions to insure patchable code => just use lui and ori.
2184   // lui rt, upper-16.
2185   // ori rt rt, lower-16.
2186   *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
2187   *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask);
2188
2189   // The following code is an optimization for the common case of Call()
2190   // or Jump() which is load to register, and jump through register:
2191   //     li(t9, address); jalr(t9)    (or jr(t9)).
2192   // If the destination address is in the same 256 MB page as the call, it
2193   // is faster to do a direct jal, or j, rather than jump thru register, since
2194   // that lets the cpu pipeline prefetch the target address. However each
2195   // time the address above is patched, we have to patch the direct jal/j
2196   // instruction, as well as possibly revert to jalr/jr if we now cross a
2197   // 256 MB page. Note that with the jal/j instructions, we do not need to
2198   // load the register, but that code is left, since it makes it easy to
2199   // revert this process. A further optimization could try replacing the
2200   // li sequence with nops.
2201   // This optimization can only be applied if the rt-code from instr2 is the
2202   // register used for the jalr/jr. Finally, we have to skip 'jr ra', which is
2203   // mips return. Occasionally this lands after an li().
2204
2205   Instr instr3 = instr_at(pc + 2 * kInstrSize);
2206   uint32_t ipc = reinterpret_cast<uint32_t>(pc + 3 * kInstrSize);
2207   bool in_range = ((ipc ^ itarget) >> (kImm26Bits + kImmFieldShift)) == 0;
2208   uint32_t target_field =
2209       static_cast<uint32_t>(itarget & kJumpAddrMask) >> kImmFieldShift;
2210   bool patched_jump = false;
2211
2212 #ifndef ALLOW_JAL_IN_BOUNDARY_REGION
2213   // This is a workaround to the 24k core E156 bug (affect some 34k cores also).
2214   // Since the excluded space is only 64KB out of 256MB (0.02 %), we will just
2215   // apply this workaround for all cores so we don't have to identify the core.
2216   if (in_range) {
2217     // The 24k core E156 bug has some very specific requirements, we only check
2218     // the most simple one: if the address of the delay slot instruction is in
2219     // the first or last 32 KB of the 256 MB segment.
2220     uint32_t segment_mask = ((256 * MB) - 1) ^ ((32 * KB) - 1);
2221     uint32_t ipc_segment_addr = ipc & segment_mask;
2222     if (ipc_segment_addr == 0 || ipc_segment_addr == segment_mask)
2223       in_range = false;
2224   }
2225 #endif
2226
2227   if (IsJalr(instr3)) {
2228     // Try to convert JALR to JAL.
2229     if (in_range && GetRt(instr2) == GetRs(instr3)) {
2230       *(p+2) = JAL | target_field;
2231       patched_jump = true;
2232     }
2233   } else if (IsJr(instr3)) {
2234     // Try to convert JR to J, skip returns (jr ra).
2235     bool is_ret = static_cast<int>(GetRs(instr3)) == ra.code();
2236     if (in_range && !is_ret && GetRt(instr2) == GetRs(instr3)) {
2237       *(p+2) = J | target_field;
2238       patched_jump = true;
2239     }
2240   } else if (IsJal(instr3)) {
2241     if (in_range) {
2242       // We are patching an already converted JAL.
2243       *(p+2) = JAL | target_field;
2244     } else {
2245       // Patch JAL, but out of range, revert to JALR.
2246       // JALR rs reg is the rt reg specified in the ORI instruction.
2247       uint32_t rs_field = GetRt(instr2) << kRsShift;
2248       uint32_t rd_field = ra.code() << kRdShift;  // Return-address (ra) reg.
2249       *(p+2) = SPECIAL | rs_field | rd_field | JALR;
2250     }
2251     patched_jump = true;
2252   } else if (IsJ(instr3)) {
2253     if (in_range) {
2254       // We are patching an already converted J (jump).
2255       *(p+2) = J | target_field;
2256     } else {
2257       // Trying patch J, but out of range, just go back to JR.
2258       // JR 'rs' reg is the 'rt' reg specified in the ORI instruction (instr2).
2259       uint32_t rs_field = GetRt(instr2) << kRsShift;
2260       *(p+2) = SPECIAL | rs_field | JR;
2261     }
2262     patched_jump = true;
2263   }
2264
2265   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
2266     CpuFeatures::FlushICache(pc, (patched_jump ? 3 : 2) * sizeof(int32_t));
2267   }
2268 }
2269
2270
2271 void Assembler::JumpLabelToJumpRegister(Address pc) {
2272   // Address pc points to lui/ori instructions.
2273   // Jump to label may follow at pc + 2 * kInstrSize.
2274   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
2275 #ifdef DEBUG
2276   Instr instr1 = instr_at(pc);
2277 #endif
2278   Instr instr2 = instr_at(pc + 1 * kInstrSize);
2279   Instr instr3 = instr_at(pc + 2 * kInstrSize);
2280   bool patched = false;
2281
2282   if (IsJal(instr3)) {
2283     DCHECK(GetOpcodeField(instr1) == LUI);
2284     DCHECK(GetOpcodeField(instr2) == ORI);
2285
2286     uint32_t rs_field = GetRt(instr2) << kRsShift;
2287     uint32_t rd_field = ra.code() << kRdShift;  // Return-address (ra) reg.
2288     *(p+2) = SPECIAL | rs_field | rd_field | JALR;
2289     patched = true;
2290   } else if (IsJ(instr3)) {
2291     DCHECK(GetOpcodeField(instr1) == LUI);
2292     DCHECK(GetOpcodeField(instr2) == ORI);
2293
2294     uint32_t rs_field = GetRt(instr2) << kRsShift;
2295     *(p+2) = SPECIAL | rs_field | JR;
2296     patched = true;
2297   }
2298
2299   if (patched) {
2300     CpuFeatures::FlushICache(pc+2, sizeof(Address));
2301   }
2302 }
2303
2304
2305 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
2306   // No out-of-line constant pool support.
2307   DCHECK(!FLAG_enable_ool_constant_pool);
2308   return isolate->factory()->empty_constant_pool_array();
2309 }
2310
2311
2312 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
2313   // No out-of-line constant pool support.
2314   DCHECK(!FLAG_enable_ool_constant_pool);
2315   return;
2316 }
2317
2318
2319 } }  // namespace v8::internal
2320
2321 #endif  // V8_TARGET_ARCH_MIPS