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