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