V8 Project
macro-assembler-mips64.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <limits.h> // For LONG_MIN, LONG_MAX.
6 
7 #include "src/v8.h"
8 
9 #if V8_TARGET_ARCH_MIPS64
10 
12 #include "src/bootstrapper.h"
13 #include "src/codegen.h"
14 #include "src/cpu-profiler.h"
15 #include "src/debug.h"
16 #include "src/isolate-inl.h"
17 #include "src/runtime/runtime.h"
18 
19 namespace v8 {
20 namespace internal {
21 
22 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
23  : Assembler(arg_isolate, buffer, size),
24  generating_stub_(false),
25  has_frame_(false) {
26  if (isolate() != NULL) {
27  code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
28  isolate());
29  }
30 }
31 
32 
33 void MacroAssembler::Load(Register dst,
34  const MemOperand& src,
35  Representation r) {
36  DCHECK(!r.IsDouble());
37  if (r.IsInteger8()) {
38  lb(dst, src);
39  } else if (r.IsUInteger8()) {
40  lbu(dst, src);
41  } else if (r.IsInteger16()) {
42  lh(dst, src);
43  } else if (r.IsUInteger16()) {
44  lhu(dst, src);
45  } else if (r.IsInteger32()) {
46  lw(dst, src);
47  } else {
48  ld(dst, src);
49  }
50 }
51 
52 
53 void MacroAssembler::Store(Register src,
54  const MemOperand& dst,
55  Representation r) {
56  DCHECK(!r.IsDouble());
57  if (r.IsInteger8() || r.IsUInteger8()) {
58  sb(src, dst);
59  } else if (r.IsInteger16() || r.IsUInteger16()) {
60  sh(src, dst);
61  } else if (r.IsInteger32()) {
62  sw(src, dst);
63  } else {
64  if (r.IsHeapObject()) {
65  AssertNotSmi(src);
66  } else if (r.IsSmi()) {
67  AssertSmi(src);
68  }
69  sd(src, dst);
70  }
71 }
72 
73 
74 void MacroAssembler::LoadRoot(Register destination,
75  Heap::RootListIndex index) {
76  ld(destination, MemOperand(s6, index << kPointerSizeLog2));
77 }
78 
79 
80 void MacroAssembler::LoadRoot(Register destination,
81  Heap::RootListIndex index,
82  Condition cond,
83  Register src1, const Operand& src2) {
84  Branch(2, NegateCondition(cond), src1, src2);
85  ld(destination, MemOperand(s6, index << kPointerSizeLog2));
86 }
87 
88 
89 void MacroAssembler::StoreRoot(Register source,
90  Heap::RootListIndex index) {
91  sd(source, MemOperand(s6, index << kPointerSizeLog2));
92 }
93 
94 
95 void MacroAssembler::StoreRoot(Register source,
96  Heap::RootListIndex index,
97  Condition cond,
98  Register src1, const Operand& src2) {
99  Branch(2, NegateCondition(cond), src1, src2);
100  sd(source, MemOperand(s6, index << kPointerSizeLog2));
101 }
102 
103 
104 // Push and pop all registers that can hold pointers.
105 void MacroAssembler::PushSafepointRegisters() {
106  // Safepoints expect a block of kNumSafepointRegisters values on the
107  // stack, so adjust the stack for unsaved registers.
108  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
109  DCHECK(num_unsaved >= 0);
110  if (num_unsaved > 0) {
111  Dsubu(sp, sp, Operand(num_unsaved * kPointerSize));
112  }
113  MultiPush(kSafepointSavedRegisters);
114 }
115 
116 
117 void MacroAssembler::PopSafepointRegisters() {
118  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
119  MultiPop(kSafepointSavedRegisters);
120  if (num_unsaved > 0) {
121  Daddu(sp, sp, Operand(num_unsaved * kPointerSize));
122  }
123 }
124 
125 
126 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
127  sd(src, SafepointRegisterSlot(dst));
128 }
129 
130 
131 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
132  ld(dst, SafepointRegisterSlot(src));
133 }
134 
135 
136 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
137  // The registers are pushed starting with the highest encoding,
138  // which means that lowest encodings are closest to the stack pointer.
139  return kSafepointRegisterStackIndexMap[reg_code];
140 }
141 
142 
143 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
144  return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
145 }
146 
147 
148 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
150  // General purpose registers are pushed last on the stack.
151  int doubles_size = FPURegister::NumAllocatableRegisters() * kDoubleSize;
152  int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
153  return MemOperand(sp, doubles_size + register_offset);
154 }
155 
156 
157 void MacroAssembler::InNewSpace(Register object,
158  Register scratch,
159  Condition cc,
160  Label* branch) {
161  DCHECK(cc == eq || cc == ne);
162  And(scratch, object, Operand(ExternalReference::new_space_mask(isolate())));
163  Branch(branch, cc, scratch,
164  Operand(ExternalReference::new_space_start(isolate())));
165 }
166 
167 
168 void MacroAssembler::RecordWriteField(
169  Register object,
170  int offset,
171  Register value,
172  Register dst,
173  RAStatus ra_status,
174  SaveFPRegsMode save_fp,
175  RememberedSetAction remembered_set_action,
176  SmiCheck smi_check,
177  PointersToHereCheck pointers_to_here_check_for_value) {
178  DCHECK(!AreAliased(value, dst, t8, object));
179  // First, check if a write barrier is even needed. The tests below
180  // catch stores of Smis.
181  Label done;
182 
183  // Skip barrier if writing a smi.
184  if (smi_check == INLINE_SMI_CHECK) {
185  JumpIfSmi(value, &done);
186  }
187 
188  // Although the object register is tagged, the offset is relative to the start
189  // of the object, so so offset must be a multiple of kPointerSize.
190  DCHECK(IsAligned(offset, kPointerSize));
191 
192  Daddu(dst, object, Operand(offset - kHeapObjectTag));
193  if (emit_debug_code()) {
194  Label ok;
195  And(t8, dst, Operand((1 << kPointerSizeLog2) - 1));
196  Branch(&ok, eq, t8, Operand(zero_reg));
197  stop("Unaligned cell in write barrier");
198  bind(&ok);
199  }
200 
201  RecordWrite(object,
202  dst,
203  value,
204  ra_status,
205  save_fp,
206  remembered_set_action,
208  pointers_to_here_check_for_value);
209 
210  bind(&done);
211 
212  // Clobber clobbered input registers when running with the debug-code flag
213  // turned on to provoke errors.
214  if (emit_debug_code()) {
215  li(value, Operand(bit_cast<int64_t>(kZapValue + 4)));
216  li(dst, Operand(bit_cast<int64_t>(kZapValue + 8)));
217  }
218 }
219 
220 
221 // Will clobber 4 registers: object, map, dst, ip. The
222 // register 'object' contains a heap object pointer.
223 void MacroAssembler::RecordWriteForMap(Register object,
224  Register map,
225  Register dst,
226  RAStatus ra_status,
227  SaveFPRegsMode fp_mode) {
228  if (emit_debug_code()) {
229  DCHECK(!dst.is(at));
230  ld(dst, FieldMemOperand(map, HeapObject::kMapOffset));
231  Check(eq,
232  kWrongAddressOrValuePassedToRecordWrite,
233  dst,
234  Operand(isolate()->factory()->meta_map()));
235  }
236 
237  if (!FLAG_incremental_marking) {
238  return;
239  }
240 
241  if (emit_debug_code()) {
242  ld(at, FieldMemOperand(object, HeapObject::kMapOffset));
243  Check(eq,
244  kWrongAddressOrValuePassedToRecordWrite,
245  map,
246  Operand(at));
247  }
248 
249  Label done;
250 
251  // A single check of the map's pages interesting flag suffices, since it is
252  // only set during incremental collection, and then it's also guaranteed that
253  // the from object's page's interesting flag is also set. This optimization
254  // relies on the fact that maps can never be in new space.
255  CheckPageFlag(map,
256  map, // Used as scratch.
257  MemoryChunk::kPointersToHereAreInterestingMask,
258  eq,
259  &done);
260 
261  Daddu(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag));
262  if (emit_debug_code()) {
263  Label ok;
264  And(at, dst, Operand((1 << kPointerSizeLog2) - 1));
265  Branch(&ok, eq, at, Operand(zero_reg));
266  stop("Unaligned cell in write barrier");
267  bind(&ok);
268  }
269 
270  // Record the actual write.
271  if (ra_status == kRAHasNotBeenSaved) {
272  push(ra);
273  }
274  RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
275  fp_mode);
276  CallStub(&stub);
277  if (ra_status == kRAHasNotBeenSaved) {
278  pop(ra);
279  }
280 
281  bind(&done);
282 
283  // Count number of write barriers in generated code.
284  isolate()->counters()->write_barriers_static()->Increment();
285  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, at, dst);
286 
287  // Clobber clobbered registers when running with the debug-code flag
288  // turned on to provoke errors.
289  if (emit_debug_code()) {
290  li(dst, Operand(bit_cast<int64_t>(kZapValue + 12)));
291  li(map, Operand(bit_cast<int64_t>(kZapValue + 16)));
292  }
293 }
294 
295 
296 // Will clobber 4 registers: object, address, scratch, ip. The
297 // register 'object' contains a heap object pointer. The heap object
298 // tag is shifted away.
299 void MacroAssembler::RecordWrite(
300  Register object,
301  Register address,
302  Register value,
303  RAStatus ra_status,
304  SaveFPRegsMode fp_mode,
305  RememberedSetAction remembered_set_action,
306  SmiCheck smi_check,
307  PointersToHereCheck pointers_to_here_check_for_value) {
308  DCHECK(!AreAliased(object, address, value, t8));
309  DCHECK(!AreAliased(object, address, value, t9));
310 
311  if (emit_debug_code()) {
312  ld(at, MemOperand(address));
313  Assert(
314  eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value));
315  }
316 
317  if (remembered_set_action == OMIT_REMEMBERED_SET &&
318  !FLAG_incremental_marking) {
319  return;
320  }
321 
322  // First, check if a write barrier is even needed. The tests below
323  // catch stores of smis and stores into the young generation.
324  Label done;
325 
326  if (smi_check == INLINE_SMI_CHECK) {
327  DCHECK_EQ(0, kSmiTag);
328  JumpIfSmi(value, &done);
329  }
330 
331  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
332  CheckPageFlag(value,
333  value, // Used as scratch.
334  MemoryChunk::kPointersToHereAreInterestingMask,
335  eq,
336  &done);
337  }
338  CheckPageFlag(object,
339  value, // Used as scratch.
340  MemoryChunk::kPointersFromHereAreInterestingMask,
341  eq,
342  &done);
343 
344  // Record the actual write.
345  if (ra_status == kRAHasNotBeenSaved) {
346  push(ra);
347  }
348  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
349  fp_mode);
350  CallStub(&stub);
351  if (ra_status == kRAHasNotBeenSaved) {
352  pop(ra);
353  }
354 
355  bind(&done);
356 
357  // Count number of write barriers in generated code.
358  isolate()->counters()->write_barriers_static()->Increment();
359  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, at,
360  value);
361 
362  // Clobber clobbered registers when running with the debug-code flag
363  // turned on to provoke errors.
364  if (emit_debug_code()) {
365  li(address, Operand(bit_cast<int64_t>(kZapValue + 12)));
366  li(value, Operand(bit_cast<int64_t>(kZapValue + 16)));
367  }
368 }
369 
370 
371 void MacroAssembler::RememberedSetHelper(Register object, // For debug tests.
372  Register address,
373  Register scratch,
374  SaveFPRegsMode fp_mode,
375  RememberedSetFinalAction and_then) {
376  Label done;
377  if (emit_debug_code()) {
378  Label ok;
379  JumpIfNotInNewSpace(object, scratch, &ok);
380  stop("Remembered set pointer is in new space");
381  bind(&ok);
382  }
383  // Load store buffer top.
384  ExternalReference store_buffer =
385  ExternalReference::store_buffer_top(isolate());
386  li(t8, Operand(store_buffer));
387  ld(scratch, MemOperand(t8));
388  // Store pointer to buffer and increment buffer top.
389  sd(address, MemOperand(scratch));
390  Daddu(scratch, scratch, kPointerSize);
391  // Write back new top of buffer.
392  sd(scratch, MemOperand(t8));
393  // Call stub on end of buffer.
394  // Check for end of buffer.
395  And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit));
396  DCHECK(!scratch.is(t8));
397  if (and_then == kFallThroughAtEnd) {
398  Branch(&done, eq, t8, Operand(zero_reg));
399  } else {
400  DCHECK(and_then == kReturnAtEnd);
401  Ret(eq, t8, Operand(zero_reg));
402  }
403  push(ra);
404  StoreBufferOverflowStub store_buffer_overflow(isolate(), fp_mode);
405  CallStub(&store_buffer_overflow);
406  pop(ra);
407  bind(&done);
408  if (and_then == kReturnAtEnd) {
409  Ret();
410  }
411 }
412 
413 
414 // -----------------------------------------------------------------------------
415 // Allocation support.
416 
417 
418 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
419  Register scratch,
420  Label* miss) {
421  Label same_contexts;
422 
423  DCHECK(!holder_reg.is(scratch));
424  DCHECK(!holder_reg.is(at));
425  DCHECK(!scratch.is(at));
426 
427  // Load current lexical context from the stack frame.
428  ld(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
429  // In debug mode, make sure the lexical context is set.
430 #ifdef DEBUG
431  Check(ne, kWeShouldNotHaveAnEmptyLexicalContext,
432  scratch, Operand(zero_reg));
433 #endif
434 
435  // Load the native context of the current context.
436  int offset =
437  Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
438  ld(scratch, FieldMemOperand(scratch, offset));
439  ld(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
440 
441  // Check the context is a native context.
442  if (emit_debug_code()) {
443  push(holder_reg); // Temporarily save holder on the stack.
444  // Read the first word and compare to the native_context_map.
445  ld(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
446  LoadRoot(at, Heap::kNativeContextMapRootIndex);
447  Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
448  holder_reg, Operand(at));
449  pop(holder_reg); // Restore holder.
450  }
451 
452  // Check if both contexts are the same.
453  ld(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
454  Branch(&same_contexts, eq, scratch, Operand(at));
455 
456  // Check the context is a native context.
457  if (emit_debug_code()) {
458  push(holder_reg); // Temporarily save holder on the stack.
459  mov(holder_reg, at); // Move at to its holding place.
460  LoadRoot(at, Heap::kNullValueRootIndex);
461  Check(ne, kJSGlobalProxyContextShouldNotBeNull,
462  holder_reg, Operand(at));
463 
464  ld(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
465  LoadRoot(at, Heap::kNativeContextMapRootIndex);
466  Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
467  holder_reg, Operand(at));
468  // Restore at is not needed. at is reloaded below.
469  pop(holder_reg); // Restore holder.
470  // Restore at to holder's context.
471  ld(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
472  }
473 
474  // Check that the security token in the calling global object is
475  // compatible with the security token in the receiving global
476  // object.
477  int token_offset = Context::kHeaderSize +
478  Context::SECURITY_TOKEN_INDEX * kPointerSize;
479 
480  ld(scratch, FieldMemOperand(scratch, token_offset));
481  ld(at, FieldMemOperand(at, token_offset));
482  Branch(miss, ne, scratch, Operand(at));
483 
484  bind(&same_contexts);
485 }
486 
487 
488 // Compute the hash code from the untagged key. This must be kept in sync with
489 // ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
490 // code-stub-hydrogen.cc
491 void MacroAssembler::GetNumberHash(Register reg0, Register scratch) {
492  // First of all we assign the hash seed to scratch.
493  LoadRoot(scratch, Heap::kHashSeedRootIndex);
494  SmiUntag(scratch);
495 
496  // Xor original key with a seed.
497  xor_(reg0, reg0, scratch);
498 
499  // Compute the hash code from the untagged key. This must be kept in sync
500  // with ComputeIntegerHash in utils.h.
501  //
502  // hash = ~hash + (hash << 15);
503  // The algorithm uses 32-bit integer values.
504  nor(scratch, reg0, zero_reg);
505  sll(at, reg0, 15);
506  addu(reg0, scratch, at);
507 
508  // hash = hash ^ (hash >> 12);
509  srl(at, reg0, 12);
510  xor_(reg0, reg0, at);
511 
512  // hash = hash + (hash << 2);
513  sll(at, reg0, 2);
514  addu(reg0, reg0, at);
515 
516  // hash = hash ^ (hash >> 4);
517  srl(at, reg0, 4);
518  xor_(reg0, reg0, at);
519 
520  // hash = hash * 2057;
521  sll(scratch, reg0, 11);
522  sll(at, reg0, 3);
523  addu(reg0, reg0, at);
524  addu(reg0, reg0, scratch);
525 
526  // hash = hash ^ (hash >> 16);
527  srl(at, reg0, 16);
528  xor_(reg0, reg0, at);
529 }
530 
531 
532 void MacroAssembler::LoadFromNumberDictionary(Label* miss,
533  Register elements,
534  Register key,
535  Register result,
536  Register reg0,
537  Register reg1,
538  Register reg2) {
539  // Register use:
540  //
541  // elements - holds the slow-case elements of the receiver on entry.
542  // Unchanged unless 'result' is the same register.
543  //
544  // key - holds the smi key on entry.
545  // Unchanged unless 'result' is the same register.
546  //
547  //
548  // result - holds the result on exit if the load succeeded.
549  // Allowed to be the same as 'key' or 'result'.
550  // Unchanged on bailout so 'key' or 'result' can be used
551  // in further computation.
552  //
553  // Scratch registers:
554  //
555  // reg0 - holds the untagged key on entry and holds the hash once computed.
556  //
557  // reg1 - Used to hold the capacity mask of the dictionary.
558  //
559  // reg2 - Used for the index into the dictionary.
560  // at - Temporary (avoid MacroAssembler instructions also using 'at').
561  Label done;
562 
563  GetNumberHash(reg0, reg1);
564 
565  // Compute the capacity mask.
566  ld(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset));
567  SmiUntag(reg1, reg1);
568  Dsubu(reg1, reg1, Operand(1));
569 
570  // Generate an unrolled loop that performs a few probes before giving up.
571  for (int i = 0; i < kNumberDictionaryProbes; i++) {
572  // Use reg2 for index calculations and keep the hash intact in reg0.
573  mov(reg2, reg0);
574  // Compute the masked index: (hash + i + i * i) & mask.
575  if (i > 0) {
576  Daddu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i)));
577  }
578  and_(reg2, reg2, reg1);
579 
580  // Scale the index by multiplying by the element size.
581  DCHECK(SeededNumberDictionary::kEntrySize == 3);
582  dsll(at, reg2, 1); // 2x.
583  daddu(reg2, reg2, at); // reg2 = reg2 * 3.
584 
585  // Check if the key is identical to the name.
586  dsll(at, reg2, kPointerSizeLog2);
587  daddu(reg2, elements, at);
588 
589  ld(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset));
590  if (i != kNumberDictionaryProbes - 1) {
591  Branch(&done, eq, key, Operand(at));
592  } else {
593  Branch(miss, ne, key, Operand(at));
594  }
595  }
596 
597  bind(&done);
598  // Check that the value is a normal property.
599  // reg2: elements + (index * kPointerSize).
600  const int kDetailsOffset =
601  SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
602  ld(reg1, FieldMemOperand(reg2, kDetailsOffset));
603  And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
604  Branch(miss, ne, at, Operand(zero_reg));
605 
606  // Get the value at the masked, scaled index and return.
607  const int kValueOffset =
608  SeededNumberDictionary::kElementsStartOffset + kPointerSize;
609  ld(result, FieldMemOperand(reg2, kValueOffset));
610 }
611 
612 
613 // ---------------------------------------------------------------------------
614 // Instruction macros.
615 
616 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) {
617  if (rt.is_reg()) {
618  addu(rd, rs, rt.rm());
619  } else {
620  if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
621  addiu(rd, rs, rt.imm64_);
622  } else {
623  // li handles the relocation.
624  DCHECK(!rs.is(at));
625  li(at, rt);
626  addu(rd, rs, at);
627  }
628  }
629 }
630 
631 
632 void MacroAssembler::Daddu(Register rd, Register rs, const Operand& rt) {
633  if (rt.is_reg()) {
634  daddu(rd, rs, rt.rm());
635  } else {
636  if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
637  daddiu(rd, rs, rt.imm64_);
638  } else {
639  // li handles the relocation.
640  DCHECK(!rs.is(at));
641  li(at, rt);
642  daddu(rd, rs, at);
643  }
644  }
645 }
646 
647 
648 void MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) {
649  if (rt.is_reg()) {
650  subu(rd, rs, rt.rm());
651  } else {
652  if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
653  addiu(rd, rs, -rt.imm64_); // No subiu instr, use addiu(x, y, -imm).
654  } else {
655  // li handles the relocation.
656  DCHECK(!rs.is(at));
657  li(at, rt);
658  subu(rd, rs, at);
659  }
660  }
661 }
662 
663 
664 void MacroAssembler::Dsubu(Register rd, Register rs, const Operand& rt) {
665  if (rt.is_reg()) {
666  dsubu(rd, rs, rt.rm());
667  } else {
668  if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
669  daddiu(rd, rs, -rt.imm64_); // No subiu instr, use addiu(x, y, -imm).
670  } else {
671  // li handles the relocation.
672  DCHECK(!rs.is(at));
673  li(at, rt);
674  dsubu(rd, rs, at);
675  }
676  }
677 }
678 
679 
680 void MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) {
681  if (rt.is_reg()) {
682  mul(rd, rs, rt.rm());
683  } else {
684  // li handles the relocation.
685  DCHECK(!rs.is(at));
686  li(at, rt);
687  mul(rd, rs, at);
688  }
689 }
690 
691 
692 void MacroAssembler::Mulh(Register rd, Register rs, const Operand& rt) {
693  if (rt.is_reg()) {
694  if (kArchVariant != kMips64r6) {
695  mult(rs, rt.rm());
696  mfhi(rd);
697  } else {
698  muh(rd, rs, rt.rm());
699  }
700  } else {
701  // li handles the relocation.
702  DCHECK(!rs.is(at));
703  li(at, rt);
704  if (kArchVariant != kMips64r6) {
705  mult(rs, at);
706  mfhi(rd);
707  } else {
708  muh(rd, rs, at);
709  }
710  }
711 }
712 
713 
714 void MacroAssembler::Dmul(Register rd, Register rs, const Operand& rt) {
715  if (rt.is_reg()) {
716  if (kArchVariant == kMips64r6) {
717  dmul(rd, rs, rt.rm());
718  } else {
719  dmult(rs, rt.rm());
720  mflo(rd);
721  }
722  } else {
723  // li handles the relocation.
724  DCHECK(!rs.is(at));
725  li(at, rt);
726  if (kArchVariant == kMips64r6) {
727  dmul(rd, rs, at);
728  } else {
729  dmult(rs, at);
730  mflo(rd);
731  }
732  }
733 }
734 
735 
736 void MacroAssembler::Dmulh(Register rd, Register rs, const Operand& rt) {
737  if (rt.is_reg()) {
738  if (kArchVariant == kMips64r6) {
739  dmuh(rd, rs, rt.rm());
740  } else {
741  dmult(rs, rt.rm());
742  mfhi(rd);
743  }
744  } else {
745  // li handles the relocation.
746  DCHECK(!rs.is(at));
747  li(at, rt);
748  if (kArchVariant == kMips64r6) {
749  dmuh(rd, rs, at);
750  } else {
751  dmult(rs, at);
752  mfhi(rd);
753  }
754  }
755 }
756 
757 
758 void MacroAssembler::Mult(Register rs, const Operand& rt) {
759  if (rt.is_reg()) {
760  mult(rs, rt.rm());
761  } else {
762  // li handles the relocation.
763  DCHECK(!rs.is(at));
764  li(at, rt);
765  mult(rs, at);
766  }
767 }
768 
769 
770 void MacroAssembler::Dmult(Register rs, const Operand& rt) {
771  if (rt.is_reg()) {
772  dmult(rs, rt.rm());
773  } else {
774  // li handles the relocation.
775  DCHECK(!rs.is(at));
776  li(at, rt);
777  dmult(rs, at);
778  }
779 }
780 
781 
782 void MacroAssembler::Multu(Register rs, const Operand& rt) {
783  if (rt.is_reg()) {
784  multu(rs, rt.rm());
785  } else {
786  // li handles the relocation.
787  DCHECK(!rs.is(at));
788  li(at, rt);
789  multu(rs, at);
790  }
791 }
792 
793 
794 void MacroAssembler::Dmultu(Register rs, const Operand& rt) {
795  if (rt.is_reg()) {
796  dmultu(rs, rt.rm());
797  } else {
798  // li handles the relocation.
799  DCHECK(!rs.is(at));
800  li(at, rt);
801  dmultu(rs, at);
802  }
803 }
804 
805 
806 void MacroAssembler::Div(Register rs, const Operand& rt) {
807  if (rt.is_reg()) {
808  div(rs, rt.rm());
809  } else {
810  // li handles the relocation.
811  DCHECK(!rs.is(at));
812  li(at, rt);
813  div(rs, at);
814  }
815 }
816 
817 
818 void MacroAssembler::Ddiv(Register rs, const Operand& rt) {
819  if (rt.is_reg()) {
820  ddiv(rs, rt.rm());
821  } else {
822  // li handles the relocation.
823  DCHECK(!rs.is(at));
824  li(at, rt);
825  ddiv(rs, at);
826  }
827 }
828 
829 
830 void MacroAssembler::Ddiv(Register rd, Register rs, const Operand& rt) {
831  if (kArchVariant != kMips64r6) {
832  if (rt.is_reg()) {
833  ddiv(rs, rt.rm());
834  mflo(rd);
835  } else {
836  // li handles the relocation.
837  DCHECK(!rs.is(at));
838  li(at, rt);
839  ddiv(rs, at);
840  mflo(rd);
841  }
842  } else {
843  if (rt.is_reg()) {
844  ddiv(rd, rs, rt.rm());
845  } else {
846  // li handles the relocation.
847  DCHECK(!rs.is(at));
848  li(at, rt);
849  ddiv(rd, rs, at);
850  }
851  }
852 }
853 
854 
855 void MacroAssembler::Divu(Register rs, const Operand& rt) {
856  if (rt.is_reg()) {
857  divu(rs, rt.rm());
858  } else {
859  // li handles the relocation.
860  DCHECK(!rs.is(at));
861  li(at, rt);
862  divu(rs, at);
863  }
864 }
865 
866 
867 void MacroAssembler::Ddivu(Register rs, const Operand& rt) {
868  if (rt.is_reg()) {
869  ddivu(rs, rt.rm());
870  } else {
871  // li handles the relocation.
872  DCHECK(!rs.is(at));
873  li(at, rt);
874  ddivu(rs, at);
875  }
876 }
877 
878 
879 void MacroAssembler::Dmod(Register rd, Register rs, const Operand& rt) {
880  if (kArchVariant != kMips64r6) {
881  if (rt.is_reg()) {
882  ddiv(rs, rt.rm());
883  mfhi(rd);
884  } else {
885  // li handles the relocation.
886  DCHECK(!rs.is(at));
887  li(at, rt);
888  ddiv(rs, at);
889  mfhi(rd);
890  }
891  } else {
892  if (rt.is_reg()) {
893  dmod(rd, rs, rt.rm());
894  } else {
895  // li handles the relocation.
896  DCHECK(!rs.is(at));
897  li(at, rt);
898  dmod(rd, rs, at);
899  }
900  }
901 }
902 
903 
904 void MacroAssembler::And(Register rd, Register rs, const Operand& rt) {
905  if (rt.is_reg()) {
906  and_(rd, rs, rt.rm());
907  } else {
908  if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
909  andi(rd, rs, rt.imm64_);
910  } else {
911  // li handles the relocation.
912  DCHECK(!rs.is(at));
913  li(at, rt);
914  and_(rd, rs, at);
915  }
916  }
917 }
918 
919 
920 void MacroAssembler::Or(Register rd, Register rs, const Operand& rt) {
921  if (rt.is_reg()) {
922  or_(rd, rs, rt.rm());
923  } else {
924  if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
925  ori(rd, rs, rt.imm64_);
926  } else {
927  // li handles the relocation.
928  DCHECK(!rs.is(at));
929  li(at, rt);
930  or_(rd, rs, at);
931  }
932  }
933 }
934 
935 
936 void MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) {
937  if (rt.is_reg()) {
938  xor_(rd, rs, rt.rm());
939  } else {
940  if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
941  xori(rd, rs, rt.imm64_);
942  } else {
943  // li handles the relocation.
944  DCHECK(!rs.is(at));
945  li(at, rt);
946  xor_(rd, rs, at);
947  }
948  }
949 }
950 
951 
952 void MacroAssembler::Nor(Register rd, Register rs, const Operand& rt) {
953  if (rt.is_reg()) {
954  nor(rd, rs, rt.rm());
955  } else {
956  // li handles the relocation.
957  DCHECK(!rs.is(at));
958  li(at, rt);
959  nor(rd, rs, at);
960  }
961 }
962 
963 
964 void MacroAssembler::Neg(Register rs, const Operand& rt) {
965  DCHECK(rt.is_reg());
966  DCHECK(!at.is(rs));
967  DCHECK(!at.is(rt.rm()));
968  li(at, -1);
969  xor_(rs, rt.rm(), at);
970 }
971 
972 
973 void MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) {
974  if (rt.is_reg()) {
975  slt(rd, rs, rt.rm());
976  } else {
977  if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
978  slti(rd, rs, rt.imm64_);
979  } else {
980  // li handles the relocation.
981  DCHECK(!rs.is(at));
982  li(at, rt);
983  slt(rd, rs, at);
984  }
985  }
986 }
987 
988 
989 void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) {
990  if (rt.is_reg()) {
991  sltu(rd, rs, rt.rm());
992  } else {
993  if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
994  sltiu(rd, rs, rt.imm64_);
995  } else {
996  // li handles the relocation.
997  DCHECK(!rs.is(at));
998  li(at, rt);
999  sltu(rd, rs, at);
1000  }
1001  }
1002 }
1003 
1004 
1005 void MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) {
1006  if (kArchVariant == kMips64r2) {
1007  if (rt.is_reg()) {
1008  rotrv(rd, rs, rt.rm());
1009  } else {
1010  rotr(rd, rs, rt.imm64_);
1011  }
1012  } else {
1013  if (rt.is_reg()) {
1014  subu(at, zero_reg, rt.rm());
1015  sllv(at, rs, at);
1016  srlv(rd, rs, rt.rm());
1017  or_(rd, rd, at);
1018  } else {
1019  if (rt.imm64_ == 0) {
1020  srl(rd, rs, 0);
1021  } else {
1022  srl(at, rs, rt.imm64_);
1023  sll(rd, rs, (0x20 - rt.imm64_) & 0x1f);
1024  or_(rd, rd, at);
1025  }
1026  }
1027  }
1028 }
1029 
1030 
1031 void MacroAssembler::Dror(Register rd, Register rs, const Operand& rt) {
1032  if (rt.is_reg()) {
1033  drotrv(rd, rs, rt.rm());
1034  } else {
1035  drotr(rd, rs, rt.imm64_);
1036  }
1037 }
1038 
1039 
1040 void MacroAssembler::Pref(int32_t hint, const MemOperand& rs) {
1041  pref(hint, rs);
1042 }
1043 
1044 
1045 // ------------Pseudo-instructions-------------
1046 
1047 void MacroAssembler::Ulw(Register rd, const MemOperand& rs) {
1048  lwr(rd, rs);
1049  lwl(rd, MemOperand(rs.rm(), rs.offset() + 3));
1050 }
1051 
1052 
1053 void MacroAssembler::Usw(Register rd, const MemOperand& rs) {
1054  swr(rd, rs);
1055  swl(rd, MemOperand(rs.rm(), rs.offset() + 3));
1056 }
1057 
1058 
1059 // Do 64-bit load from unaligned address. Note this only handles
1060 // the specific case of 32-bit aligned, but not 64-bit aligned.
1061 void MacroAssembler::Uld(Register rd, const MemOperand& rs, Register scratch) {
1062  // Assert fail if the offset from start of object IS actually aligned.
1063  // ONLY use with known misalignment, since there is performance cost.
1064  DCHECK((rs.offset() + kHeapObjectTag) & (kPointerSize - 1));
1065  // TODO(plind): endian dependency.
1066  lwu(rd, rs);
1067  lw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2));
1068  dsll32(scratch, scratch, 0);
1069  Daddu(rd, rd, scratch);
1070 }
1071 
1072 
1073 // Do 64-bit store to unaligned address. Note this only handles
1074 // the specific case of 32-bit aligned, but not 64-bit aligned.
1075 void MacroAssembler::Usd(Register rd, const MemOperand& rs, Register scratch) {
1076  // Assert fail if the offset from start of object IS actually aligned.
1077  // ONLY use with known misalignment, since there is performance cost.
1078  DCHECK((rs.offset() + kHeapObjectTag) & (kPointerSize - 1));
1079  // TODO(plind): endian dependency.
1080  sw(rd, rs);
1081  dsrl32(scratch, rd, 0);
1082  sw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2));
1083 }
1084 
1085 
1086 void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) {
1088  if (value->IsSmi()) {
1089  li(dst, Operand(value), mode);
1090  } else {
1091  DCHECK(value->IsHeapObject());
1092  if (isolate()->heap()->InNewSpace(*value)) {
1093  Handle<Cell> cell = isolate()->factory()->NewCell(value);
1094  li(dst, Operand(cell));
1095  ld(dst, FieldMemOperand(dst, Cell::kValueOffset));
1096  } else {
1097  li(dst, Operand(value));
1098  }
1099  }
1100 }
1101 
1102 
1103 void MacroAssembler::li(Register rd, Operand j, LiFlags mode) {
1104  DCHECK(!j.is_reg());
1105  BlockTrampolinePoolScope block_trampoline_pool(this);
1106  if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) {
1107  // Normal load of an immediate value which does not need Relocation Info.
1108  if (is_int32(j.imm64_)) {
1109  if (is_int16(j.imm64_)) {
1110  daddiu(rd, zero_reg, (j.imm64_ & kImm16Mask));
1111  } else if (!(j.imm64_ & kHiMask)) {
1112  ori(rd, zero_reg, (j.imm64_ & kImm16Mask));
1113  } else if (!(j.imm64_ & kImm16Mask)) {
1114  lui(rd, (j.imm64_ >> kLuiShift) & kImm16Mask);
1115  } else {
1116  lui(rd, (j.imm64_ >> kLuiShift) & kImm16Mask);
1117  ori(rd, rd, (j.imm64_ & kImm16Mask));
1118  }
1119  } else {
1120  lui(rd, (j.imm64_ >> 48) & kImm16Mask);
1121  ori(rd, rd, (j.imm64_ >> 32) & kImm16Mask);
1122  dsll(rd, rd, 16);
1123  ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
1124  dsll(rd, rd, 16);
1125  ori(rd, rd, j.imm64_ & kImm16Mask);
1126  }
1127  } else if (MustUseReg(j.rmode_)) {
1128  RecordRelocInfo(j.rmode_, j.imm64_);
1129  lui(rd, (j.imm64_ >> 32) & kImm16Mask);
1130  ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
1131  dsll(rd, rd, 16);
1132  ori(rd, rd, j.imm64_ & kImm16Mask);
1133  } else if (mode == ADDRESS_LOAD) {
1134  // We always need the same number of instructions as we may need to patch
1135  // this code to load another value which may need all 4 instructions.
1136  lui(rd, (j.imm64_ >> 32) & kImm16Mask);
1137  ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
1138  dsll(rd, rd, 16);
1139  ori(rd, rd, j.imm64_ & kImm16Mask);
1140  } else {
1141  lui(rd, (j.imm64_ >> 48) & kImm16Mask);
1142  ori(rd, rd, (j.imm64_ >> 32) & kImm16Mask);
1143  dsll(rd, rd, 16);
1144  ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
1145  dsll(rd, rd, 16);
1146  ori(rd, rd, j.imm64_ & kImm16Mask);
1147  }
1148 }
1149 
1150 
1151 void MacroAssembler::MultiPush(RegList regs) {
1152  int16_t num_to_push = NumberOfBitsSet(regs);
1153  int16_t stack_offset = num_to_push * kPointerSize;
1154 
1155  Dsubu(sp, sp, Operand(stack_offset));
1156  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
1157  if ((regs & (1 << i)) != 0) {
1158  stack_offset -= kPointerSize;
1159  sd(ToRegister(i), MemOperand(sp, stack_offset));
1160  }
1161  }
1162 }
1163 
1164 
1165 void MacroAssembler::MultiPushReversed(RegList regs) {
1166  int16_t num_to_push = NumberOfBitsSet(regs);
1167  int16_t stack_offset = num_to_push * kPointerSize;
1168 
1169  Dsubu(sp, sp, Operand(stack_offset));
1170  for (int16_t i = 0; i < kNumRegisters; i++) {
1171  if ((regs & (1 << i)) != 0) {
1172  stack_offset -= kPointerSize;
1173  sd(ToRegister(i), MemOperand(sp, stack_offset));
1174  }
1175  }
1176 }
1177 
1178 
1179 void MacroAssembler::MultiPop(RegList regs) {
1180  int16_t stack_offset = 0;
1181 
1182  for (int16_t i = 0; i < kNumRegisters; i++) {
1183  if ((regs & (1 << i)) != 0) {
1184  ld(ToRegister(i), MemOperand(sp, stack_offset));
1185  stack_offset += kPointerSize;
1186  }
1187  }
1188  daddiu(sp, sp, stack_offset);
1189 }
1190 
1191 
1192 void MacroAssembler::MultiPopReversed(RegList regs) {
1193  int16_t stack_offset = 0;
1194 
1195  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
1196  if ((regs & (1 << i)) != 0) {
1197  ld(ToRegister(i), MemOperand(sp, stack_offset));
1198  stack_offset += kPointerSize;
1199  }
1200  }
1201  daddiu(sp, sp, stack_offset);
1202 }
1203 
1204 
1205 void MacroAssembler::MultiPushFPU(RegList regs) {
1206  int16_t num_to_push = NumberOfBitsSet(regs);
1207  int16_t stack_offset = num_to_push * kDoubleSize;
1208 
1209  Dsubu(sp, sp, Operand(stack_offset));
1210  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
1211  if ((regs & (1 << i)) != 0) {
1212  stack_offset -= kDoubleSize;
1213  sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1214  }
1215  }
1216 }
1217 
1218 
1219 void MacroAssembler::MultiPushReversedFPU(RegList regs) {
1220  int16_t num_to_push = NumberOfBitsSet(regs);
1221  int16_t stack_offset = num_to_push * kDoubleSize;
1222 
1223  Dsubu(sp, sp, Operand(stack_offset));
1224  for (int16_t i = 0; i < kNumRegisters; i++) {
1225  if ((regs & (1 << i)) != 0) {
1226  stack_offset -= kDoubleSize;
1227  sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1228  }
1229  }
1230 }
1231 
1232 
1233 void MacroAssembler::MultiPopFPU(RegList regs) {
1234  int16_t stack_offset = 0;
1235 
1236  for (int16_t i = 0; i < kNumRegisters; i++) {
1237  if ((regs & (1 << i)) != 0) {
1238  ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1239  stack_offset += kDoubleSize;
1240  }
1241  }
1242  daddiu(sp, sp, stack_offset);
1243 }
1244 
1245 
1246 void MacroAssembler::MultiPopReversedFPU(RegList regs) {
1247  int16_t stack_offset = 0;
1248 
1249  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
1250  if ((regs & (1 << i)) != 0) {
1251  ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1252  stack_offset += kDoubleSize;
1253  }
1254  }
1255  daddiu(sp, sp, stack_offset);
1256 }
1257 
1258 
1259 void MacroAssembler::FlushICache(Register address, unsigned instructions) {
1260  RegList saved_regs = kJSCallerSaved | ra.bit();
1261  MultiPush(saved_regs);
1262  AllowExternalCallThatCantCauseGC scope(this);
1263 
1264  // Save to a0 in case address == a4.
1265  Move(a0, address);
1266  PrepareCallCFunction(2, a4);
1267 
1268  li(a1, instructions * kInstrSize);
1269  CallCFunction(ExternalReference::flush_icache_function(isolate()), 2);
1270  MultiPop(saved_regs);
1271 }
1272 
1273 
1274 void MacroAssembler::Ext(Register rt,
1275  Register rs,
1276  uint16_t pos,
1277  uint16_t size) {
1278  DCHECK(pos < 32);
1279  DCHECK(pos + size < 33);
1280  ext_(rt, rs, pos, size);
1281 }
1282 
1283 
1284 void MacroAssembler::Ins(Register rt,
1285  Register rs,
1286  uint16_t pos,
1287  uint16_t size) {
1288  DCHECK(pos < 32);
1289  DCHECK(pos + size <= 32);
1290  DCHECK(size != 0);
1291  ins_(rt, rs, pos, size);
1292 }
1293 
1294 
1295 void MacroAssembler::Cvt_d_uw(FPURegister fd,
1296  FPURegister fs,
1297  FPURegister scratch) {
1298  // Move the data from fs to t8.
1299  mfc1(t8, fs);
1300  Cvt_d_uw(fd, t8, scratch);
1301 }
1302 
1303 
1304 void MacroAssembler::Cvt_d_uw(FPURegister fd,
1305  Register rs,
1306  FPURegister scratch) {
1307  // Convert rs to a FP value in fd (and fd + 1).
1308  // We do this by converting rs minus the MSB to avoid sign conversion,
1309  // then adding 2^31 to the result (if needed).
1310 
1311  DCHECK(!fd.is(scratch));
1312  DCHECK(!rs.is(t9));
1313  DCHECK(!rs.is(at));
1314 
1315  // Save rs's MSB to t9.
1316  Ext(t9, rs, 31, 1);
1317  // Remove rs's MSB.
1318  Ext(at, rs, 0, 31);
1319  // Move the result to fd.
1320  mtc1(at, fd);
1321  mthc1(zero_reg, fd);
1322 
1323  // Convert fd to a real FP value.
1324  cvt_d_w(fd, fd);
1325 
1326  Label conversion_done;
1327 
1328  // If rs's MSB was 0, it's done.
1329  // Otherwise we need to add that to the FP register.
1330  Branch(&conversion_done, eq, t9, Operand(zero_reg));
1331 
1332  // Load 2^31 into f20 as its float representation.
1333  li(at, 0x41E00000);
1334  mtc1(zero_reg, scratch);
1335  mthc1(at, scratch);
1336  // Add it to fd.
1337  add_d(fd, fd, scratch);
1338 
1339  bind(&conversion_done);
1340 }
1341 
1342 
1343 void MacroAssembler::Round_l_d(FPURegister fd, FPURegister fs) {
1344  round_l_d(fd, fs);
1345 }
1346 
1347 
1348 void MacroAssembler::Floor_l_d(FPURegister fd, FPURegister fs) {
1349  floor_l_d(fd, fs);
1350 }
1351 
1352 
1353 void MacroAssembler::Ceil_l_d(FPURegister fd, FPURegister fs) {
1354  ceil_l_d(fd, fs);
1355 }
1356 
1357 
1358 void MacroAssembler::Trunc_l_d(FPURegister fd, FPURegister fs) {
1359  trunc_l_d(fd, fs);
1360 }
1361 
1362 
1363 void MacroAssembler::Trunc_l_ud(FPURegister fd,
1364  FPURegister fs,
1365  FPURegister scratch) {
1366  // Load to GPR.
1367  dmfc1(t8, fs);
1368  // Reset sign bit.
1369  li(at, 0x7fffffffffffffff);
1370  and_(t8, t8, at);
1371  dmtc1(t8, fs);
1372  trunc_l_d(fd, fs);
1373 }
1374 
1375 
1376 void MacroAssembler::Trunc_uw_d(FPURegister fd,
1377  FPURegister fs,
1378  FPURegister scratch) {
1379  Trunc_uw_d(fs, t8, scratch);
1380  mtc1(t8, fd);
1381 }
1382 
1383 
1384 void MacroAssembler::Trunc_w_d(FPURegister fd, FPURegister fs) {
1385  trunc_w_d(fd, fs);
1386 }
1387 
1388 
1389 void MacroAssembler::Round_w_d(FPURegister fd, FPURegister fs) {
1390  round_w_d(fd, fs);
1391 }
1392 
1393 
1394 void MacroAssembler::Floor_w_d(FPURegister fd, FPURegister fs) {
1395  floor_w_d(fd, fs);
1396 }
1397 
1398 
1399 void MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) {
1400  ceil_w_d(fd, fs);
1401 }
1402 
1403 
1404 void MacroAssembler::Trunc_uw_d(FPURegister fd,
1405  Register rs,
1406  FPURegister scratch) {
1407  DCHECK(!fd.is(scratch));
1408  DCHECK(!rs.is(at));
1409 
1410  // Load 2^31 into scratch as its float representation.
1411  li(at, 0x41E00000);
1412  mtc1(zero_reg, scratch);
1413  mthc1(at, scratch);
1414  // Test if scratch > fd.
1415  // If fd < 2^31 we can convert it normally.
1416  Label simple_convert;
1417  BranchF(&simple_convert, NULL, lt, fd, scratch);
1418 
1419  // First we subtract 2^31 from fd, then trunc it to rs
1420  // and add 2^31 to rs.
1421  sub_d(scratch, fd, scratch);
1422  trunc_w_d(scratch, scratch);
1423  mfc1(rs, scratch);
1424  Or(rs, rs, 1 << 31);
1425 
1426  Label done;
1427  Branch(&done);
1428  // Simple conversion.
1429  bind(&simple_convert);
1430  trunc_w_d(scratch, fd);
1431  mfc1(rs, scratch);
1432 
1433  bind(&done);
1434 }
1435 
1436 
1437 void MacroAssembler::Madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
1438  FPURegister ft, FPURegister scratch) {
1439  if (0) { // TODO(plind): find reasonable arch-variant symbol names.
1440  madd_d(fd, fr, fs, ft);
1441  } else {
1442  // Can not change source regs's value.
1443  DCHECK(!fr.is(scratch) && !fs.is(scratch) && !ft.is(scratch));
1444  mul_d(scratch, fs, ft);
1445  add_d(fd, fr, scratch);
1446  }
1447 }
1448 
1449 
1450 void MacroAssembler::BranchF(Label* target,
1451  Label* nan,
1452  Condition cc,
1453  FPURegister cmp1,
1454  FPURegister cmp2,
1455  BranchDelaySlot bd) {
1456  BlockTrampolinePoolScope block_trampoline_pool(this);
1457  if (cc == al) {
1458  Branch(bd, target);
1459  return;
1460  }
1461 
1462  DCHECK(nan || target);
1463  // Check for unordered (NaN) cases.
1464  if (nan) {
1465  if (kArchVariant != kMips64r6) {
1466  c(UN, D, cmp1, cmp2);
1467  bc1t(nan);
1468  } else {
1469  // Use f31 for comparison result. It has to be unavailable to lithium
1470  // register allocator.
1471  DCHECK(!cmp1.is(f31) && !cmp2.is(f31));
1472  cmp(UN, L, f31, cmp1, cmp2);
1473  bc1nez(nan, f31);
1474  }
1475  }
1476 
1477  if (kArchVariant != kMips64r6) {
1478  if (target) {
1479  // Here NaN cases were either handled by this function or are assumed to
1480  // have been handled by the caller.
1481  switch (cc) {
1482  case lt:
1483  c(OLT, D, cmp1, cmp2);
1484  bc1t(target);
1485  break;
1486  case gt:
1487  c(ULE, D, cmp1, cmp2);
1488  bc1f(target);
1489  break;
1490  case ge:
1491  c(ULT, D, cmp1, cmp2);
1492  bc1f(target);
1493  break;
1494  case le:
1495  c(OLE, D, cmp1, cmp2);
1496  bc1t(target);
1497  break;
1498  case eq:
1499  c(EQ, D, cmp1, cmp2);
1500  bc1t(target);
1501  break;
1502  case ueq:
1503  c(UEQ, D, cmp1, cmp2);
1504  bc1t(target);
1505  break;
1506  case ne:
1507  c(EQ, D, cmp1, cmp2);
1508  bc1f(target);
1509  break;
1510  case nue:
1511  c(UEQ, D, cmp1, cmp2);
1512  bc1f(target);
1513  break;
1514  default:
1515  CHECK(0);
1516  }
1517  }
1518  } else {
1519  if (target) {
1520  // Here NaN cases were either handled by this function or are assumed to
1521  // have been handled by the caller.
1522  // Unsigned conditions are treated as their signed counterpart.
1523  // Use f31 for comparison result, it is valid in fp64 (FR = 1) mode.
1524  DCHECK(!cmp1.is(f31) && !cmp2.is(f31));
1525  switch (cc) {
1526  case lt:
1527  cmp(OLT, L, f31, cmp1, cmp2);
1528  bc1nez(target, f31);
1529  break;
1530  case gt:
1531  cmp(ULE, L, f31, cmp1, cmp2);
1532  bc1eqz(target, f31);
1533  break;
1534  case ge:
1535  cmp(ULT, L, f31, cmp1, cmp2);
1536  bc1eqz(target, f31);
1537  break;
1538  case le:
1539  cmp(OLE, L, f31, cmp1, cmp2);
1540  bc1nez(target, f31);
1541  break;
1542  case eq:
1543  cmp(EQ, L, f31, cmp1, cmp2);
1544  bc1nez(target, f31);
1545  break;
1546  case ueq:
1547  cmp(UEQ, L, f31, cmp1, cmp2);
1548  bc1nez(target, f31);
1549  break;
1550  case ne:
1551  cmp(EQ, L, f31, cmp1, cmp2);
1552  bc1eqz(target, f31);
1553  break;
1554  case nue:
1555  cmp(UEQ, L, f31, cmp1, cmp2);
1556  bc1eqz(target, f31);
1557  break;
1558  default:
1559  CHECK(0);
1560  }
1561  }
1562  }
1563 
1564  if (bd == PROTECT) {
1565  nop();
1566  }
1567 }
1568 
1569 
1570 void MacroAssembler::Move(FPURegister dst, double imm) {
1571  static const DoubleRepresentation minus_zero(-0.0);
1572  static const DoubleRepresentation zero(0.0);
1573  DoubleRepresentation value_rep(imm);
1574  // Handle special values first.
1575  bool force_load = dst.is(kDoubleRegZero);
1576  if (value_rep == zero && !force_load) {
1577  mov_d(dst, kDoubleRegZero);
1578  } else if (value_rep == minus_zero && !force_load) {
1579  neg_d(dst, kDoubleRegZero);
1580  } else {
1581  uint32_t lo, hi;
1582  DoubleAsTwoUInt32(imm, &lo, &hi);
1583  // Move the low part of the double into the lower bits of the corresponding
1584  // FPU register.
1585  if (lo != 0) {
1586  li(at, Operand(lo));
1587  mtc1(at, dst);
1588  } else {
1589  mtc1(zero_reg, dst);
1590  }
1591  // Move the high part of the double into the high bits of the corresponding
1592  // FPU register.
1593  if (hi != 0) {
1594  li(at, Operand(hi));
1595  mthc1(at, dst);
1596  } else {
1597  mthc1(zero_reg, dst);
1598  }
1599  }
1600 }
1601 
1602 
1603 void MacroAssembler::Movz(Register rd, Register rs, Register rt) {
1604  if (kArchVariant == kMips64r6) {
1605  Label done;
1606  Branch(&done, ne, rt, Operand(zero_reg));
1607  mov(rd, rs);
1608  bind(&done);
1609  } else {
1610  movz(rd, rs, rt);
1611  }
1612 }
1613 
1614 
1615 void MacroAssembler::Movn(Register rd, Register rs, Register rt) {
1616  if (kArchVariant == kMips64r6) {
1617  Label done;
1618  Branch(&done, eq, rt, Operand(zero_reg));
1619  mov(rd, rs);
1620  bind(&done);
1621  } else {
1622  movn(rd, rs, rt);
1623  }
1624 }
1625 
1626 
1627 void MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) {
1628  movt(rd, rs, cc);
1629 }
1630 
1631 
1632 void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) {
1633  movf(rd, rs, cc);
1634 }
1635 
1636 
1637 void MacroAssembler::Clz(Register rd, Register rs) {
1638  clz(rd, rs);
1639 }
1640 
1641 
1642 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
1643  Register result,
1644  DoubleRegister double_input,
1645  Register scratch,
1646  DoubleRegister double_scratch,
1647  Register except_flag,
1648  CheckForInexactConversion check_inexact) {
1649  DCHECK(!result.is(scratch));
1650  DCHECK(!double_input.is(double_scratch));
1651  DCHECK(!except_flag.is(scratch));
1652 
1653  Label done;
1654 
1655  // Clear the except flag (0 = no exception)
1656  mov(except_flag, zero_reg);
1657 
1658  // Test for values that can be exactly represented as a signed 32-bit integer.
1659  cvt_w_d(double_scratch, double_input);
1660  mfc1(result, double_scratch);
1661  cvt_d_w(double_scratch, double_scratch);
1662  BranchF(&done, NULL, eq, double_input, double_scratch);
1663 
1664  int32_t except_mask = kFCSRFlagMask; // Assume interested in all exceptions.
1665 
1666  if (check_inexact == kDontCheckForInexactConversion) {
1667  // Ignore inexact exceptions.
1668  except_mask &= ~kFCSRInexactFlagMask;
1669  }
1670 
1671  // Save FCSR.
1672  cfc1(scratch, FCSR);
1673  // Disable FPU exceptions.
1674  ctc1(zero_reg, FCSR);
1675 
1676  // Do operation based on rounding mode.
1677  switch (rounding_mode) {
1678  case kRoundToNearest:
1679  Round_w_d(double_scratch, double_input);
1680  break;
1681  case kRoundToZero:
1682  Trunc_w_d(double_scratch, double_input);
1683  break;
1684  case kRoundToPlusInf:
1685  Ceil_w_d(double_scratch, double_input);
1686  break;
1687  case kRoundToMinusInf:
1688  Floor_w_d(double_scratch, double_input);
1689  break;
1690  } // End of switch-statement.
1691 
1692  // Retrieve FCSR.
1693  cfc1(except_flag, FCSR);
1694  // Restore FCSR.
1695  ctc1(scratch, FCSR);
1696  // Move the converted value into the result register.
1697  mfc1(result, double_scratch);
1698 
1699  // Check for fpu exceptions.
1700  And(except_flag, except_flag, Operand(except_mask));
1701 
1702  bind(&done);
1703 }
1704 
1705 
1706 void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
1707  DoubleRegister double_input,
1708  Label* done) {
1709  DoubleRegister single_scratch = kLithiumScratchDouble.low();
1710  Register scratch = at;
1711  Register scratch2 = t9;
1712 
1713  // Clear cumulative exception flags and save the FCSR.
1714  cfc1(scratch2, FCSR);
1715  ctc1(zero_reg, FCSR);
1716  // Try a conversion to a signed integer.
1717  trunc_w_d(single_scratch, double_input);
1718  mfc1(result, single_scratch);
1719  // Retrieve and restore the FCSR.
1720  cfc1(scratch, FCSR);
1721  ctc1(scratch2, FCSR);
1722  // Check for overflow and NaNs.
1723  And(scratch,
1724  scratch,
1726  // If we had no exceptions we are done.
1727  Branch(done, eq, scratch, Operand(zero_reg));
1728 }
1729 
1730 
1731 void MacroAssembler::TruncateDoubleToI(Register result,
1732  DoubleRegister double_input) {
1733  Label done;
1734 
1735  TryInlineTruncateDoubleToI(result, double_input, &done);
1736 
1737  // If we fell through then inline version didn't succeed - call stub instead.
1738  push(ra);
1739  Dsubu(sp, sp, Operand(kDoubleSize)); // Put input on stack.
1740  sdc1(double_input, MemOperand(sp, 0));
1741 
1742  DoubleToIStub stub(isolate(), sp, result, 0, true, true);
1743  CallStub(&stub);
1744 
1745  Daddu(sp, sp, Operand(kDoubleSize));
1746  pop(ra);
1747 
1748  bind(&done);
1749 }
1750 
1751 
1752 void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) {
1753  Label done;
1754  DoubleRegister double_scratch = f12;
1755  DCHECK(!result.is(object));
1756 
1757  ldc1(double_scratch,
1758  MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag));
1759  TryInlineTruncateDoubleToI(result, double_scratch, &done);
1760 
1761  // If we fell through then inline version didn't succeed - call stub instead.
1762  push(ra);
1763  DoubleToIStub stub(isolate(),
1764  object,
1765  result,
1766  HeapNumber::kValueOffset - kHeapObjectTag,
1767  true,
1768  true);
1769  CallStub(&stub);
1770  pop(ra);
1771 
1772  bind(&done);
1773 }
1774 
1775 
1776 void MacroAssembler::TruncateNumberToI(Register object,
1777  Register result,
1778  Register heap_number_map,
1779  Register scratch,
1780  Label* not_number) {
1781  Label done;
1782  DCHECK(!result.is(object));
1783 
1784  UntagAndJumpIfSmi(result, object, &done);
1785  JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number);
1786  TruncateHeapNumberToI(result, object);
1787 
1788  bind(&done);
1789 }
1790 
1791 
1792 void MacroAssembler::GetLeastBitsFromSmi(Register dst,
1793  Register src,
1794  int num_least_bits) {
1795  // Ext(dst, src, kSmiTagSize, num_least_bits);
1796  SmiUntag(dst, src);
1797  And(dst, dst, Operand((1 << num_least_bits) - 1));
1798 }
1799 
1800 
1801 void MacroAssembler::GetLeastBitsFromInt32(Register dst,
1802  Register src,
1803  int num_least_bits) {
1804  DCHECK(!src.is(dst));
1805  And(dst, src, Operand((1 << num_least_bits) - 1));
1806 }
1807 
1808 
1809 // Emulated condtional branches do not emit a nop in the branch delay slot.
1810 //
1811 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct.
1812 #define BRANCH_ARGS_CHECK(cond, rs, rt) DCHECK( \
1813  (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \
1814  (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg))))
1815 
1816 
1817 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) {
1818  BranchShort(offset, bdslot);
1819 }
1820 
1821 
1822 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs,
1823  const Operand& rt,
1824  BranchDelaySlot bdslot) {
1825  BranchShort(offset, cond, rs, rt, bdslot);
1826 }
1827 
1828 
1829 void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) {
1830  if (L->is_bound()) {
1831  if (is_near(L)) {
1832  BranchShort(L, bdslot);
1833  } else {
1834  Jr(L, bdslot);
1835  }
1836  } else {
1837  if (is_trampoline_emitted()) {
1838  Jr(L, bdslot);
1839  } else {
1840  BranchShort(L, bdslot);
1841  }
1842  }
1843 }
1844 
1845 
1846 void MacroAssembler::Branch(Label* L, Condition cond, Register rs,
1847  const Operand& rt,
1848  BranchDelaySlot bdslot) {
1849  if (L->is_bound()) {
1850  if (is_near(L)) {
1851  BranchShort(L, cond, rs, rt, bdslot);
1852  } else {
1853  if (cond != cc_always) {
1854  Label skip;
1855  Condition neg_cond = NegateCondition(cond);
1856  BranchShort(&skip, neg_cond, rs, rt);
1857  Jr(L, bdslot);
1858  bind(&skip);
1859  } else {
1860  Jr(L, bdslot);
1861  }
1862  }
1863  } else {
1864  if (is_trampoline_emitted()) {
1865  if (cond != cc_always) {
1866  Label skip;
1867  Condition neg_cond = NegateCondition(cond);
1868  BranchShort(&skip, neg_cond, rs, rt);
1869  Jr(L, bdslot);
1870  bind(&skip);
1871  } else {
1872  Jr(L, bdslot);
1873  }
1874  } else {
1875  BranchShort(L, cond, rs, rt, bdslot);
1876  }
1877  }
1878 }
1879 
1880 
1881 void MacroAssembler::Branch(Label* L,
1882  Condition cond,
1883  Register rs,
1884  Heap::RootListIndex index,
1885  BranchDelaySlot bdslot) {
1886  LoadRoot(at, index);
1887  Branch(L, cond, rs, Operand(at), bdslot);
1888 }
1889 
1890 
1891 void MacroAssembler::BranchShort(int16_t offset, BranchDelaySlot bdslot) {
1892  b(offset);
1893 
1894  // Emit a nop in the branch delay slot if required.
1895  if (bdslot == PROTECT)
1896  nop();
1897 }
1898 
1899 
1900 void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs,
1901  const Operand& rt,
1902  BranchDelaySlot bdslot) {
1903  BRANCH_ARGS_CHECK(cond, rs, rt);
1904  DCHECK(!rs.is(zero_reg));
1905  Register r2 = no_reg;
1906  Register scratch = at;
1907 
1908  if (rt.is_reg()) {
1909  // NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or
1910  // rt.
1911  BlockTrampolinePoolScope block_trampoline_pool(this);
1912  r2 = rt.rm_;
1913  switch (cond) {
1914  case cc_always:
1915  b(offset);
1916  break;
1917  case eq:
1918  beq(rs, r2, offset);
1919  break;
1920  case ne:
1921  bne(rs, r2, offset);
1922  break;
1923  // Signed comparison.
1924  case greater:
1925  if (r2.is(zero_reg)) {
1926  bgtz(rs, offset);
1927  } else {
1928  slt(scratch, r2, rs);
1929  bne(scratch, zero_reg, offset);
1930  }
1931  break;
1932  case greater_equal:
1933  if (r2.is(zero_reg)) {
1934  bgez(rs, offset);
1935  } else {
1936  slt(scratch, rs, r2);
1937  beq(scratch, zero_reg, offset);
1938  }
1939  break;
1940  case less:
1941  if (r2.is(zero_reg)) {
1942  bltz(rs, offset);
1943  } else {
1944  slt(scratch, rs, r2);
1945  bne(scratch, zero_reg, offset);
1946  }
1947  break;
1948  case less_equal:
1949  if (r2.is(zero_reg)) {
1950  blez(rs, offset);
1951  } else {
1952  slt(scratch, r2, rs);
1953  beq(scratch, zero_reg, offset);
1954  }
1955  break;
1956  // Unsigned comparison.
1957  case Ugreater:
1958  if (r2.is(zero_reg)) {
1959  bgtz(rs, offset);
1960  } else {
1961  sltu(scratch, r2, rs);
1962  bne(scratch, zero_reg, offset);
1963  }
1964  break;
1965  case Ugreater_equal:
1966  if (r2.is(zero_reg)) {
1967  bgez(rs, offset);
1968  } else {
1969  sltu(scratch, rs, r2);
1970  beq(scratch, zero_reg, offset);
1971  }
1972  break;
1973  case Uless:
1974  if (r2.is(zero_reg)) {
1975  // No code needs to be emitted.
1976  return;
1977  } else {
1978  sltu(scratch, rs, r2);
1979  bne(scratch, zero_reg, offset);
1980  }
1981  break;
1982  case Uless_equal:
1983  if (r2.is(zero_reg)) {
1984  b(offset);
1985  } else {
1986  sltu(scratch, r2, rs);
1987  beq(scratch, zero_reg, offset);
1988  }
1989  break;
1990  default:
1991  UNREACHABLE();
1992  }
1993  } else {
1994  // Be careful to always use shifted_branch_offset only just before the
1995  // branch instruction, as the location will be remember for patching the
1996  // target.
1997  BlockTrampolinePoolScope block_trampoline_pool(this);
1998  switch (cond) {
1999  case cc_always:
2000  b(offset);
2001  break;
2002  case eq:
2003  // We don't want any other register but scratch clobbered.
2004  DCHECK(!scratch.is(rs));
2005  r2 = scratch;
2006  li(r2, rt);
2007  beq(rs, r2, offset);
2008  break;
2009  case ne:
2010  // We don't want any other register but scratch clobbered.
2011  DCHECK(!scratch.is(rs));
2012  r2 = scratch;
2013  li(r2, rt);
2014  bne(rs, r2, offset);
2015  break;
2016  // Signed comparison.
2017  case greater:
2018  if (rt.imm64_ == 0) {
2019  bgtz(rs, offset);
2020  } else {
2021  r2 = scratch;
2022  li(r2, rt);
2023  slt(scratch, r2, rs);
2024  bne(scratch, zero_reg, offset);
2025  }
2026  break;
2027  case greater_equal:
2028  if (rt.imm64_ == 0) {
2029  bgez(rs, offset);
2030  } else if (is_int16(rt.imm64_)) {
2031  slti(scratch, rs, rt.imm64_);
2032  beq(scratch, zero_reg, offset);
2033  } else {
2034  r2 = scratch;
2035  li(r2, rt);
2036  slt(scratch, rs, r2);
2037  beq(scratch, zero_reg, offset);
2038  }
2039  break;
2040  case less:
2041  if (rt.imm64_ == 0) {
2042  bltz(rs, offset);
2043  } else if (is_int16(rt.imm64_)) {
2044  slti(scratch, rs, rt.imm64_);
2045  bne(scratch, zero_reg, offset);
2046  } else {
2047  r2 = scratch;
2048  li(r2, rt);
2049  slt(scratch, rs, r2);
2050  bne(scratch, zero_reg, offset);
2051  }
2052  break;
2053  case less_equal:
2054  if (rt.imm64_ == 0) {
2055  blez(rs, offset);
2056  } else {
2057  r2 = scratch;
2058  li(r2, rt);
2059  slt(scratch, r2, rs);
2060  beq(scratch, zero_reg, offset);
2061  }
2062  break;
2063  // Unsigned comparison.
2064  case Ugreater:
2065  if (rt.imm64_ == 0) {
2066  bgtz(rs, offset);
2067  } else {
2068  r2 = scratch;
2069  li(r2, rt);
2070  sltu(scratch, r2, rs);
2071  bne(scratch, zero_reg, offset);
2072  }
2073  break;
2074  case Ugreater_equal:
2075  if (rt.imm64_ == 0) {
2076  bgez(rs, offset);
2077  } else if (is_int16(rt.imm64_)) {
2078  sltiu(scratch, rs, rt.imm64_);
2079  beq(scratch, zero_reg, offset);
2080  } else {
2081  r2 = scratch;
2082  li(r2, rt);
2083  sltu(scratch, rs, r2);
2084  beq(scratch, zero_reg, offset);
2085  }
2086  break;
2087  case Uless:
2088  if (rt.imm64_ == 0) {
2089  // No code needs to be emitted.
2090  return;
2091  } else if (is_int16(rt.imm64_)) {
2092  sltiu(scratch, rs, rt.imm64_);
2093  bne(scratch, zero_reg, offset);
2094  } else {
2095  r2 = scratch;
2096  li(r2, rt);
2097  sltu(scratch, rs, r2);
2098  bne(scratch, zero_reg, offset);
2099  }
2100  break;
2101  case Uless_equal:
2102  if (rt.imm64_ == 0) {
2103  b(offset);
2104  } else {
2105  r2 = scratch;
2106  li(r2, rt);
2107  sltu(scratch, r2, rs);
2108  beq(scratch, zero_reg, offset);
2109  }
2110  break;
2111  default:
2112  UNREACHABLE();
2113  }
2114  }
2115  // Emit a nop in the branch delay slot if required.
2116  if (bdslot == PROTECT)
2117  nop();
2118 }
2119 
2120 
2121 void MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) {
2122  // We use branch_offset as an argument for the branch instructions to be sure
2123  // it is called just before generating the branch instruction, as needed.
2124 
2125  b(shifted_branch_offset(L, false));
2126 
2127  // Emit a nop in the branch delay slot if required.
2128  if (bdslot == PROTECT)
2129  nop();
2130 }
2131 
2132 
2133 void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
2134  const Operand& rt,
2135  BranchDelaySlot bdslot) {
2136  BRANCH_ARGS_CHECK(cond, rs, rt);
2137 
2138  int32_t offset = 0;
2139  Register r2 = no_reg;
2140  Register scratch = at;
2141  if (rt.is_reg()) {
2142  BlockTrampolinePoolScope block_trampoline_pool(this);
2143  r2 = rt.rm_;
2144  // Be careful to always use shifted_branch_offset only just before the
2145  // branch instruction, as the location will be remember for patching the
2146  // target.
2147  switch (cond) {
2148  case cc_always:
2149  offset = shifted_branch_offset(L, false);
2150  b(offset);
2151  break;
2152  case eq:
2153  offset = shifted_branch_offset(L, false);
2154  beq(rs, r2, offset);
2155  break;
2156  case ne:
2157  offset = shifted_branch_offset(L, false);
2158  bne(rs, r2, offset);
2159  break;
2160  // Signed comparison.
2161  case greater:
2162  if (r2.is(zero_reg)) {
2163  offset = shifted_branch_offset(L, false);
2164  bgtz(rs, offset);
2165  } else {
2166  slt(scratch, r2, rs);
2167  offset = shifted_branch_offset(L, false);
2168  bne(scratch, zero_reg, offset);
2169  }
2170  break;
2171  case greater_equal:
2172  if (r2.is(zero_reg)) {
2173  offset = shifted_branch_offset(L, false);
2174  bgez(rs, offset);
2175  } else {
2176  slt(scratch, rs, r2);
2177  offset = shifted_branch_offset(L, false);
2178  beq(scratch, zero_reg, offset);
2179  }
2180  break;
2181  case less:
2182  if (r2.is(zero_reg)) {
2183  offset = shifted_branch_offset(L, false);
2184  bltz(rs, offset);
2185  } else {
2186  slt(scratch, rs, r2);
2187  offset = shifted_branch_offset(L, false);
2188  bne(scratch, zero_reg, offset);
2189  }
2190  break;
2191  case less_equal:
2192  if (r2.is(zero_reg)) {
2193  offset = shifted_branch_offset(L, false);
2194  blez(rs, offset);
2195  } else {
2196  slt(scratch, r2, rs);
2197  offset = shifted_branch_offset(L, false);
2198  beq(scratch, zero_reg, offset);
2199  }
2200  break;
2201  // Unsigned comparison.
2202  case Ugreater:
2203  if (r2.is(zero_reg)) {
2204  offset = shifted_branch_offset(L, false);
2205  bgtz(rs, offset);
2206  } else {
2207  sltu(scratch, r2, rs);
2208  offset = shifted_branch_offset(L, false);
2209  bne(scratch, zero_reg, offset);
2210  }
2211  break;
2212  case Ugreater_equal:
2213  if (r2.is(zero_reg)) {
2214  offset = shifted_branch_offset(L, false);
2215  bgez(rs, offset);
2216  } else {
2217  sltu(scratch, rs, r2);
2218  offset = shifted_branch_offset(L, false);
2219  beq(scratch, zero_reg, offset);
2220  }
2221  break;
2222  case Uless:
2223  if (r2.is(zero_reg)) {
2224  // No code needs to be emitted.
2225  return;
2226  } else {
2227  sltu(scratch, rs, r2);
2228  offset = shifted_branch_offset(L, false);
2229  bne(scratch, zero_reg, offset);
2230  }
2231  break;
2232  case Uless_equal:
2233  if (r2.is(zero_reg)) {
2234  offset = shifted_branch_offset(L, false);
2235  b(offset);
2236  } else {
2237  sltu(scratch, r2, rs);
2238  offset = shifted_branch_offset(L, false);
2239  beq(scratch, zero_reg, offset);
2240  }
2241  break;
2242  default:
2243  UNREACHABLE();
2244  }
2245  } else {
2246  // Be careful to always use shifted_branch_offset only just before the
2247  // branch instruction, as the location will be remember for patching the
2248  // target.
2249  BlockTrampolinePoolScope block_trampoline_pool(this);
2250  switch (cond) {
2251  case cc_always:
2252  offset = shifted_branch_offset(L, false);
2253  b(offset);
2254  break;
2255  case eq:
2256  DCHECK(!scratch.is(rs));
2257  r2 = scratch;
2258  li(r2, rt);
2259  offset = shifted_branch_offset(L, false);
2260  beq(rs, r2, offset);
2261  break;
2262  case ne:
2263  DCHECK(!scratch.is(rs));
2264  r2 = scratch;
2265  li(r2, rt);
2266  offset = shifted_branch_offset(L, false);
2267  bne(rs, r2, offset);
2268  break;
2269  // Signed comparison.
2270  case greater:
2271  if (rt.imm64_ == 0) {
2272  offset = shifted_branch_offset(L, false);
2273  bgtz(rs, offset);
2274  } else {
2275  DCHECK(!scratch.is(rs));
2276  r2 = scratch;
2277  li(r2, rt);
2278  slt(scratch, r2, rs);
2279  offset = shifted_branch_offset(L, false);
2280  bne(scratch, zero_reg, offset);
2281  }
2282  break;
2283  case greater_equal:
2284  if (rt.imm64_ == 0) {
2285  offset = shifted_branch_offset(L, false);
2286  bgez(rs, offset);
2287  } else if (is_int16(rt.imm64_)) {
2288  slti(scratch, rs, rt.imm64_);
2289  offset = shifted_branch_offset(L, false);
2290  beq(scratch, zero_reg, offset);
2291  } else {
2292  DCHECK(!scratch.is(rs));
2293  r2 = scratch;
2294  li(r2, rt);
2295  slt(scratch, rs, r2);
2296  offset = shifted_branch_offset(L, false);
2297  beq(scratch, zero_reg, offset);
2298  }
2299  break;
2300  case less:
2301  if (rt.imm64_ == 0) {
2302  offset = shifted_branch_offset(L, false);
2303  bltz(rs, offset);
2304  } else if (is_int16(rt.imm64_)) {
2305  slti(scratch, rs, rt.imm64_);
2306  offset = shifted_branch_offset(L, false);
2307  bne(scratch, zero_reg, offset);
2308  } else {
2309  DCHECK(!scratch.is(rs));
2310  r2 = scratch;
2311  li(r2, rt);
2312  slt(scratch, rs, r2);
2313  offset = shifted_branch_offset(L, false);
2314  bne(scratch, zero_reg, offset);
2315  }
2316  break;
2317  case less_equal:
2318  if (rt.imm64_ == 0) {
2319  offset = shifted_branch_offset(L, false);
2320  blez(rs, offset);
2321  } else {
2322  DCHECK(!scratch.is(rs));
2323  r2 = scratch;
2324  li(r2, rt);
2325  slt(scratch, r2, rs);
2326  offset = shifted_branch_offset(L, false);
2327  beq(scratch, zero_reg, offset);
2328  }
2329  break;
2330  // Unsigned comparison.
2331  case Ugreater:
2332  if (rt.imm64_ == 0) {
2333  offset = shifted_branch_offset(L, false);
2334  bne(rs, zero_reg, offset);
2335  } else {
2336  DCHECK(!scratch.is(rs));
2337  r2 = scratch;
2338  li(r2, rt);
2339  sltu(scratch, r2, rs);
2340  offset = shifted_branch_offset(L, false);
2341  bne(scratch, zero_reg, offset);
2342  }
2343  break;
2344  case Ugreater_equal:
2345  if (rt.imm64_ == 0) {
2346  offset = shifted_branch_offset(L, false);
2347  bgez(rs, offset);
2348  } else if (is_int16(rt.imm64_)) {
2349  sltiu(scratch, rs, rt.imm64_);
2350  offset = shifted_branch_offset(L, false);
2351  beq(scratch, zero_reg, offset);
2352  } else {
2353  DCHECK(!scratch.is(rs));
2354  r2 = scratch;
2355  li(r2, rt);
2356  sltu(scratch, rs, r2);
2357  offset = shifted_branch_offset(L, false);
2358  beq(scratch, zero_reg, offset);
2359  }
2360  break;
2361  case Uless:
2362  if (rt.imm64_ == 0) {
2363  // No code needs to be emitted.
2364  return;
2365  } else if (is_int16(rt.imm64_)) {
2366  sltiu(scratch, rs, rt.imm64_);
2367  offset = shifted_branch_offset(L, false);
2368  bne(scratch, zero_reg, offset);
2369  } else {
2370  DCHECK(!scratch.is(rs));
2371  r2 = scratch;
2372  li(r2, rt);
2373  sltu(scratch, rs, r2);
2374  offset = shifted_branch_offset(L, false);
2375  bne(scratch, zero_reg, offset);
2376  }
2377  break;
2378  case Uless_equal:
2379  if (rt.imm64_ == 0) {
2380  offset = shifted_branch_offset(L, false);
2381  beq(rs, zero_reg, offset);
2382  } else {
2383  DCHECK(!scratch.is(rs));
2384  r2 = scratch;
2385  li(r2, rt);
2386  sltu(scratch, r2, rs);
2387  offset = shifted_branch_offset(L, false);
2388  beq(scratch, zero_reg, offset);
2389  }
2390  break;
2391  default:
2392  UNREACHABLE();
2393  }
2394  }
2395  // Check that offset could actually hold on an int16_t.
2396  DCHECK(is_int16(offset));
2397  // Emit a nop in the branch delay slot if required.
2398  if (bdslot == PROTECT)
2399  nop();
2400 }
2401 
2402 
2403 void MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) {
2404  BranchAndLinkShort(offset, bdslot);
2405 }
2406 
2407 
2408 void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs,
2409  const Operand& rt,
2410  BranchDelaySlot bdslot) {
2411  BranchAndLinkShort(offset, cond, rs, rt, bdslot);
2412 }
2413 
2414 
2415 void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) {
2416  if (L->is_bound()) {
2417  if (is_near(L)) {
2418  BranchAndLinkShort(L, bdslot);
2419  } else {
2420  Jalr(L, bdslot);
2421  }
2422  } else {
2423  if (is_trampoline_emitted()) {
2424  Jalr(L, bdslot);
2425  } else {
2426  BranchAndLinkShort(L, bdslot);
2427  }
2428  }
2429 }
2430 
2431 
2432 void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs,
2433  const Operand& rt,
2434  BranchDelaySlot bdslot) {
2435  if (L->is_bound()) {
2436  if (is_near(L)) {
2437  BranchAndLinkShort(L, cond, rs, rt, bdslot);
2438  } else {
2439  Label skip;
2440  Condition neg_cond = NegateCondition(cond);
2441  BranchShort(&skip, neg_cond, rs, rt);
2442  Jalr(L, bdslot);
2443  bind(&skip);
2444  }
2445  } else {
2446  if (is_trampoline_emitted()) {
2447  Label skip;
2448  Condition neg_cond = NegateCondition(cond);
2449  BranchShort(&skip, neg_cond, rs, rt);
2450  Jalr(L, bdslot);
2451  bind(&skip);
2452  } else {
2453  BranchAndLinkShort(L, cond, rs, rt, bdslot);
2454  }
2455  }
2456 }
2457 
2458 
2459 // We need to use a bgezal or bltzal, but they can't be used directly with the
2460 // slt instructions. We could use sub or add instead but we would miss overflow
2461 // cases, so we keep slt and add an intermediate third instruction.
2462 void MacroAssembler::BranchAndLinkShort(int16_t offset,
2463  BranchDelaySlot bdslot) {
2464  bal(offset);
2465 
2466  // Emit a nop in the branch delay slot if required.
2467  if (bdslot == PROTECT)
2468  nop();
2469 }
2470 
2471 
2472 void MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond,
2473  Register rs, const Operand& rt,
2474  BranchDelaySlot bdslot) {
2475  BRANCH_ARGS_CHECK(cond, rs, rt);
2476  Register r2 = no_reg;
2477  Register scratch = at;
2478 
2479  if (rt.is_reg()) {
2480  r2 = rt.rm_;
2481  } else if (cond != cc_always) {
2482  r2 = scratch;
2483  li(r2, rt);
2484  }
2485 
2486  {
2487  BlockTrampolinePoolScope block_trampoline_pool(this);
2488  switch (cond) {
2489  case cc_always:
2490  bal(offset);
2491  break;
2492  case eq:
2493  bne(rs, r2, 2);
2494  nop();
2495  bal(offset);
2496  break;
2497  case ne:
2498  beq(rs, r2, 2);
2499  nop();
2500  bal(offset);
2501  break;
2502 
2503  // Signed comparison.
2504  case greater:
2505  // rs > rt
2506  slt(scratch, r2, rs);
2507  beq(scratch, zero_reg, 2);
2508  nop();
2509  bal(offset);
2510  break;
2511  case greater_equal:
2512  // rs >= rt
2513  slt(scratch, rs, r2);
2514  bne(scratch, zero_reg, 2);
2515  nop();
2516  bal(offset);
2517  break;
2518  case less:
2519  // rs < r2
2520  slt(scratch, rs, r2);
2521  bne(scratch, zero_reg, 2);
2522  nop();
2523  bal(offset);
2524  break;
2525  case less_equal:
2526  // rs <= r2
2527  slt(scratch, r2, rs);
2528  bne(scratch, zero_reg, 2);
2529  nop();
2530  bal(offset);
2531  break;
2532 
2533 
2534  // Unsigned comparison.
2535  case Ugreater:
2536  // rs > rt
2537  sltu(scratch, r2, rs);
2538  beq(scratch, zero_reg, 2);
2539  nop();
2540  bal(offset);
2541  break;
2542  case Ugreater_equal:
2543  // rs >= rt
2544  sltu(scratch, rs, r2);
2545  bne(scratch, zero_reg, 2);
2546  nop();
2547  bal(offset);
2548  break;
2549  case Uless:
2550  // rs < r2
2551  sltu(scratch, rs, r2);
2552  bne(scratch, zero_reg, 2);
2553  nop();
2554  bal(offset);
2555  break;
2556  case Uless_equal:
2557  // rs <= r2
2558  sltu(scratch, r2, rs);
2559  bne(scratch, zero_reg, 2);
2560  nop();
2561  bal(offset);
2562  break;
2563  default:
2564  UNREACHABLE();
2565  }
2566  }
2567  // Emit a nop in the branch delay slot if required.
2568  if (bdslot == PROTECT)
2569  nop();
2570 }
2571 
2572 
2573 void MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) {
2574  bal(shifted_branch_offset(L, false));
2575 
2576  // Emit a nop in the branch delay slot if required.
2577  if (bdslot == PROTECT)
2578  nop();
2579 }
2580 
2581 
2582 void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs,
2583  const Operand& rt,
2584  BranchDelaySlot bdslot) {
2585  BRANCH_ARGS_CHECK(cond, rs, rt);
2586 
2587  int32_t offset = 0;
2588  Register r2 = no_reg;
2589  Register scratch = at;
2590  if (rt.is_reg()) {
2591  r2 = rt.rm_;
2592  } else if (cond != cc_always) {
2593  r2 = scratch;
2594  li(r2, rt);
2595  }
2596 
2597  {
2598  BlockTrampolinePoolScope block_trampoline_pool(this);
2599  switch (cond) {
2600  case cc_always:
2601  offset = shifted_branch_offset(L, false);
2602  bal(offset);
2603  break;
2604  case eq:
2605  bne(rs, r2, 2);
2606  nop();
2607  offset = shifted_branch_offset(L, false);
2608  bal(offset);
2609  break;
2610  case ne:
2611  beq(rs, r2, 2);
2612  nop();
2613  offset = shifted_branch_offset(L, false);
2614  bal(offset);
2615  break;
2616 
2617  // Signed comparison.
2618  case greater:
2619  // rs > rt
2620  slt(scratch, r2, rs);
2621  beq(scratch, zero_reg, 2);
2622  nop();
2623  offset = shifted_branch_offset(L, false);
2624  bal(offset);
2625  break;
2626  case greater_equal:
2627  // rs >= rt
2628  slt(scratch, rs, r2);
2629  bne(scratch, zero_reg, 2);
2630  nop();
2631  offset = shifted_branch_offset(L, false);
2632  bal(offset);
2633  break;
2634  case less:
2635  // rs < r2
2636  slt(scratch, rs, r2);
2637  bne(scratch, zero_reg, 2);
2638  nop();
2639  offset = shifted_branch_offset(L, false);
2640  bal(offset);
2641  break;
2642  case less_equal:
2643  // rs <= r2
2644  slt(scratch, r2, rs);
2645  bne(scratch, zero_reg, 2);
2646  nop();
2647  offset = shifted_branch_offset(L, false);
2648  bal(offset);
2649  break;
2650 
2651 
2652  // Unsigned comparison.
2653  case Ugreater:
2654  // rs > rt
2655  sltu(scratch, r2, rs);
2656  beq(scratch, zero_reg, 2);
2657  nop();
2658  offset = shifted_branch_offset(L, false);
2659  bal(offset);
2660  break;
2661  case Ugreater_equal:
2662  // rs >= rt
2663  sltu(scratch, rs, r2);
2664  bne(scratch, zero_reg, 2);
2665  nop();
2666  offset = shifted_branch_offset(L, false);
2667  bal(offset);
2668  break;
2669  case Uless:
2670  // rs < r2
2671  sltu(scratch, rs, r2);
2672  bne(scratch, zero_reg, 2);
2673  nop();
2674  offset = shifted_branch_offset(L, false);
2675  bal(offset);
2676  break;
2677  case Uless_equal:
2678  // rs <= r2
2679  sltu(scratch, r2, rs);
2680  bne(scratch, zero_reg, 2);
2681  nop();
2682  offset = shifted_branch_offset(L, false);
2683  bal(offset);
2684  break;
2685 
2686  default:
2687  UNREACHABLE();
2688  }
2689  }
2690  // Check that offset could actually hold on an int16_t.
2691  DCHECK(is_int16(offset));
2692 
2693  // Emit a nop in the branch delay slot if required.
2694  if (bdslot == PROTECT)
2695  nop();
2696 }
2697 
2698 
2699 void MacroAssembler::Jump(Register target,
2700  Condition cond,
2701  Register rs,
2702  const Operand& rt,
2703  BranchDelaySlot bd) {
2704  BlockTrampolinePoolScope block_trampoline_pool(this);
2705  if (cond == cc_always) {
2706  jr(target);
2707  } else {
2708  BRANCH_ARGS_CHECK(cond, rs, rt);
2709  Branch(2, NegateCondition(cond), rs, rt);
2710  jr(target);
2711  }
2712  // Emit a nop in the branch delay slot if required.
2713  if (bd == PROTECT)
2714  nop();
2715 }
2716 
2717 
2718 void MacroAssembler::Jump(intptr_t target,
2719  RelocInfo::Mode rmode,
2720  Condition cond,
2721  Register rs,
2722  const Operand& rt,
2723  BranchDelaySlot bd) {
2724  Label skip;
2725  if (cond != cc_always) {
2726  Branch(USE_DELAY_SLOT, &skip, NegateCondition(cond), rs, rt);
2727  }
2728  // The first instruction of 'li' may be placed in the delay slot.
2729  // This is not an issue, t9 is expected to be clobbered anyway.
2730  li(t9, Operand(target, rmode));
2731  Jump(t9, al, zero_reg, Operand(zero_reg), bd);
2732  bind(&skip);
2733 }
2734 
2735 
2736 void MacroAssembler::Jump(Address target,
2737  RelocInfo::Mode rmode,
2738  Condition cond,
2739  Register rs,
2740  const Operand& rt,
2741  BranchDelaySlot bd) {
2742  DCHECK(!RelocInfo::IsCodeTarget(rmode));
2743  Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd);
2744 }
2745 
2746 
2747 void MacroAssembler::Jump(Handle<Code> code,
2748  RelocInfo::Mode rmode,
2749  Condition cond,
2750  Register rs,
2751  const Operand& rt,
2752  BranchDelaySlot bd) {
2753  DCHECK(RelocInfo::IsCodeTarget(rmode));
2754  AllowDeferredHandleDereference embedding_raw_address;
2755  Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd);
2756 }
2757 
2758 
2759 int MacroAssembler::CallSize(Register target,
2760  Condition cond,
2761  Register rs,
2762  const Operand& rt,
2763  BranchDelaySlot bd) {
2764  int size = 0;
2765 
2766  if (cond == cc_always) {
2767  size += 1;
2768  } else {
2769  size += 3;
2770  }
2771 
2772  if (bd == PROTECT)
2773  size += 1;
2774 
2775  return size * kInstrSize;
2776 }
2777 
2778 
2779 // Note: To call gcc-compiled C code on mips, you must call thru t9.
2780 void MacroAssembler::Call(Register target,
2781  Condition cond,
2782  Register rs,
2783  const Operand& rt,
2784  BranchDelaySlot bd) {
2785  BlockTrampolinePoolScope block_trampoline_pool(this);
2786  Label start;
2787  bind(&start);
2788  if (cond == cc_always) {
2789  jalr(target);
2790  } else {
2791  BRANCH_ARGS_CHECK(cond, rs, rt);
2792  Branch(2, NegateCondition(cond), rs, rt);
2793  jalr(target);
2794  }
2795  // Emit a nop in the branch delay slot if required.
2796  if (bd == PROTECT)
2797  nop();
2798 
2799  DCHECK_EQ(CallSize(target, cond, rs, rt, bd),
2800  SizeOfCodeGeneratedSince(&start));
2801 }
2802 
2803 
2804 int MacroAssembler::CallSize(Address target,
2805  RelocInfo::Mode rmode,
2806  Condition cond,
2807  Register rs,
2808  const Operand& rt,
2809  BranchDelaySlot bd) {
2810  int size = CallSize(t9, cond, rs, rt, bd);
2811  return size + 4 * kInstrSize;
2812 }
2813 
2814 
2815 void MacroAssembler::Call(Address target,
2816  RelocInfo::Mode rmode,
2817  Condition cond,
2818  Register rs,
2819  const Operand& rt,
2820  BranchDelaySlot bd) {
2821  BlockTrampolinePoolScope block_trampoline_pool(this);
2822  Label start;
2823  bind(&start);
2824  int64_t target_int = reinterpret_cast<int64_t>(target);
2825  // Must record previous source positions before the
2826  // li() generates a new code target.
2827  positions_recorder()->WriteRecordedPositions();
2828  li(t9, Operand(target_int, rmode), ADDRESS_LOAD);
2829  Call(t9, cond, rs, rt, bd);
2830  DCHECK_EQ(CallSize(target, rmode, cond, rs, rt, bd),
2831  SizeOfCodeGeneratedSince(&start));
2832 }
2833 
2834 
2835 int MacroAssembler::CallSize(Handle<Code> code,
2836  RelocInfo::Mode rmode,
2837  TypeFeedbackId ast_id,
2838  Condition cond,
2839  Register rs,
2840  const Operand& rt,
2841  BranchDelaySlot bd) {
2842  AllowDeferredHandleDereference using_raw_address;
2843  return CallSize(reinterpret_cast<Address>(code.location()),
2844  rmode, cond, rs, rt, bd);
2845 }
2846 
2847 
2848 void MacroAssembler::Call(Handle<Code> code,
2849  RelocInfo::Mode rmode,
2850  TypeFeedbackId ast_id,
2851  Condition cond,
2852  Register rs,
2853  const Operand& rt,
2854  BranchDelaySlot bd) {
2855  BlockTrampolinePoolScope block_trampoline_pool(this);
2856  Label start;
2857  bind(&start);
2858  DCHECK(RelocInfo::IsCodeTarget(rmode));
2859  if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
2860  SetRecordedAstId(ast_id);
2861  rmode = RelocInfo::CODE_TARGET_WITH_ID;
2862  }
2863  AllowDeferredHandleDereference embedding_raw_address;
2864  Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd);
2865  DCHECK_EQ(CallSize(code, rmode, ast_id, cond, rs, rt, bd),
2866  SizeOfCodeGeneratedSince(&start));
2867 }
2868 
2869 
2870 void MacroAssembler::Ret(Condition cond,
2871  Register rs,
2872  const Operand& rt,
2873  BranchDelaySlot bd) {
2874  Jump(ra, cond, rs, rt, bd);
2875 }
2876 
2877 
2878 void MacroAssembler::J(Label* L, BranchDelaySlot bdslot) {
2879  BlockTrampolinePoolScope block_trampoline_pool(this);
2880 
2881  uint64_t imm28;
2882  imm28 = jump_address(L);
2883  imm28 &= kImm28Mask;
2884  { BlockGrowBufferScope block_buf_growth(this);
2885  // Buffer growth (and relocation) must be blocked for internal references
2886  // until associated instructions are emitted and available to be patched.
2887  RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
2888  j(imm28);
2889  }
2890  // Emit a nop in the branch delay slot if required.
2891  if (bdslot == PROTECT)
2892  nop();
2893 }
2894 
2895 
2896 void MacroAssembler::Jr(Label* L, BranchDelaySlot bdslot) {
2897  BlockTrampolinePoolScope block_trampoline_pool(this);
2898 
2899  uint64_t imm64;
2900  imm64 = jump_address(L);
2901  { BlockGrowBufferScope block_buf_growth(this);
2902  // Buffer growth (and relocation) must be blocked for internal references
2903  // until associated instructions are emitted and available to be patched.
2904  RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
2905  li(at, Operand(imm64), ADDRESS_LOAD);
2906  }
2907  jr(at);
2908 
2909  // Emit a nop in the branch delay slot if required.
2910  if (bdslot == PROTECT)
2911  nop();
2912 }
2913 
2914 
2915 void MacroAssembler::Jalr(Label* L, BranchDelaySlot bdslot) {
2916  BlockTrampolinePoolScope block_trampoline_pool(this);
2917 
2918  uint64_t imm64;
2919  imm64 = jump_address(L);
2920  { BlockGrowBufferScope block_buf_growth(this);
2921  // Buffer growth (and relocation) must be blocked for internal references
2922  // until associated instructions are emitted and available to be patched.
2923  RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
2924  li(at, Operand(imm64), ADDRESS_LOAD);
2925  }
2926  jalr(at);
2927 
2928  // Emit a nop in the branch delay slot if required.
2929  if (bdslot == PROTECT)
2930  nop();
2931 }
2932 
2933 
2934 void MacroAssembler::DropAndRet(int drop) {
2935  Ret(USE_DELAY_SLOT);
2936  daddiu(sp, sp, drop * kPointerSize);
2937 }
2938 
2939 void MacroAssembler::DropAndRet(int drop,
2940  Condition cond,
2941  Register r1,
2942  const Operand& r2) {
2943  // Both Drop and Ret need to be conditional.
2944  Label skip;
2945  if (cond != cc_always) {
2946  Branch(&skip, NegateCondition(cond), r1, r2);
2947  }
2948 
2949  Drop(drop);
2950  Ret();
2951 
2952  if (cond != cc_always) {
2953  bind(&skip);
2954  }
2955 }
2956 
2957 
2958 void MacroAssembler::Drop(int count,
2959  Condition cond,
2960  Register reg,
2961  const Operand& op) {
2962  if (count <= 0) {
2963  return;
2964  }
2965 
2966  Label skip;
2967 
2968  if (cond != al) {
2969  Branch(&skip, NegateCondition(cond), reg, op);
2970  }
2971 
2972  daddiu(sp, sp, count * kPointerSize);
2973 
2974  if (cond != al) {
2975  bind(&skip);
2976  }
2977 }
2978 
2979 
2980 
2981 void MacroAssembler::Swap(Register reg1,
2982  Register reg2,
2983  Register scratch) {
2984  if (scratch.is(no_reg)) {
2985  Xor(reg1, reg1, Operand(reg2));
2986  Xor(reg2, reg2, Operand(reg1));
2987  Xor(reg1, reg1, Operand(reg2));
2988  } else {
2989  mov(scratch, reg1);
2990  mov(reg1, reg2);
2991  mov(reg2, scratch);
2992  }
2993 }
2994 
2995 
2996 void MacroAssembler::Call(Label* target) {
2997  BranchAndLink(target);
2998 }
2999 
3000 
3001 void MacroAssembler::Push(Handle<Object> handle) {
3002  li(at, Operand(handle));
3003  push(at);
3004 }
3005 
3006 
3007 void MacroAssembler::PushRegisterAsTwoSmis(Register src, Register scratch) {
3008  DCHECK(!src.is(scratch));
3009  mov(scratch, src);
3010  dsrl32(src, src, 0);
3011  dsll32(src, src, 0);
3012  push(src);
3013  dsll32(scratch, scratch, 0);
3014  push(scratch);
3015 }
3016 
3017 
3018 void MacroAssembler::PopRegisterAsTwoSmis(Register dst, Register scratch) {
3019  DCHECK(!dst.is(scratch));
3020  pop(scratch);
3021  dsrl32(scratch, scratch, 0);
3022  pop(dst);
3023  dsrl32(dst, dst, 0);
3024  dsll32(dst, dst, 0);
3025  or_(dst, dst, scratch);
3026 }
3027 
3028 
3029 void MacroAssembler::DebugBreak() {
3030  PrepareCEntryArgs(0);
3031  PrepareCEntryFunction(ExternalReference(Runtime::kDebugBreak, isolate()));
3032  CEntryStub ces(isolate(), 1);
3033  DCHECK(AllowThisStubCall(&ces));
3034  Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
3035 }
3036 
3037 
3038 // ---------------------------------------------------------------------------
3039 // Exception handling.
3040 
3041 void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
3042  int handler_index) {
3043  // Adjust this code if not the case.
3044  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
3045  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
3046  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
3047  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
3048  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
3049  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
3050 
3051  // For the JSEntry handler, we must preserve a0-a3 and s0.
3052  // a5-a7 are available. We will build up the handler from the bottom by
3053  // pushing on the stack.
3054  // Set up the code object (a5) and the state (a6) for pushing.
3055  unsigned state =
3056  StackHandler::IndexField::encode(handler_index) |
3057  StackHandler::KindField::encode(kind);
3058  li(a5, Operand(CodeObject()), CONSTANT_SIZE);
3059  li(a6, Operand(state));
3060 
3061  // Push the frame pointer, context, state, and code object.
3062  if (kind == StackHandler::JS_ENTRY) {
3063  DCHECK_EQ(Smi::FromInt(0), 0);
3064  // The second zero_reg indicates no context.
3065  // The first zero_reg is the NULL frame pointer.
3066  // The operands are reversed to match the order of MultiPush/Pop.
3067  Push(zero_reg, zero_reg, a6, a5);
3068  } else {
3069  MultiPush(a5.bit() | a6.bit() | cp.bit() | fp.bit());
3070  }
3071 
3072  // Link the current handler as the next handler.
3073  li(a6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
3074  ld(a5, MemOperand(a6));
3075  push(a5);
3076  // Set this new handler as the current one.
3077  sd(sp, MemOperand(a6));
3078 }
3079 
3080 
3081 void MacroAssembler::PopTryHandler() {
3082  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
3083  pop(a1);
3084  Daddu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
3085  li(at, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
3086  sd(a1, MemOperand(at));
3087 }
3088 
3089 
3090 void MacroAssembler::JumpToHandlerEntry() {
3091  // Compute the handler entry address and jump to it. The handler table is
3092  // a fixed array of (smi-tagged) code offsets.
3093  // v0 = exception, a1 = code object, a2 = state.
3094  Uld(a3, FieldMemOperand(a1, Code::kHandlerTableOffset));
3095  Daddu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3096  dsrl(a2, a2, StackHandler::kKindWidth); // Handler index.
3097  dsll(a2, a2, kPointerSizeLog2);
3098  Daddu(a2, a3, a2);
3099  ld(a2, MemOperand(a2)); // Smi-tagged offset.
3100  Daddu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start.
3101  dsra32(t9, a2, 0);
3102  Daddu(t9, t9, a1);
3103  Jump(t9); // Jump.
3104 }
3105 
3106 
3107 void MacroAssembler::Throw(Register value) {
3108  // Adjust this code if not the case.
3109  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
3110  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
3111  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
3112  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
3113  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
3114  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
3115 
3116  // The exception is expected in v0.
3117  Move(v0, value);
3118 
3119  // Drop the stack pointer to the top of the top handler.
3120  li(a3, Operand(ExternalReference(Isolate::kHandlerAddress,
3121  isolate())));
3122  ld(sp, MemOperand(a3));
3123 
3124  // Restore the next handler.
3125  pop(a2);
3126  sd(a2, MemOperand(a3));
3127 
3128  // Get the code object (a1) and state (a2). Restore the context and frame
3129  // pointer.
3130  MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit());
3131 
3132  // If the handler is a JS frame, restore the context to the frame.
3133  // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
3134  // or cp.
3135  Label done;
3136  Branch(&done, eq, cp, Operand(zero_reg));
3137  sd(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3138  bind(&done);
3139 
3140  JumpToHandlerEntry();
3141 }
3142 
3143 
3144 void MacroAssembler::ThrowUncatchable(Register value) {
3145  // Adjust this code if not the case.
3146  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
3147  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
3148  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
3149  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
3150  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
3151  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
3152 
3153  // The exception is expected in v0.
3154  if (!value.is(v0)) {
3155  mov(v0, value);
3156  }
3157  // Drop the stack pointer to the top of the top stack handler.
3158  li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
3159  ld(sp, MemOperand(a3));
3160 
3161  // Unwind the handlers until the ENTRY handler is found.
3162  Label fetch_next, check_kind;
3163  jmp(&check_kind);
3164  bind(&fetch_next);
3165  ld(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
3166 
3167  bind(&check_kind);
3168  STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
3169  ld(a2, MemOperand(sp, StackHandlerConstants::kStateOffset));
3170  And(a2, a2, Operand(StackHandler::KindField::kMask));
3171  Branch(&fetch_next, ne, a2, Operand(zero_reg));
3172 
3173  // Set the top handler address to next handler past the top ENTRY handler.
3174  pop(a2);
3175  sd(a2, MemOperand(a3));
3176 
3177  // Get the code object (a1) and state (a2). Clear the context and frame
3178  // pointer (0 was saved in the handler).
3179  MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit());
3180 
3181  JumpToHandlerEntry();
3182 }
3183 
3184 
3185 void MacroAssembler::Allocate(int object_size,
3186  Register result,
3187  Register scratch1,
3188  Register scratch2,
3189  Label* gc_required,
3191  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
3192  if (!FLAG_inline_new) {
3193  if (emit_debug_code()) {
3194  // Trash the registers to simulate an allocation failure.
3195  li(result, 0x7091);
3196  li(scratch1, 0x7191);
3197  li(scratch2, 0x7291);
3198  }
3199  jmp(gc_required);
3200  return;
3201  }
3202 
3203  DCHECK(!result.is(scratch1));
3204  DCHECK(!result.is(scratch2));
3205  DCHECK(!scratch1.is(scratch2));
3206  DCHECK(!scratch1.is(t9));
3207  DCHECK(!scratch2.is(t9));
3208  DCHECK(!result.is(t9));
3209 
3210  // Make object size into bytes.
3211  if ((flags & SIZE_IN_WORDS) != 0) {
3212  object_size *= kPointerSize;
3213  }
3214  DCHECK(0 == (object_size & kObjectAlignmentMask));
3215 
3216  // Check relative positions of allocation top and limit addresses.
3217  // ARM adds additional checks to make sure the ldm instruction can be
3218  // used. On MIPS we don't have ldm so we don't need additional checks either.
3219  ExternalReference allocation_top =
3220  AllocationUtils::GetAllocationTopReference(isolate(), flags);
3221  ExternalReference allocation_limit =
3222  AllocationUtils::GetAllocationLimitReference(isolate(), flags);
3223 
3224  intptr_t top =
3225  reinterpret_cast<intptr_t>(allocation_top.address());
3226  intptr_t limit =
3227  reinterpret_cast<intptr_t>(allocation_limit.address());
3228  DCHECK((limit - top) == kPointerSize);
3229 
3230  // Set up allocation top address and object size registers.
3231  Register topaddr = scratch1;
3232  li(topaddr, Operand(allocation_top));
3233 
3234  // This code stores a temporary value in t9.
3235  if ((flags & RESULT_CONTAINS_TOP) == 0) {
3236  // Load allocation top into result and allocation limit into t9.
3237  ld(result, MemOperand(topaddr));
3238  ld(t9, MemOperand(topaddr, kPointerSize));
3239  } else {
3240  if (emit_debug_code()) {
3241  // Assert that result actually contains top on entry. t9 is used
3242  // immediately below so this use of t9 does not cause difference with
3243  // respect to register content between debug and release mode.
3244  ld(t9, MemOperand(topaddr));
3245  Check(eq, kUnexpectedAllocationTop, result, Operand(t9));
3246  }
3247  // Load allocation limit into t9. Result already contains allocation top.
3248  ld(t9, MemOperand(topaddr, limit - top));
3249  }
3250 
3252  if (emit_debug_code()) {
3253  And(at, result, Operand(kDoubleAlignmentMask));
3254  Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg));
3255  }
3256 
3257  // Calculate new top and bail out if new space is exhausted. Use result
3258  // to calculate the new top.
3259  Daddu(scratch2, result, Operand(object_size));
3260  Branch(gc_required, Ugreater, scratch2, Operand(t9));
3261  sd(scratch2, MemOperand(topaddr));
3262 
3263  // Tag object if requested.
3264  if ((flags & TAG_OBJECT) != 0) {
3265  Daddu(result, result, Operand(kHeapObjectTag));
3266  }
3267 }
3268 
3269 
3270 void MacroAssembler::Allocate(Register object_size,
3271  Register result,
3272  Register scratch1,
3273  Register scratch2,
3274  Label* gc_required,
3276  if (!FLAG_inline_new) {
3277  if (emit_debug_code()) {
3278  // Trash the registers to simulate an allocation failure.
3279  li(result, 0x7091);
3280  li(scratch1, 0x7191);
3281  li(scratch2, 0x7291);
3282  }
3283  jmp(gc_required);
3284  return;
3285  }
3286 
3287  DCHECK(!result.is(scratch1));
3288  DCHECK(!result.is(scratch2));
3289  DCHECK(!scratch1.is(scratch2));
3290  DCHECK(!object_size.is(t9));
3291  DCHECK(!scratch1.is(t9) && !scratch2.is(t9) && !result.is(t9));
3292 
3293  // Check relative positions of allocation top and limit addresses.
3294  // ARM adds additional checks to make sure the ldm instruction can be
3295  // used. On MIPS we don't have ldm so we don't need additional checks either.
3296  ExternalReference allocation_top =
3297  AllocationUtils::GetAllocationTopReference(isolate(), flags);
3298  ExternalReference allocation_limit =
3299  AllocationUtils::GetAllocationLimitReference(isolate(), flags);
3300  intptr_t top =
3301  reinterpret_cast<intptr_t>(allocation_top.address());
3302  intptr_t limit =
3303  reinterpret_cast<intptr_t>(allocation_limit.address());
3304  DCHECK((limit - top) == kPointerSize);
3305 
3306  // Set up allocation top address and object size registers.
3307  Register topaddr = scratch1;
3308  li(topaddr, Operand(allocation_top));
3309 
3310  // This code stores a temporary value in t9.
3311  if ((flags & RESULT_CONTAINS_TOP) == 0) {
3312  // Load allocation top into result and allocation limit into t9.
3313  ld(result, MemOperand(topaddr));
3314  ld(t9, MemOperand(topaddr, kPointerSize));
3315  } else {
3316  if (emit_debug_code()) {
3317  // Assert that result actually contains top on entry. t9 is used
3318  // immediately below so this use of t9 does not cause difference with
3319  // respect to register content between debug and release mode.
3320  ld(t9, MemOperand(topaddr));
3321  Check(eq, kUnexpectedAllocationTop, result, Operand(t9));
3322  }
3323  // Load allocation limit into t9. Result already contains allocation top.
3324  ld(t9, MemOperand(topaddr, limit - top));
3325  }
3326 
3328  if (emit_debug_code()) {
3329  And(at, result, Operand(kDoubleAlignmentMask));
3330  Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg));
3331  }
3332 
3333  // Calculate new top and bail out if new space is exhausted. Use result
3334  // to calculate the new top. Object size may be in words so a shift is
3335  // required to get the number of bytes.
3336  if ((flags & SIZE_IN_WORDS) != 0) {
3337  dsll(scratch2, object_size, kPointerSizeLog2);
3338  Daddu(scratch2, result, scratch2);
3339  } else {
3340  Daddu(scratch2, result, Operand(object_size));
3341  }
3342  Branch(gc_required, Ugreater, scratch2, Operand(t9));
3343 
3344  // Update allocation top. result temporarily holds the new top.
3345  if (emit_debug_code()) {
3346  And(t9, scratch2, Operand(kObjectAlignmentMask));
3347  Check(eq, kUnalignedAllocationInNewSpace, t9, Operand(zero_reg));
3348  }
3349  sd(scratch2, MemOperand(topaddr));
3350 
3351  // Tag object if requested.
3352  if ((flags & TAG_OBJECT) != 0) {
3353  Daddu(result, result, Operand(kHeapObjectTag));
3354  }
3355 }
3356 
3357 
3358 void MacroAssembler::UndoAllocationInNewSpace(Register object,
3359  Register scratch) {
3360  ExternalReference new_space_allocation_top =
3361  ExternalReference::new_space_allocation_top_address(isolate());
3362 
3363  // Make sure the object has no tag before resetting top.
3364  And(object, object, Operand(~kHeapObjectTagMask));
3365 #ifdef DEBUG
3366  // Check that the object un-allocated is below the current top.
3367  li(scratch, Operand(new_space_allocation_top));
3368  ld(scratch, MemOperand(scratch));
3369  Check(less, kUndoAllocationOfNonAllocatedMemory,
3370  object, Operand(scratch));
3371 #endif
3372  // Write the address of the object to un-allocate as the current top.
3373  li(scratch, Operand(new_space_allocation_top));
3374  sd(object, MemOperand(scratch));
3375 }
3376 
3377 
3378 void MacroAssembler::AllocateTwoByteString(Register result,
3379  Register length,
3380  Register scratch1,
3381  Register scratch2,
3382  Register scratch3,
3383  Label* gc_required) {
3384  // Calculate the number of bytes needed for the characters in the string while
3385  // observing object alignment.
3386  DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
3387  dsll(scratch1, length, 1); // Length in bytes, not chars.
3388  daddiu(scratch1, scratch1,
3389  kObjectAlignmentMask + SeqTwoByteString::kHeaderSize);
3390  And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
3391 
3392  // Allocate two-byte string in new space.
3393  Allocate(scratch1,
3394  result,
3395  scratch2,
3396  scratch3,
3397  gc_required,
3398  TAG_OBJECT);
3399 
3400  // Set the map, length and hash field.
3401  InitializeNewString(result,
3402  length,
3403  Heap::kStringMapRootIndex,
3404  scratch1,
3405  scratch2);
3406 }
3407 
3408 
3409 void MacroAssembler::AllocateOneByteString(Register result, Register length,
3410  Register scratch1, Register scratch2,
3411  Register scratch3,
3412  Label* gc_required) {
3413  // Calculate the number of bytes needed for the characters in the string
3414  // while observing object alignment.
3415  DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
3416  DCHECK(kCharSize == 1);
3417  daddiu(scratch1, length,
3418  kObjectAlignmentMask + SeqOneByteString::kHeaderSize);
3419  And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
3420 
3421  // Allocate one-byte string in new space.
3422  Allocate(scratch1,
3423  result,
3424  scratch2,
3425  scratch3,
3426  gc_required,
3427  TAG_OBJECT);
3428 
3429  // Set the map, length and hash field.
3430  InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
3431  scratch1, scratch2);
3432 }
3433 
3434 
3435 void MacroAssembler::AllocateTwoByteConsString(Register result,
3436  Register length,
3437  Register scratch1,
3438  Register scratch2,
3439  Label* gc_required) {
3440  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
3441  TAG_OBJECT);
3442  InitializeNewString(result,
3443  length,
3444  Heap::kConsStringMapRootIndex,
3445  scratch1,
3446  scratch2);
3447 }
3448 
3449 
3450 void MacroAssembler::AllocateOneByteConsString(Register result, Register length,
3451  Register scratch1,
3452  Register scratch2,
3453  Label* gc_required) {
3454  Allocate(ConsString::kSize,
3455  result,
3456  scratch1,
3457  scratch2,
3458  gc_required,
3459  TAG_OBJECT);
3460 
3461  InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
3462  scratch1, scratch2);
3463 }
3464 
3465 
3466 void MacroAssembler::AllocateTwoByteSlicedString(Register result,
3467  Register length,
3468  Register scratch1,
3469  Register scratch2,
3470  Label* gc_required) {
3471  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
3472  TAG_OBJECT);
3473 
3474  InitializeNewString(result,
3475  length,
3476  Heap::kSlicedStringMapRootIndex,
3477  scratch1,
3478  scratch2);
3479 }
3480 
3481 
3482 void MacroAssembler::AllocateOneByteSlicedString(Register result,
3483  Register length,
3484  Register scratch1,
3485  Register scratch2,
3486  Label* gc_required) {
3487  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
3488  TAG_OBJECT);
3489 
3490  InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
3491  scratch1, scratch2);
3492 }
3493 
3494 
3495 void MacroAssembler::JumpIfNotUniqueNameInstanceType(Register reg,
3496  Label* not_unique_name) {
3498  Label succeed;
3499  And(at, reg, Operand(kIsNotStringMask | kIsNotInternalizedMask));
3500  Branch(&succeed, eq, at, Operand(zero_reg));
3501  Branch(not_unique_name, ne, reg, Operand(SYMBOL_TYPE));
3502 
3503  bind(&succeed);
3504 }
3505 
3506 
3507 // Allocates a heap number or jumps to the label if the young space is full and
3508 // a scavenge is needed.
3509 void MacroAssembler::AllocateHeapNumber(Register result,
3510  Register scratch1,
3511  Register scratch2,
3512  Register heap_number_map,
3513  Label* need_gc,
3514  TaggingMode tagging_mode,
3515  MutableMode mode) {
3516  // Allocate an object in the heap for the heap number and tag it as a heap
3517  // object.
3518  Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc,
3519  tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
3520 
3521  Heap::RootListIndex map_index = mode == MUTABLE
3522  ? Heap::kMutableHeapNumberMapRootIndex
3523  : Heap::kHeapNumberMapRootIndex;
3524  AssertIsRoot(heap_number_map, map_index);
3525 
3526  // Store heap number map in the allocated object.
3527  if (tagging_mode == TAG_RESULT) {
3528  sd(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
3529  } else {
3530  sd(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
3531  }
3532 }
3533 
3534 
3535 void MacroAssembler::AllocateHeapNumberWithValue(Register result,
3536  FPURegister value,
3537  Register scratch1,
3538  Register scratch2,
3539  Label* gc_required) {
3540  LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
3541  AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required);
3542  sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset));
3543 }
3544 
3545 
3546 // Copies a fixed number of fields of heap objects from src to dst.
3547 void MacroAssembler::CopyFields(Register dst,
3548  Register src,
3549  RegList temps,
3550  int field_count) {
3551  DCHECK((temps & dst.bit()) == 0);
3552  DCHECK((temps & src.bit()) == 0);
3553  // Primitive implementation using only one temporary register.
3554 
3555  Register tmp = no_reg;
3556  // Find a temp register in temps list.
3557  for (int i = 0; i < kNumRegisters; i++) {
3558  if ((temps & (1 << i)) != 0) {
3559  tmp.code_ = i;
3560  break;
3561  }
3562  }
3563  DCHECK(!tmp.is(no_reg));
3564 
3565  for (int i = 0; i < field_count; i++) {
3566  ld(tmp, FieldMemOperand(src, i * kPointerSize));
3567  sd(tmp, FieldMemOperand(dst, i * kPointerSize));
3568  }
3569 }
3570 
3571 
3572 void MacroAssembler::CopyBytes(Register src,
3573  Register dst,
3574  Register length,
3575  Register scratch) {
3576  Label align_loop_1, word_loop, byte_loop, byte_loop_1, done;
3577 
3578  // Align src before copying in word size chunks.
3579  Branch(&byte_loop, le, length, Operand(kPointerSize));
3580  bind(&align_loop_1);
3581  And(scratch, src, kPointerSize - 1);
3582  Branch(&word_loop, eq, scratch, Operand(zero_reg));
3583  lbu(scratch, MemOperand(src));
3584  Daddu(src, src, 1);
3585  sb(scratch, MemOperand(dst));
3586  Daddu(dst, dst, 1);
3587  Dsubu(length, length, Operand(1));
3588  Branch(&align_loop_1, ne, length, Operand(zero_reg));
3589 
3590  // Copy bytes in word size chunks.
3591  bind(&word_loop);
3592  if (emit_debug_code()) {
3593  And(scratch, src, kPointerSize - 1);
3594  Assert(eq, kExpectingAlignmentForCopyBytes,
3595  scratch, Operand(zero_reg));
3596  }
3597  Branch(&byte_loop, lt, length, Operand(kPointerSize));
3598  ld(scratch, MemOperand(src));
3599  Daddu(src, src, kPointerSize);
3600 
3601  // TODO(kalmard) check if this can be optimized to use sw in most cases.
3602  // Can't use unaligned access - copy byte by byte.
3603  sb(scratch, MemOperand(dst, 0));
3604  dsrl(scratch, scratch, 8);
3605  sb(scratch, MemOperand(dst, 1));
3606  dsrl(scratch, scratch, 8);
3607  sb(scratch, MemOperand(dst, 2));
3608  dsrl(scratch, scratch, 8);
3609  sb(scratch, MemOperand(dst, 3));
3610  dsrl(scratch, scratch, 8);
3611  sb(scratch, MemOperand(dst, 4));
3612  dsrl(scratch, scratch, 8);
3613  sb(scratch, MemOperand(dst, 5));
3614  dsrl(scratch, scratch, 8);
3615  sb(scratch, MemOperand(dst, 6));
3616  dsrl(scratch, scratch, 8);
3617  sb(scratch, MemOperand(dst, 7));
3618  Daddu(dst, dst, 8);
3619 
3620  Dsubu(length, length, Operand(kPointerSize));
3621  Branch(&word_loop);
3622 
3623  // Copy the last bytes if any left.
3624  bind(&byte_loop);
3625  Branch(&done, eq, length, Operand(zero_reg));
3626  bind(&byte_loop_1);
3627  lbu(scratch, MemOperand(src));
3628  Daddu(src, src, 1);
3629  sb(scratch, MemOperand(dst));
3630  Daddu(dst, dst, 1);
3631  Dsubu(length, length, Operand(1));
3632  Branch(&byte_loop_1, ne, length, Operand(zero_reg));
3633  bind(&done);
3634 }
3635 
3636 
3637 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
3638  Register end_offset,
3639  Register filler) {
3640  Label loop, entry;
3641  Branch(&entry);
3642  bind(&loop);
3643  sd(filler, MemOperand(start_offset));
3644  Daddu(start_offset, start_offset, kPointerSize);
3645  bind(&entry);
3646  Branch(&loop, lt, start_offset, Operand(end_offset));
3647 }
3648 
3649 
3650 void MacroAssembler::CheckFastElements(Register map,
3651  Register scratch,
3652  Label* fail) {
3657  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
3658  Branch(fail, hi, scratch,
3659  Operand(Map::kMaximumBitField2FastHoleyElementValue));
3660 }
3661 
3662 
3663 void MacroAssembler::CheckFastObjectElements(Register map,
3664  Register scratch,
3665  Label* fail) {
3670  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
3671  Branch(fail, ls, scratch,
3672  Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
3673  Branch(fail, hi, scratch,
3674  Operand(Map::kMaximumBitField2FastHoleyElementValue));
3675 }
3676 
3677 
3678 void MacroAssembler::CheckFastSmiElements(Register map,
3679  Register scratch,
3680  Label* fail) {
3683  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
3684  Branch(fail, hi, scratch,
3685  Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
3686 }
3687 
3688 
3689 void MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
3690  Register key_reg,
3691  Register elements_reg,
3692  Register scratch1,
3693  Register scratch2,
3694  Register scratch3,
3695  Label* fail,
3696  int elements_offset) {
3697  Label smi_value, maybe_nan, have_double_value, is_nan, done;
3698  Register mantissa_reg = scratch2;
3699  Register exponent_reg = scratch3;
3700 
3701  // Handle smi values specially.
3702  JumpIfSmi(value_reg, &smi_value);
3703 
3704  // Ensure that the object is a heap number
3705  CheckMap(value_reg,
3706  scratch1,
3707  Heap::kHeapNumberMapRootIndex,
3708  fail,
3710 
3711  // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
3712  // in the exponent.
3713  li(scratch1, Operand(kNaNOrInfinityLowerBoundUpper32));
3714  lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
3715  Branch(&maybe_nan, ge, exponent_reg, Operand(scratch1));
3716 
3717  lwu(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
3718 
3719  bind(&have_double_value);
3720  // dsll(scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize);
3721  dsra(scratch1, key_reg, 32 - kDoubleSizeLog2);
3722  Daddu(scratch1, scratch1, elements_reg);
3723  sw(mantissa_reg, FieldMemOperand(
3724  scratch1, FixedDoubleArray::kHeaderSize - elements_offset));
3725  uint32_t offset = FixedDoubleArray::kHeaderSize - elements_offset +
3726  sizeof(kHoleNanLower32);
3727  sw(exponent_reg, FieldMemOperand(scratch1, offset));
3728  jmp(&done);
3729 
3730  bind(&maybe_nan);
3731  // Could be NaN, Infinity or -Infinity. If fraction is not zero, it's NaN,
3732  // otherwise it's Infinity or -Infinity, and the non-NaN code path applies.
3733  lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
3734  Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg));
3735  bind(&is_nan);
3736  // Load canonical NaN for storing into the double array.
3737  LoadRoot(at, Heap::kNanValueRootIndex);
3738  lw(mantissa_reg, FieldMemOperand(at, HeapNumber::kMantissaOffset));
3739  lw(exponent_reg, FieldMemOperand(at, HeapNumber::kExponentOffset));
3740  jmp(&have_double_value);
3741 
3742  bind(&smi_value);
3743  Daddu(scratch1, elements_reg,
3744  Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag -
3745  elements_offset));
3746  // dsll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize);
3747  dsra(scratch2, key_reg, 32 - kDoubleSizeLog2);
3748  Daddu(scratch1, scratch1, scratch2);
3749  // scratch1 is now effective address of the double element
3750 
3751  Register untagged_value = elements_reg;
3752  SmiUntag(untagged_value, value_reg);
3753  mtc1(untagged_value, f2);
3754  cvt_d_w(f0, f2);
3755  sdc1(f0, MemOperand(scratch1, 0));
3756  bind(&done);
3757 }
3758 
3759 
3760 void MacroAssembler::CompareMapAndBranch(Register obj,
3761  Register scratch,
3762  Handle<Map> map,
3763  Label* early_success,
3764  Condition cond,
3765  Label* branch_to) {
3766  ld(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
3767  CompareMapAndBranch(scratch, map, early_success, cond, branch_to);
3768 }
3769 
3770 
3771 void MacroAssembler::CompareMapAndBranch(Register obj_map,
3772  Handle<Map> map,
3773  Label* early_success,
3774  Condition cond,
3775  Label* branch_to) {
3776  Branch(branch_to, cond, obj_map, Operand(map));
3777 }
3778 
3779 
3780 void MacroAssembler::CheckMap(Register obj,
3781  Register scratch,
3782  Handle<Map> map,
3783  Label* fail,
3784  SmiCheckType smi_check_type) {
3785  if (smi_check_type == DO_SMI_CHECK) {
3786  JumpIfSmi(obj, fail);
3787  }
3788  Label success;
3789  CompareMapAndBranch(obj, scratch, map, &success, ne, fail);
3790  bind(&success);
3791 }
3792 
3793 
3794 void MacroAssembler::DispatchMap(Register obj,
3795  Register scratch,
3796  Handle<Map> map,
3797  Handle<Code> success,
3798  SmiCheckType smi_check_type) {
3799  Label fail;
3800  if (smi_check_type == DO_SMI_CHECK) {
3801  JumpIfSmi(obj, &fail);
3802  }
3803  ld(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
3804  Jump(success, RelocInfo::CODE_TARGET, eq, scratch, Operand(map));
3805  bind(&fail);
3806 }
3807 
3808 
3809 void MacroAssembler::CheckMap(Register obj,
3810  Register scratch,
3811  Heap::RootListIndex index,
3812  Label* fail,
3813  SmiCheckType smi_check_type) {
3814  if (smi_check_type == DO_SMI_CHECK) {
3815  JumpIfSmi(obj, fail);
3816  }
3817  ld(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
3818  LoadRoot(at, index);
3819  Branch(fail, ne, scratch, Operand(at));
3820 }
3821 
3822 
3823 void MacroAssembler::MovFromFloatResult(const DoubleRegister dst) {
3824  if (IsMipsSoftFloatABI) {
3825  Move(dst, v0, v1);
3826  } else {
3827  Move(dst, f0); // Reg f0 is o32 ABI FP return value.
3828  }
3829 }
3830 
3831 
3832 void MacroAssembler::MovFromFloatParameter(const DoubleRegister dst) {
3833  if (IsMipsSoftFloatABI) {
3834  Move(dst, a0, a1);
3835  } else {
3836  Move(dst, f12); // Reg f12 is o32 ABI FP first argument value.
3837  }
3838 }
3839 
3840 
3841 void MacroAssembler::MovToFloatParameter(DoubleRegister src) {
3842  if (!IsMipsSoftFloatABI) {
3843  Move(f12, src);
3844  } else {
3845  Move(a0, a1, src);
3846  }
3847 }
3848 
3849 
3850 void MacroAssembler::MovToFloatResult(DoubleRegister src) {
3851  if (!IsMipsSoftFloatABI) {
3852  Move(f0, src);
3853  } else {
3854  Move(v0, v1, src);
3855  }
3856 }
3857 
3858 
3859 void MacroAssembler::MovToFloatParameters(DoubleRegister src1,
3860  DoubleRegister src2) {
3861  if (!IsMipsSoftFloatABI) {
3862  const DoubleRegister fparg2 = (kMipsAbi == kN64) ? f13 : f14;
3863  if (src2.is(f12)) {
3864  DCHECK(!src1.is(fparg2));
3865  Move(fparg2, src2);
3866  Move(f12, src1);
3867  } else {
3868  Move(f12, src1);
3869  Move(fparg2, src2);
3870  }
3871  } else {
3872  Move(a0, a1, src1);
3873  Move(a2, a3, src2);
3874  }
3875 }
3876 
3877 
3878 // -----------------------------------------------------------------------------
3879 // JavaScript invokes.
3880 
3881 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
3882  const ParameterCount& actual,
3883  Handle<Code> code_constant,
3884  Register code_reg,
3885  Label* done,
3886  bool* definitely_mismatches,
3887  InvokeFlag flag,
3888  const CallWrapper& call_wrapper) {
3889  bool definitely_matches = false;
3890  *definitely_mismatches = false;
3891  Label regular_invoke;
3892 
3893  // Check whether the expected and actual arguments count match. If not,
3894  // setup registers according to contract with ArgumentsAdaptorTrampoline:
3895  // a0: actual arguments count
3896  // a1: function (passed through to callee)
3897  // a2: expected arguments count
3898 
3899  // The code below is made a lot easier because the calling code already sets
3900  // up actual and expected registers according to the contract if values are
3901  // passed in registers.
3902  DCHECK(actual.is_immediate() || actual.reg().is(a0));
3903  DCHECK(expected.is_immediate() || expected.reg().is(a2));
3904  DCHECK((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(a3));
3905 
3906  if (expected.is_immediate()) {
3907  DCHECK(actual.is_immediate());
3908  if (expected.immediate() == actual.immediate()) {
3909  definitely_matches = true;
3910  } else {
3911  li(a0, Operand(actual.immediate()));
3912  const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3913  if (expected.immediate() == sentinel) {
3914  // Don't worry about adapting arguments for builtins that
3915  // don't want that done. Skip adaption code by making it look
3916  // like we have a match between expected and actual number of
3917  // arguments.
3918  definitely_matches = true;
3919  } else {
3920  *definitely_mismatches = true;
3921  li(a2, Operand(expected.immediate()));
3922  }
3923  }
3924  } else if (actual.is_immediate()) {
3925  Branch(&regular_invoke, eq, expected.reg(), Operand(actual.immediate()));
3926  li(a0, Operand(actual.immediate()));
3927  } else {
3928  Branch(&regular_invoke, eq, expected.reg(), Operand(actual.reg()));
3929  }
3930 
3931  if (!definitely_matches) {
3932  if (!code_constant.is_null()) {
3933  li(a3, Operand(code_constant));
3934  daddiu(a3, a3, Code::kHeaderSize - kHeapObjectTag);
3935  }
3936 
3937  Handle<Code> adaptor =
3938  isolate()->builtins()->ArgumentsAdaptorTrampoline();
3939  if (flag == CALL_FUNCTION) {
3940  call_wrapper.BeforeCall(CallSize(adaptor));
3941  Call(adaptor);
3942  call_wrapper.AfterCall();
3943  if (!*definitely_mismatches) {
3944  Branch(done);
3945  }
3946  } else {
3947  Jump(adaptor, RelocInfo::CODE_TARGET);
3948  }
3949  bind(&regular_invoke);
3950  }
3951 }
3952 
3953 
3954 void MacroAssembler::InvokeCode(Register code,
3955  const ParameterCount& expected,
3956  const ParameterCount& actual,
3957  InvokeFlag flag,
3958  const CallWrapper& call_wrapper) {
3959  // You can't call a function without a valid frame.
3960  DCHECK(flag == JUMP_FUNCTION || has_frame());
3961 
3962  Label done;
3963 
3964  bool definitely_mismatches = false;
3965  InvokePrologue(expected, actual, Handle<Code>::null(), code,
3966  &done, &definitely_mismatches, flag,
3967  call_wrapper);
3968  if (!definitely_mismatches) {
3969  if (flag == CALL_FUNCTION) {
3970  call_wrapper.BeforeCall(CallSize(code));
3971  Call(code);
3972  call_wrapper.AfterCall();
3973  } else {
3975  Jump(code);
3976  }
3977  // Continue here if InvokePrologue does handle the invocation due to
3978  // mismatched parameter counts.
3979  bind(&done);
3980  }
3981 }
3982 
3983 
3984 void MacroAssembler::InvokeFunction(Register function,
3985  const ParameterCount& actual,
3986  InvokeFlag flag,
3987  const CallWrapper& call_wrapper) {
3988  // You can't call a function without a valid frame.
3989  DCHECK(flag == JUMP_FUNCTION || has_frame());
3990 
3991  // Contract with called JS functions requires that function is passed in a1.
3992  DCHECK(function.is(a1));
3993  Register expected_reg = a2;
3994  Register code_reg = a3;
3995  ld(code_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
3996  ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
3997  // The argument count is stored as int32_t on 64-bit platforms.
3998  // TODO(plind): Smi on 32-bit platforms.
3999  lw(expected_reg,
4000  FieldMemOperand(code_reg,
4001  SharedFunctionInfo::kFormalParameterCountOffset));
4002  ld(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
4003  ParameterCount expected(expected_reg);
4004  InvokeCode(code_reg, expected, actual, flag, call_wrapper);
4005 }
4006 
4007 
4008 void MacroAssembler::InvokeFunction(Register function,
4009  const ParameterCount& expected,
4010  const ParameterCount& actual,
4011  InvokeFlag flag,
4012  const CallWrapper& call_wrapper) {
4013  // You can't call a function without a valid frame.
4014  DCHECK(flag == JUMP_FUNCTION || has_frame());
4015 
4016  // Contract with called JS functions requires that function is passed in a1.
4017  DCHECK(function.is(a1));
4018 
4019  // Get the function and setup the context.
4020  ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
4021 
4022  // We call indirectly through the code field in the function to
4023  // allow recompilation to take effect without changing any of the
4024  // call sites.
4025  ld(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
4026  InvokeCode(a3, expected, actual, flag, call_wrapper);
4027 }
4028 
4029 
4030 void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
4031  const ParameterCount& expected,
4032  const ParameterCount& actual,
4033  InvokeFlag flag,
4034  const CallWrapper& call_wrapper) {
4035  li(a1, function);
4036  InvokeFunction(a1, expected, actual, flag, call_wrapper);
4037 }
4038 
4039 
4040 void MacroAssembler::IsObjectJSObjectType(Register heap_object,
4041  Register map,
4042  Register scratch,
4043  Label* fail) {
4044  ld(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
4045  IsInstanceJSObjectType(map, scratch, fail);
4046 }
4047 
4048 
4049 void MacroAssembler::IsInstanceJSObjectType(Register map,
4050  Register scratch,
4051  Label* fail) {
4052  lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
4053  Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
4054  Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
4055 }
4056 
4057 
4058 void MacroAssembler::IsObjectJSStringType(Register object,
4059  Register scratch,
4060  Label* fail) {
4061  DCHECK(kNotStringTag != 0);
4062 
4063  ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
4064  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
4065  And(scratch, scratch, Operand(kIsNotStringMask));
4066  Branch(fail, ne, scratch, Operand(zero_reg));
4067 }
4068 
4069 
4070 void MacroAssembler::IsObjectNameType(Register object,
4071  Register scratch,
4072  Label* fail) {
4073  ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
4074  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
4075  Branch(fail, hi, scratch, Operand(LAST_NAME_TYPE));
4076 }
4077 
4078 
4079 // ---------------------------------------------------------------------------
4080 // Support functions.
4081 
4082 
4083 void MacroAssembler::TryGetFunctionPrototype(Register function,
4084  Register result,
4085  Register scratch,
4086  Label* miss,
4087  bool miss_on_bound_function) {
4088  Label non_instance;
4089  if (miss_on_bound_function) {
4090  // Check that the receiver isn't a smi.
4091  JumpIfSmi(function, miss);
4092 
4093  // Check that the function really is a function. Load map into result reg.
4094  GetObjectType(function, result, scratch);
4095  Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE));
4096 
4097  ld(scratch,
4098  FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
4099  lwu(scratch,
4100  FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
4101  And(scratch, scratch,
4102  Operand(1 << SharedFunctionInfo::kBoundFunction));
4103  Branch(miss, ne, scratch, Operand(zero_reg));
4104 
4105  // Make sure that the function has an instance prototype.
4106  lbu(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
4107  And(scratch, scratch, Operand(1 << Map::kHasNonInstancePrototype));
4108  Branch(&non_instance, ne, scratch, Operand(zero_reg));
4109  }
4110 
4111  // Get the prototype or initial map from the function.
4112  ld(result,
4113  FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
4114 
4115  // If the prototype or initial map is the hole, don't return it and
4116  // simply miss the cache instead. This will allow us to allocate a
4117  // prototype object on-demand in the runtime system.
4118  LoadRoot(t8, Heap::kTheHoleValueRootIndex);
4119  Branch(miss, eq, result, Operand(t8));
4120 
4121  // If the function does not have an initial map, we're done.
4122  Label done;
4123  GetObjectType(result, scratch, scratch);
4124  Branch(&done, ne, scratch, Operand(MAP_TYPE));
4125 
4126  // Get the prototype from the initial map.
4127  ld(result, FieldMemOperand(result, Map::kPrototypeOffset));
4128 
4129  if (miss_on_bound_function) {
4130  jmp(&done);
4131 
4132  // Non-instance prototype: Fetch prototype from constructor field
4133  // in initial map.
4134  bind(&non_instance);
4135  ld(result, FieldMemOperand(result, Map::kConstructorOffset));
4136  }
4137 
4138  // All done.
4139  bind(&done);
4140 }
4141 
4142 
4143 void MacroAssembler::GetObjectType(Register object,
4144  Register map,
4145  Register type_reg) {
4146  ld(map, FieldMemOperand(object, HeapObject::kMapOffset));
4147  lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
4148 }
4149 
4150 
4151 // -----------------------------------------------------------------------------
4152 // Runtime calls.
4153 
4154 void MacroAssembler::CallStub(CodeStub* stub,
4155  TypeFeedbackId ast_id,
4156  Condition cond,
4157  Register r1,
4158  const Operand& r2,
4159  BranchDelaySlot bd) {
4160  DCHECK(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs.
4161  Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id,
4162  cond, r1, r2, bd);
4163 }
4164 
4165 
4166 void MacroAssembler::TailCallStub(CodeStub* stub,
4167  Condition cond,
4168  Register r1,
4169  const Operand& r2,
4170  BranchDelaySlot bd) {
4171  Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2, bd);
4172 }
4173 
4174 
4175 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
4176  int64_t offset = (ref0.address() - ref1.address());
4177  DCHECK(static_cast<int>(offset) == offset);
4178  return static_cast<int>(offset);
4179 }
4180 
4181 
4182 void MacroAssembler::CallApiFunctionAndReturn(
4183  Register function_address,
4184  ExternalReference thunk_ref,
4185  int stack_space,
4186  MemOperand return_value_operand,
4187  MemOperand* context_restore_operand) {
4188  ExternalReference next_address =
4189  ExternalReference::handle_scope_next_address(isolate());
4190  const int kNextOffset = 0;
4191  const int kLimitOffset = AddressOffset(
4192  ExternalReference::handle_scope_limit_address(isolate()),
4193  next_address);
4194  const int kLevelOffset = AddressOffset(
4195  ExternalReference::handle_scope_level_address(isolate()),
4196  next_address);
4197 
4198  DCHECK(function_address.is(a1) || function_address.is(a2));
4199 
4200  Label profiler_disabled;
4201  Label end_profiler_check;
4202  li(t9, Operand(ExternalReference::is_profiling_address(isolate())));
4203  lb(t9, MemOperand(t9, 0));
4204  Branch(&profiler_disabled, eq, t9, Operand(zero_reg));
4205 
4206  // Additional parameter is the address of the actual callback.
4207  li(t9, Operand(thunk_ref));
4208  jmp(&end_profiler_check);
4209 
4210  bind(&profiler_disabled);
4211  mov(t9, function_address);
4212  bind(&end_profiler_check);
4213 
4214  // Allocate HandleScope in callee-save registers.
4215  li(s3, Operand(next_address));
4216  ld(s0, MemOperand(s3, kNextOffset));
4217  ld(s1, MemOperand(s3, kLimitOffset));
4218  ld(s2, MemOperand(s3, kLevelOffset));
4219  Daddu(s2, s2, Operand(1));
4220  sd(s2, MemOperand(s3, kLevelOffset));
4221 
4222  if (FLAG_log_timer_events) {
4223  FrameScope frame(this, StackFrame::MANUAL);
4224  PushSafepointRegisters();
4225  PrepareCallCFunction(1, a0);
4226  li(a0, Operand(ExternalReference::isolate_address(isolate())));
4227  CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
4228  PopSafepointRegisters();
4229  }
4230 
4231  // Native call returns to the DirectCEntry stub which redirects to the
4232  // return address pushed on stack (could have moved after GC).
4233  // DirectCEntry stub itself is generated early and never moves.
4234  DirectCEntryStub stub(isolate());
4235  stub.GenerateCall(this, t9);
4236 
4237  if (FLAG_log_timer_events) {
4238  FrameScope frame(this, StackFrame::MANUAL);
4239  PushSafepointRegisters();
4240  PrepareCallCFunction(1, a0);
4241  li(a0, Operand(ExternalReference::isolate_address(isolate())));
4242  CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1);
4243  PopSafepointRegisters();
4244  }
4245 
4246  Label promote_scheduled_exception;
4247  Label exception_handled;
4248  Label delete_allocated_handles;
4249  Label leave_exit_frame;
4250  Label return_value_loaded;
4251 
4252  // Load value from ReturnValue.
4253  ld(v0, return_value_operand);
4254  bind(&return_value_loaded);
4255 
4256  // No more valid handles (the result handle was the last one). Restore
4257  // previous handle scope.
4258  sd(s0, MemOperand(s3, kNextOffset));
4259  if (emit_debug_code()) {
4260  ld(a1, MemOperand(s3, kLevelOffset));
4261  Check(eq, kUnexpectedLevelAfterReturnFromApiCall, a1, Operand(s2));
4262  }
4263  Dsubu(s2, s2, Operand(1));
4264  sd(s2, MemOperand(s3, kLevelOffset));
4265  ld(at, MemOperand(s3, kLimitOffset));
4266  Branch(&delete_allocated_handles, ne, s1, Operand(at));
4267 
4268  // Check if the function scheduled an exception.
4269  bind(&leave_exit_frame);
4270  LoadRoot(a4, Heap::kTheHoleValueRootIndex);
4271  li(at, Operand(ExternalReference::scheduled_exception_address(isolate())));
4272  ld(a5, MemOperand(at));
4273  Branch(&promote_scheduled_exception, ne, a4, Operand(a5));
4274  bind(&exception_handled);
4275 
4276  bool restore_context = context_restore_operand != NULL;
4277  if (restore_context) {
4278  ld(cp, *context_restore_operand);
4279  }
4280  li(s0, Operand(stack_space));
4281  LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN);
4282 
4283  bind(&promote_scheduled_exception);
4284  {
4285  FrameScope frame(this, StackFrame::INTERNAL);
4286  CallExternalReference(
4287  ExternalReference(Runtime::kPromoteScheduledException, isolate()),
4288  0);
4289  }
4290  jmp(&exception_handled);
4291 
4292  // HandleScope limit has changed. Delete allocated extensions.
4293  bind(&delete_allocated_handles);
4294  sd(s1, MemOperand(s3, kLimitOffset));
4295  mov(s0, v0);
4296  mov(a0, v0);
4297  PrepareCallCFunction(1, s1);
4298  li(a0, Operand(ExternalReference::isolate_address(isolate())));
4299  CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate()),
4300  1);
4301  mov(v0, s0);
4302  jmp(&leave_exit_frame);
4303 }
4304 
4305 
4306 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
4307  return has_frame_ || !stub->SometimesSetsUpAFrame();
4308 }
4309 
4310 
4311 void MacroAssembler::IndexFromHash(Register hash, Register index) {
4312  // If the hash field contains an array index pick it out. The assert checks
4313  // that the constants for the maximum number of digits for an array index
4314  // cached in the hash field and the number of bits reserved for it does not
4315  // conflict.
4316  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
4317  (1 << String::kArrayIndexValueBits));
4318  DecodeFieldToSmi<String::ArrayIndexValueBits>(index, hash);
4319 }
4320 
4321 
4322 void MacroAssembler::ObjectToDoubleFPURegister(Register object,
4323  FPURegister result,
4324  Register scratch1,
4325  Register scratch2,
4326  Register heap_number_map,
4327  Label* not_number,
4329  Label done;
4330  if ((flags & OBJECT_NOT_SMI) == 0) {
4331  Label not_smi;
4332  JumpIfNotSmi(object, &not_smi);
4333  // Remove smi tag and convert to double.
4334  // dsra(scratch1, object, kSmiTagSize);
4335  dsra32(scratch1, object, 0);
4336  mtc1(scratch1, result);
4337  cvt_d_w(result, result);
4338  Branch(&done);
4339  bind(&not_smi);
4340  }
4341  // Check for heap number and load double value from it.
4342  ld(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
4343  Branch(not_number, ne, scratch1, Operand(heap_number_map));
4344 
4345  if ((flags & AVOID_NANS_AND_INFINITIES) != 0) {
4346  // If exponent is all ones the number is either a NaN or +/-Infinity.
4347  Register exponent = scratch1;
4348  Register mask_reg = scratch2;
4349  lwu(exponent, FieldMemOperand(object, HeapNumber::kExponentOffset));
4350  li(mask_reg, HeapNumber::kExponentMask);
4351 
4352  And(exponent, exponent, mask_reg);
4353  Branch(not_number, eq, exponent, Operand(mask_reg));
4354  }
4355  ldc1(result, FieldMemOperand(object, HeapNumber::kValueOffset));
4356  bind(&done);
4357 }
4358 
4359 
4360 void MacroAssembler::SmiToDoubleFPURegister(Register smi,
4361  FPURegister value,
4362  Register scratch1) {
4363  // dsra(scratch1, smi, kSmiTagSize);
4364  dsra32(scratch1, smi, 0);
4365  mtc1(scratch1, value);
4366  cvt_d_w(value, value);
4367 }
4368 
4369 
4370 void MacroAssembler::AdduAndCheckForOverflow(Register dst,
4371  Register left,
4372  Register right,
4373  Register overflow_dst,
4374  Register scratch) {
4375  DCHECK(!dst.is(overflow_dst));
4376  DCHECK(!dst.is(scratch));
4377  DCHECK(!overflow_dst.is(scratch));
4378  DCHECK(!overflow_dst.is(left));
4379  DCHECK(!overflow_dst.is(right));
4380 
4381  if (left.is(right) && dst.is(left)) {
4382  DCHECK(!dst.is(t9));
4383  DCHECK(!scratch.is(t9));
4384  DCHECK(!left.is(t9));
4385  DCHECK(!right.is(t9));
4386  DCHECK(!overflow_dst.is(t9));
4387  mov(t9, right);
4388  right = t9;
4389  }
4390 
4391  if (dst.is(left)) {
4392  mov(scratch, left); // Preserve left.
4393  daddu(dst, left, right); // Left is overwritten.
4394  xor_(scratch, dst, scratch); // Original left.
4395  xor_(overflow_dst, dst, right);
4396  and_(overflow_dst, overflow_dst, scratch);
4397  } else if (dst.is(right)) {
4398  mov(scratch, right); // Preserve right.
4399  daddu(dst, left, right); // Right is overwritten.
4400  xor_(scratch, dst, scratch); // Original right.
4401  xor_(overflow_dst, dst, left);
4402  and_(overflow_dst, overflow_dst, scratch);
4403  } else {
4404  daddu(dst, left, right);
4405  xor_(overflow_dst, dst, left);
4406  xor_(scratch, dst, right);
4407  and_(overflow_dst, scratch, overflow_dst);
4408  }
4409 }
4410 
4411 
4412 void MacroAssembler::SubuAndCheckForOverflow(Register dst,
4413  Register left,
4414  Register right,
4415  Register overflow_dst,
4416  Register scratch) {
4417  DCHECK(!dst.is(overflow_dst));
4418  DCHECK(!dst.is(scratch));
4419  DCHECK(!overflow_dst.is(scratch));
4420  DCHECK(!overflow_dst.is(left));
4421  DCHECK(!overflow_dst.is(right));
4422  DCHECK(!scratch.is(left));
4423  DCHECK(!scratch.is(right));
4424 
4425  // This happens with some crankshaft code. Since Subu works fine if
4426  // left == right, let's not make that restriction here.
4427  if (left.is(right)) {
4428  mov(dst, zero_reg);
4429  mov(overflow_dst, zero_reg);
4430  return;
4431  }
4432 
4433  if (dst.is(left)) {
4434  mov(scratch, left); // Preserve left.
4435  dsubu(dst, left, right); // Left is overwritten.
4436  xor_(overflow_dst, dst, scratch); // scratch is original left.
4437  xor_(scratch, scratch, right); // scratch is original left.
4438  and_(overflow_dst, scratch, overflow_dst);
4439  } else if (dst.is(right)) {
4440  mov(scratch, right); // Preserve right.
4441  dsubu(dst, left, right); // Right is overwritten.
4442  xor_(overflow_dst, dst, left);
4443  xor_(scratch, left, scratch); // Original right.
4444  and_(overflow_dst, scratch, overflow_dst);
4445  } else {
4446  dsubu(dst, left, right);
4447  xor_(overflow_dst, dst, left);
4448  xor_(scratch, left, right);
4449  and_(overflow_dst, scratch, overflow_dst);
4450  }
4451 }
4452 
4453 
4454 void MacroAssembler::CallRuntime(const Runtime::Function* f,
4455  int num_arguments,
4456  SaveFPRegsMode save_doubles) {
4457  // All parameters are on the stack. v0 has the return value after call.
4458 
4459  // If the expected number of arguments of the runtime function is
4460  // constant, we check that the actual number of arguments match the
4461  // expectation.
4462  CHECK(f->nargs < 0 || f->nargs == num_arguments);
4463 
4464  // TODO(1236192): Most runtime routines don't need the number of
4465  // arguments passed in because it is constant. At some point we
4466  // should remove this need and make the runtime routine entry code
4467  // smarter.
4468  PrepareCEntryArgs(num_arguments);
4469  PrepareCEntryFunction(ExternalReference(f, isolate()));
4470  CEntryStub stub(isolate(), 1, save_doubles);
4471  CallStub(&stub);
4472 }
4473 
4474 
4475 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
4476  int num_arguments,
4477  BranchDelaySlot bd) {
4478  PrepareCEntryArgs(num_arguments);
4479  PrepareCEntryFunction(ext);
4480 
4481  CEntryStub stub(isolate(), 1);
4482  CallStub(&stub, TypeFeedbackId::None(), al, zero_reg, Operand(zero_reg), bd);
4483 }
4484 
4485 
4486 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
4487  int num_arguments,
4488  int result_size) {
4489  // TODO(1236192): Most runtime routines don't need the number of
4490  // arguments passed in because it is constant. At some point we
4491  // should remove this need and make the runtime routine entry code
4492  // smarter.
4493  PrepareCEntryArgs(num_arguments);
4494  JumpToExternalReference(ext);
4495 }
4496 
4497 
4498 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
4499  int num_arguments,
4500  int result_size) {
4501  TailCallExternalReference(ExternalReference(fid, isolate()),
4502  num_arguments,
4503  result_size);
4504 }
4505 
4506 
4507 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
4508  BranchDelaySlot bd) {
4509  PrepareCEntryFunction(builtin);
4510  CEntryStub stub(isolate(), 1);
4511  Jump(stub.GetCode(),
4512  RelocInfo::CODE_TARGET,
4513  al,
4514  zero_reg,
4515  Operand(zero_reg),
4516  bd);
4517 }
4518 
4519 
4520 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
4521  InvokeFlag flag,
4522  const CallWrapper& call_wrapper) {
4523  // You can't call a builtin without a valid frame.
4524  DCHECK(flag == JUMP_FUNCTION || has_frame());
4525 
4526  GetBuiltinEntry(t9, id);
4527  if (flag == CALL_FUNCTION) {
4528  call_wrapper.BeforeCall(CallSize(t9));
4529  Call(t9);
4530  call_wrapper.AfterCall();
4531  } else {
4533  Jump(t9);
4534  }
4535 }
4536 
4537 
4538 void MacroAssembler::GetBuiltinFunction(Register target,
4539  Builtins::JavaScript id) {
4540  // Load the builtins object into target register.
4541  ld(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
4542  ld(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
4543  // Load the JavaScript builtin function from the builtins object.
4544  ld(target, FieldMemOperand(target,
4545  JSBuiltinsObject::OffsetOfFunctionWithId(id)));
4546 }
4547 
4548 
4549 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
4550  DCHECK(!target.is(a1));
4551  GetBuiltinFunction(a1, id);
4552  // Load the code entry point from the builtins object.
4553  ld(target, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
4554 }
4555 
4556 
4557 void MacroAssembler::SetCounter(StatsCounter* counter, int value,
4558  Register scratch1, Register scratch2) {
4559  if (FLAG_native_code_counters && counter->Enabled()) {
4560  li(scratch1, Operand(value));
4561  li(scratch2, Operand(ExternalReference(counter)));
4562  sd(scratch1, MemOperand(scratch2));
4563  }
4564 }
4565 
4566 
4567 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
4568  Register scratch1, Register scratch2) {
4569  DCHECK(value > 0);
4570  if (FLAG_native_code_counters && counter->Enabled()) {
4571  li(scratch2, Operand(ExternalReference(counter)));
4572  ld(scratch1, MemOperand(scratch2));
4573  Daddu(scratch1, scratch1, Operand(value));
4574  sd(scratch1, MemOperand(scratch2));
4575  }
4576 }
4577 
4578 
4579 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
4580  Register scratch1, Register scratch2) {
4581  DCHECK(value > 0);
4582  if (FLAG_native_code_counters && counter->Enabled()) {
4583  li(scratch2, Operand(ExternalReference(counter)));
4584  ld(scratch1, MemOperand(scratch2));
4585  Dsubu(scratch1, scratch1, Operand(value));
4586  sd(scratch1, MemOperand(scratch2));
4587  }
4588 }
4589 
4590 
4591 // -----------------------------------------------------------------------------
4592 // Debugging.
4593 
4594 void MacroAssembler::Assert(Condition cc, BailoutReason reason,
4595  Register rs, Operand rt) {
4596  if (emit_debug_code())
4597  Check(cc, reason, rs, rt);
4598 }
4599 
4600 
4601 void MacroAssembler::AssertFastElements(Register elements) {
4602  if (emit_debug_code()) {
4603  DCHECK(!elements.is(at));
4604  Label ok;
4605  push(elements);
4606  ld(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
4607  LoadRoot(at, Heap::kFixedArrayMapRootIndex);
4608  Branch(&ok, eq, elements, Operand(at));
4609  LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex);
4610  Branch(&ok, eq, elements, Operand(at));
4611  LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);
4612  Branch(&ok, eq, elements, Operand(at));
4613  Abort(kJSObjectWithFastElementsMapHasSlowElements);
4614  bind(&ok);
4615  pop(elements);
4616  }
4617 }
4618 
4619 
4620 void MacroAssembler::Check(Condition cc, BailoutReason reason,
4621  Register rs, Operand rt) {
4622  Label L;
4623  Branch(&L, cc, rs, rt);
4624  Abort(reason);
4625  // Will not return here.
4626  bind(&L);
4627 }
4628 
4629 
4630 void MacroAssembler::Abort(BailoutReason reason) {
4631  Label abort_start;
4632  bind(&abort_start);
4633 #ifdef DEBUG
4634  const char* msg = GetBailoutReason(reason);
4635  if (msg != NULL) {
4636  RecordComment("Abort message: ");
4637  RecordComment(msg);
4638  }
4639 
4640  if (FLAG_trap_on_abort) {
4641  stop(msg);
4642  return;
4643  }
4644 #endif
4645 
4646  li(a0, Operand(Smi::FromInt(reason)));
4647  push(a0);
4648  // Disable stub call restrictions to always allow calls to abort.
4649  if (!has_frame_) {
4650  // We don't actually want to generate a pile of code for this, so just
4651  // claim there is a stack frame, without generating one.
4652  FrameScope scope(this, StackFrame::NONE);
4653  CallRuntime(Runtime::kAbort, 1);
4654  } else {
4655  CallRuntime(Runtime::kAbort, 1);
4656  }
4657  // Will not return here.
4658  if (is_trampoline_pool_blocked()) {
4659  // If the calling code cares about the exact number of
4660  // instructions generated, we insert padding here to keep the size
4661  // of the Abort macro constant.
4662  // Currently in debug mode with debug_code enabled the number of
4663  // generated instructions is 10, so we use this as a maximum value.
4664  static const int kExpectedAbortInstructions = 10;
4665  int abort_instructions = InstructionsGeneratedSince(&abort_start);
4666  DCHECK(abort_instructions <= kExpectedAbortInstructions);
4667  while (abort_instructions++ < kExpectedAbortInstructions) {
4668  nop();
4669  }
4670  }
4671 }
4672 
4673 
4674 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
4675  if (context_chain_length > 0) {
4676  // Move up the chain of contexts to the context containing the slot.
4677  ld(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
4678  for (int i = 1; i < context_chain_length; i++) {
4679  ld(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
4680  }
4681  } else {
4682  // Slot is in the current function context. Move it into the
4683  // destination register in case we store into it (the write barrier
4684  // cannot be allowed to destroy the context in esi).
4685  Move(dst, cp);
4686  }
4687 }
4688 
4689 
4690 void MacroAssembler::LoadTransitionedArrayMapConditional(
4691  ElementsKind expected_kind,
4692  ElementsKind transitioned_kind,
4693  Register map_in_out,
4694  Register scratch,
4695  Label* no_map_match) {
4696  // Load the global or builtins object from the current context.
4697  ld(scratch,
4698  MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
4699  ld(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
4700 
4701  // Check that the function's map is the same as the expected cached map.
4702  ld(scratch,
4703  MemOperand(scratch,
4704  Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX)));
4705  size_t offset = expected_kind * kPointerSize +
4706  FixedArrayBase::kHeaderSize;
4707  ld(at, FieldMemOperand(scratch, offset));
4708  Branch(no_map_match, ne, map_in_out, Operand(at));
4709 
4710  // Use the transitioned cached map.
4711  offset = transitioned_kind * kPointerSize +
4712  FixedArrayBase::kHeaderSize;
4713  ld(map_in_out, FieldMemOperand(scratch, offset));
4714 }
4715 
4716 
4717 void MacroAssembler::LoadGlobalFunction(int index, Register function) {
4718  // Load the global or builtins object from the current context.
4719  ld(function,
4720  MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
4721  // Load the native context from the global or builtins object.
4722  ld(function, FieldMemOperand(function,
4723  GlobalObject::kNativeContextOffset));
4724  // Load the function from the native context.
4725  ld(function, MemOperand(function, Context::SlotOffset(index)));
4726 }
4727 
4728 
4729 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
4730  Register map,
4731  Register scratch) {
4732  // Load the initial map. The global functions all have initial maps.
4733  ld(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
4734  if (emit_debug_code()) {
4735  Label ok, fail;
4736  CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
4737  Branch(&ok);
4738  bind(&fail);
4739  Abort(kGlobalFunctionsMustHaveInitialMap);
4740  bind(&ok);
4741  }
4742 }
4743 
4744 
4745 void MacroAssembler::StubPrologue() {
4746  Push(ra, fp, cp);
4747  Push(Smi::FromInt(StackFrame::STUB));
4748  // Adjust FP to point to saved FP.
4749  Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
4750 }
4751 
4752 
4753 void MacroAssembler::Prologue(bool code_pre_aging) {
4754  PredictableCodeSizeScope predictible_code_size_scope(
4755  this, kNoCodeAgeSequenceLength);
4756  // The following three instructions must remain together and unmodified
4757  // for code aging to work properly.
4758  if (code_pre_aging) {
4759  // Pre-age the code.
4760  Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
4761  nop(Assembler::CODE_AGE_MARKER_NOP);
4762  // Load the stub address to t9 and call it,
4763  // GetCodeAgeAndParity() extracts the stub address from this instruction.
4764  li(t9,
4765  Operand(reinterpret_cast<uint64_t>(stub->instruction_start())),
4766  ADDRESS_LOAD);
4767  nop(); // Prevent jalr to jal optimization.
4768  jalr(t9, a0);
4769  nop(); // Branch delay slot nop.
4770  nop(); // Pad the empty space.
4771  } else {
4772  Push(ra, fp, cp, a1);
4773  nop(Assembler::CODE_AGE_SEQUENCE_NOP);
4774  nop(Assembler::CODE_AGE_SEQUENCE_NOP);
4775  nop(Assembler::CODE_AGE_SEQUENCE_NOP);
4776  // Adjust fp to point to caller's fp.
4777  Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
4778  }
4779 }
4780 
4781 
4782 void MacroAssembler::EnterFrame(StackFrame::Type type) {
4783  daddiu(sp, sp, -5 * kPointerSize);
4784  li(t8, Operand(Smi::FromInt(type)));
4785  li(t9, Operand(CodeObject()), CONSTANT_SIZE);
4786  sd(ra, MemOperand(sp, 4 * kPointerSize));
4787  sd(fp, MemOperand(sp, 3 * kPointerSize));
4788  sd(cp, MemOperand(sp, 2 * kPointerSize));
4789  sd(t8, MemOperand(sp, 1 * kPointerSize));
4790  sd(t9, MemOperand(sp, 0 * kPointerSize));
4791  // Adjust FP to point to saved FP.
4792  Daddu(fp, sp,
4793  Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize));
4794 }
4795 
4796 
4797 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
4798  mov(sp, fp);
4799  ld(fp, MemOperand(sp, 0 * kPointerSize));
4800  ld(ra, MemOperand(sp, 1 * kPointerSize));
4801  daddiu(sp, sp, 2 * kPointerSize);
4802 }
4803 
4804 
4805 void MacroAssembler::EnterExitFrame(bool save_doubles,
4806  int stack_space) {
4807  // Set up the frame structure on the stack.
4808  STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement);
4809  STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset);
4810  STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset);
4811 
4812  // This is how the stack will look:
4813  // fp + 2 (==kCallerSPDisplacement) - old stack's end
4814  // [fp + 1 (==kCallerPCOffset)] - saved old ra
4815  // [fp + 0 (==kCallerFPOffset)] - saved old fp
4816  // [fp - 1 (==kSPOffset)] - sp of the called function
4817  // [fp - 2 (==kCodeOffset)] - CodeObject
4818  // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the
4819  // new stack (will contain saved ra)
4820 
4821  // Save registers.
4822  daddiu(sp, sp, -4 * kPointerSize);
4823  sd(ra, MemOperand(sp, 3 * kPointerSize));
4824  sd(fp, MemOperand(sp, 2 * kPointerSize));
4825  daddiu(fp, sp, 2 * kPointerSize); // Set up new frame pointer.
4826 
4827  if (emit_debug_code()) {
4828  sd(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset));
4829  }
4830 
4831  // Accessed from ExitFrame::code_slot.
4832  li(t8, Operand(CodeObject()), CONSTANT_SIZE);
4833  sd(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
4834 
4835  // Save the frame pointer and the context in top.
4836  li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
4837  sd(fp, MemOperand(t8));
4838  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
4839  sd(cp, MemOperand(t8));
4840 
4841  const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
4842  if (save_doubles) {
4843  // The stack is already aligned to 0 modulo 8 for stores with sdc1.
4844  int kNumOfSavedRegisters = FPURegister::kMaxNumRegisters / 2;
4845  int space = kNumOfSavedRegisters * kDoubleSize ;
4846  Dsubu(sp, sp, Operand(space));
4847  // Remember: we only need to save every 2nd double FPU value.
4848  for (int i = 0; i < kNumOfSavedRegisters; i++) {
4849  FPURegister reg = FPURegister::from_code(2 * i);
4850  sdc1(reg, MemOperand(sp, i * kDoubleSize));
4851  }
4852  }
4853 
4854  // Reserve place for the return address, stack space and an optional slot
4855  // (used by the DirectCEntryStub to hold the return value if a struct is
4856  // returned) and align the frame preparing for calling the runtime function.
4857  DCHECK(stack_space >= 0);
4858  Dsubu(sp, sp, Operand((stack_space + 2) * kPointerSize));
4859  if (frame_alignment > 0) {
4860  DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
4861  And(sp, sp, Operand(-frame_alignment)); // Align stack.
4862  }
4863 
4864  // Set the exit frame sp value to point just before the return address
4865  // location.
4866  daddiu(at, sp, kPointerSize);
4867  sd(at, MemOperand(fp, ExitFrameConstants::kSPOffset));
4868 }
4869 
4870 
4871 void MacroAssembler::LeaveExitFrame(bool save_doubles,
4872  Register argument_count,
4873  bool restore_context,
4874  bool do_return) {
4875  // Optionally restore all double registers.
4876  if (save_doubles) {
4877  // Remember: we only need to restore every 2nd double FPU value.
4878  int kNumOfSavedRegisters = FPURegister::kMaxNumRegisters / 2;
4879  Dsubu(t8, fp, Operand(ExitFrameConstants::kFrameSize +
4880  kNumOfSavedRegisters * kDoubleSize));
4881  for (int i = 0; i < kNumOfSavedRegisters; i++) {
4882  FPURegister reg = FPURegister::from_code(2 * i);
4883  ldc1(reg, MemOperand(t8, i * kDoubleSize));
4884  }
4885  }
4886 
4887  // Clear top frame.
4888  li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
4889  sd(zero_reg, MemOperand(t8));
4890 
4891  // Restore current context from top and clear it in debug mode.
4892  if (restore_context) {
4893  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
4894  ld(cp, MemOperand(t8));
4895  }
4896 #ifdef DEBUG
4897  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
4898  sd(a3, MemOperand(t8));
4899 #endif
4900 
4901  // Pop the arguments, restore registers, and return.
4902  mov(sp, fp); // Respect ABI stack constraint.
4903  ld(fp, MemOperand(sp, ExitFrameConstants::kCallerFPOffset));
4904  ld(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset));
4905 
4906  if (argument_count.is_valid()) {
4907  dsll(t8, argument_count, kPointerSizeLog2);
4908  daddu(sp, sp, t8);
4909  }
4910 
4911  if (do_return) {
4912  Ret(USE_DELAY_SLOT);
4913  // If returning, the instruction in the delay slot will be the addiu below.
4914  }
4915  daddiu(sp, sp, 2 * kPointerSize);
4916 }
4917 
4918 
4919 void MacroAssembler::InitializeNewString(Register string,
4920  Register length,
4921  Heap::RootListIndex map_index,
4922  Register scratch1,
4923  Register scratch2) {
4924  // dsll(scratch1, length, kSmiTagSize);
4925  dsll32(scratch1, length, 0);
4926  LoadRoot(scratch2, map_index);
4927  sd(scratch1, FieldMemOperand(string, String::kLengthOffset));
4928  li(scratch1, Operand(String::kEmptyHashField));
4929  sd(scratch2, FieldMemOperand(string, HeapObject::kMapOffset));
4930  sd(scratch1, FieldMemOperand(string, String::kHashFieldOffset));
4931 }
4932 
4933 
4934 int MacroAssembler::ActivationFrameAlignment() {
4935 #if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64
4936  // Running on the real platform. Use the alignment as mandated by the local
4937  // environment.
4938  // Note: This will break if we ever start generating snapshots on one Mips
4939  // platform for another Mips platform with a different alignment.
4940  return base::OS::ActivationFrameAlignment();
4941 #else // V8_HOST_ARCH_MIPS
4942  // If we are using the simulator then we should always align to the expected
4943  // alignment. As the simulator is used to generate snapshots we do not know
4944  // if the target platform will need alignment, so this is controlled from a
4945  // flag.
4946  return FLAG_sim_stack_alignment;
4947 #endif // V8_HOST_ARCH_MIPS
4948 }
4949 
4950 
4951 void MacroAssembler::AssertStackIsAligned() {
4952  if (emit_debug_code()) {
4953  const int frame_alignment = ActivationFrameAlignment();
4954  const int frame_alignment_mask = frame_alignment - 1;
4955 
4956  if (frame_alignment > kPointerSize) {
4957  Label alignment_as_expected;
4958  DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
4959  andi(at, sp, frame_alignment_mask);
4960  Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
4961  // Don't use Check here, as it will call Runtime_Abort re-entering here.
4962  stop("Unexpected stack alignment");
4963  bind(&alignment_as_expected);
4964  }
4965  }
4966 }
4967 
4968 
4969 void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
4970  Register reg,
4971  Register scratch,
4972  Label* not_power_of_two_or_zero) {
4973  Dsubu(scratch, reg, Operand(1));
4974  Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt,
4975  scratch, Operand(zero_reg));
4976  and_(at, scratch, reg); // In the delay slot.
4977  Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg));
4978 }
4979 
4980 
4981 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) {
4982  DCHECK(!reg.is(overflow));
4983  mov(overflow, reg); // Save original value.
4984  SmiTag(reg);
4985  xor_(overflow, overflow, reg); // Overflow if (value ^ 2 * value) < 0.
4986 }
4987 
4988 
4989 void MacroAssembler::SmiTagCheckOverflow(Register dst,
4990  Register src,
4991  Register overflow) {
4992  if (dst.is(src)) {
4993  // Fall back to slower case.
4994  SmiTagCheckOverflow(dst, overflow);
4995  } else {
4996  DCHECK(!dst.is(src));
4997  DCHECK(!dst.is(overflow));
4998  DCHECK(!src.is(overflow));
4999  SmiTag(dst, src);
5000  xor_(overflow, dst, src); // Overflow if (value ^ 2 * value) < 0.
5001  }
5002 }
5003 
5004 
5005 void MacroAssembler::SmiLoadUntag(Register dst, MemOperand src) {
5006  if (SmiValuesAre32Bits()) {
5007  lw(dst, UntagSmiMemOperand(src.rm(), src.offset()));
5008  } else {
5009  lw(dst, src);
5010  SmiUntag(dst);
5011  }
5012 }
5013 
5014 
5015 void MacroAssembler::SmiLoadScale(Register dst, MemOperand src, int scale) {
5016  if (SmiValuesAre32Bits()) {
5017  // TODO(plind): not clear if lw or ld faster here, need micro-benchmark.
5018  lw(dst, UntagSmiMemOperand(src.rm(), src.offset()));
5019  dsll(dst, dst, scale);
5020  } else {
5021  lw(dst, src);
5022  DCHECK(scale >= kSmiTagSize);
5023  sll(dst, dst, scale - kSmiTagSize);
5024  }
5025 }
5026 
5027 
5028 // Returns 2 values: the Smi and a scaled version of the int within the Smi.
5029 void MacroAssembler::SmiLoadWithScale(Register d_smi,
5030  Register d_scaled,
5031  MemOperand src,
5032  int scale) {
5033  if (SmiValuesAre32Bits()) {
5034  ld(d_smi, src);
5035  dsra(d_scaled, d_smi, kSmiShift - scale);
5036  } else {
5037  lw(d_smi, src);
5038  DCHECK(scale >= kSmiTagSize);
5039  sll(d_scaled, d_smi, scale - kSmiTagSize);
5040  }
5041 }
5042 
5043 
5044 // Returns 2 values: the untagged Smi (int32) and scaled version of that int.
5045 void MacroAssembler::SmiLoadUntagWithScale(Register d_int,
5046  Register d_scaled,
5047  MemOperand src,
5048  int scale) {
5049  if (SmiValuesAre32Bits()) {
5050  lw(d_int, UntagSmiMemOperand(src.rm(), src.offset()));
5051  dsll(d_scaled, d_int, scale);
5052  } else {
5053  lw(d_int, src);
5054  // Need both the int and the scaled in, so use two instructions.
5055  SmiUntag(d_int);
5056  sll(d_scaled, d_int, scale);
5057  }
5058 }
5059 
5060 
5061 void MacroAssembler::UntagAndJumpIfSmi(Register dst,
5062  Register src,
5063  Label* smi_case) {
5064  // DCHECK(!dst.is(src));
5065  JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT);
5066  SmiUntag(dst, src);
5067 }
5068 
5069 
5070 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst,
5071  Register src,
5072  Label* non_smi_case) {
5073  // DCHECK(!dst.is(src));
5074  JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT);
5075  SmiUntag(dst, src);
5076 }
5077 
5078 void MacroAssembler::JumpIfSmi(Register value,
5079  Label* smi_label,
5080  Register scratch,
5081  BranchDelaySlot bd) {
5082  DCHECK_EQ(0, kSmiTag);
5083  andi(scratch, value, kSmiTagMask);
5084  Branch(bd, smi_label, eq, scratch, Operand(zero_reg));
5085 }
5086 
5087 void MacroAssembler::JumpIfNotSmi(Register value,
5088  Label* not_smi_label,
5089  Register scratch,
5090  BranchDelaySlot bd) {
5091  DCHECK_EQ(0, kSmiTag);
5092  andi(scratch, value, kSmiTagMask);
5093  Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg));
5094 }
5095 
5096 
5097 void MacroAssembler::JumpIfNotBothSmi(Register reg1,
5098  Register reg2,
5099  Label* on_not_both_smi) {
5100  STATIC_ASSERT(kSmiTag == 0);
5101  // TODO(plind): Find some better to fix this assert issue.
5102 #if defined(__APPLE__)
5103  DCHECK_EQ(1, kSmiTagMask);
5104 #else
5105  DCHECK_EQ((uint64_t)1, kSmiTagMask);
5106 #endif
5107  or_(at, reg1, reg2);
5108  JumpIfNotSmi(at, on_not_both_smi);
5109 }
5110 
5111 
5112 void MacroAssembler::JumpIfEitherSmi(Register reg1,
5113  Register reg2,
5114  Label* on_either_smi) {
5115  STATIC_ASSERT(kSmiTag == 0);
5116  // TODO(plind): Find some better to fix this assert issue.
5117 #if defined(__APPLE__)
5118  DCHECK_EQ(1, kSmiTagMask);
5119 #else
5120  DCHECK_EQ((uint64_t)1, kSmiTagMask);
5121 #endif
5122  // Both Smi tags must be 1 (not Smi).
5123  and_(at, reg1, reg2);
5124  JumpIfSmi(at, on_either_smi);
5125 }
5126 
5127 
5128 void MacroAssembler::AssertNotSmi(Register object) {
5129  if (emit_debug_code()) {
5130  STATIC_ASSERT(kSmiTag == 0);
5131  andi(at, object, kSmiTagMask);
5132  Check(ne, kOperandIsASmi, at, Operand(zero_reg));
5133  }
5134 }
5135 
5136 
5137 void MacroAssembler::AssertSmi(Register object) {
5138  if (emit_debug_code()) {
5139  STATIC_ASSERT(kSmiTag == 0);
5140  andi(at, object, kSmiTagMask);
5141  Check(eq, kOperandIsASmi, at, Operand(zero_reg));
5142  }
5143 }
5144 
5145 
5146 void MacroAssembler::AssertString(Register object) {
5147  if (emit_debug_code()) {
5148  STATIC_ASSERT(kSmiTag == 0);
5149  SmiTst(object, a4);
5150  Check(ne, kOperandIsASmiAndNotAString, a4, Operand(zero_reg));
5151  push(object);
5152  ld(object, FieldMemOperand(object, HeapObject::kMapOffset));
5153  lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset));
5154  Check(lo, kOperandIsNotAString, object, Operand(FIRST_NONSTRING_TYPE));
5155  pop(object);
5156  }
5157 }
5158 
5159 
5160 void MacroAssembler::AssertName(Register object) {
5161  if (emit_debug_code()) {
5162  STATIC_ASSERT(kSmiTag == 0);
5163  SmiTst(object, a4);
5164  Check(ne, kOperandIsASmiAndNotAName, a4, Operand(zero_reg));
5165  push(object);
5166  ld(object, FieldMemOperand(object, HeapObject::kMapOffset));
5167  lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset));
5168  Check(le, kOperandIsNotAName, object, Operand(LAST_NAME_TYPE));
5169  pop(object);
5170  }
5171 }
5172 
5173 
5174 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
5175  Register scratch) {
5176  if (emit_debug_code()) {
5177  Label done_checking;
5178  AssertNotSmi(object);
5179  LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
5180  Branch(&done_checking, eq, object, Operand(scratch));
5181  push(object);
5182  ld(object, FieldMemOperand(object, HeapObject::kMapOffset));
5183  LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex);
5184  Assert(eq, kExpectedUndefinedOrCell, object, Operand(scratch));
5185  pop(object);
5186  bind(&done_checking);
5187  }
5188 }
5189 
5190 
5191 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
5192  if (emit_debug_code()) {
5193  DCHECK(!reg.is(at));
5194  LoadRoot(at, index);
5195  Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at));
5196  }
5197 }
5198 
5199 
5200 void MacroAssembler::JumpIfNotHeapNumber(Register object,
5201  Register heap_number_map,
5202  Register scratch,
5203  Label* on_not_heap_number) {
5204  ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
5205  AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
5206  Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map));
5207 }
5208 
5209 
5210 void MacroAssembler::LookupNumberStringCache(Register object,
5211  Register result,
5212  Register scratch1,
5213  Register scratch2,
5214  Register scratch3,
5215  Label* not_found) {
5216  // Use of registers. Register result is used as a temporary.
5217  Register number_string_cache = result;
5218  Register mask = scratch3;
5219 
5220  // Load the number string cache.
5221  LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
5222 
5223  // Make the hash mask from the length of the number string cache. It
5224  // contains two elements (number and string) for each cache entry.
5225  ld(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset));
5226  // Divide length by two (length is a smi).
5227  // dsra(mask, mask, kSmiTagSize + 1);
5228  dsra32(mask, mask, 1);
5229  Daddu(mask, mask, -1); // Make mask.
5230 
5231  // Calculate the entry in the number string cache. The hash value in the
5232  // number string cache for smis is just the smi value, and the hash for
5233  // doubles is the xor of the upper and lower words. See
5234  // Heap::GetNumberStringCache.
5235  Label is_smi;
5236  Label load_result_from_cache;
5237  JumpIfSmi(object, &is_smi);
5238  CheckMap(object,
5239  scratch1,
5240  Heap::kHeapNumberMapRootIndex,
5241  not_found,
5243 
5244  STATIC_ASSERT(8 == kDoubleSize);
5245  Daddu(scratch1,
5246  object,
5247  Operand(HeapNumber::kValueOffset - kHeapObjectTag));
5248  ld(scratch2, MemOperand(scratch1, kPointerSize));
5249  ld(scratch1, MemOperand(scratch1, 0));
5250  Xor(scratch1, scratch1, Operand(scratch2));
5251  And(scratch1, scratch1, Operand(mask));
5252 
5253  // Calculate address of entry in string cache: each entry consists
5254  // of two pointer sized fields.
5255  dsll(scratch1, scratch1, kPointerSizeLog2 + 1);
5256  Daddu(scratch1, number_string_cache, scratch1);
5257 
5258  Register probe = mask;
5259  ld(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize));
5260  JumpIfSmi(probe, not_found);
5261  ldc1(f12, FieldMemOperand(object, HeapNumber::kValueOffset));
5262  ldc1(f14, FieldMemOperand(probe, HeapNumber::kValueOffset));
5263  BranchF(&load_result_from_cache, NULL, eq, f12, f14);
5264  Branch(not_found);
5265 
5266  bind(&is_smi);
5267  Register scratch = scratch1;
5268  // dsra(scratch, object, 1); // Shift away the tag.
5269  dsra32(scratch, scratch, 0);
5270  And(scratch, mask, Operand(scratch));
5271 
5272  // Calculate address of entry in string cache: each entry consists
5273  // of two pointer sized fields.
5274  dsll(scratch, scratch, kPointerSizeLog2 + 1);
5275  Daddu(scratch, number_string_cache, scratch);
5276 
5277  // Check if the entry is the smi we are looking for.
5278  ld(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize));
5279  Branch(not_found, ne, object, Operand(probe));
5280 
5281  // Get the result from the cache.
5282  bind(&load_result_from_cache);
5283  ld(result, FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
5284 
5285  IncrementCounter(isolate()->counters()->number_to_string_native(),
5286  1,
5287  scratch1,
5288  scratch2);
5289 }
5290 
5291 
5292 void MacroAssembler::JumpIfNonSmisNotBothSequentialOneByteStrings(
5293  Register first, Register second, Register scratch1, Register scratch2,
5294  Label* failure) {
5295  // Test that both first and second are sequential one-byte strings.
5296  // Assume that they are non-smis.
5297  ld(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
5298  ld(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
5299  lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
5300  lbu(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
5301 
5302  JumpIfBothInstanceTypesAreNotSequentialOneByte(scratch1, scratch2, scratch1,
5303  scratch2, failure);
5304 }
5305 
5306 
5307 void MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register first,
5308  Register second,
5309  Register scratch1,
5310  Register scratch2,
5311  Label* failure) {
5312  // Check that neither is a smi.
5313  STATIC_ASSERT(kSmiTag == 0);
5314  And(scratch1, first, Operand(second));
5315  JumpIfSmi(scratch1, failure);
5316  JumpIfNonSmisNotBothSequentialOneByteStrings(first, second, scratch1,
5317  scratch2, failure);
5318 }
5319 
5320 
5321 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
5322  Register first, Register second, Register scratch1, Register scratch2,
5323  Label* failure) {
5324  const int kFlatOneByteStringMask =
5326  const int kFlatOneByteStringTag =
5328  DCHECK(kFlatOneByteStringTag <= 0xffff); // Ensure this fits 16-bit immed.
5329  andi(scratch1, first, kFlatOneByteStringMask);
5330  Branch(failure, ne, scratch1, Operand(kFlatOneByteStringTag));
5331  andi(scratch2, second, kFlatOneByteStringMask);
5332  Branch(failure, ne, scratch2, Operand(kFlatOneByteStringTag));
5333 }
5334 
5335 
5336 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(Register type,
5337  Register scratch,
5338  Label* failure) {
5339  const int kFlatOneByteStringMask =
5341  const int kFlatOneByteStringTag =
5343  And(scratch, type, Operand(kFlatOneByteStringMask));
5344  Branch(failure, ne, scratch, Operand(kFlatOneByteStringTag));
5345 }
5346 
5347 
5348 static const int kRegisterPassedArguments = (kMipsAbi == kN64) ? 8 : 4;
5349 
5350 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
5351  int num_double_arguments) {
5352  int stack_passed_words = 0;
5353  num_reg_arguments += 2 * num_double_arguments;
5354 
5355  // O32: Up to four simple arguments are passed in registers a0..a3.
5356  // N64: Up to eight simple arguments are passed in registers a0..a7.
5357  if (num_reg_arguments > kRegisterPassedArguments) {
5358  stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
5359  }
5360  stack_passed_words += kCArgSlotCount;
5361  return stack_passed_words;
5362 }
5363 
5364 
5365 void MacroAssembler::EmitSeqStringSetCharCheck(Register string,
5366  Register index,
5367  Register value,
5368  Register scratch,
5369  uint32_t encoding_mask) {
5370  Label is_object;
5371  SmiTst(string, at);
5372  Check(ne, kNonObject, at, Operand(zero_reg));
5373 
5374  ld(at, FieldMemOperand(string, HeapObject::kMapOffset));
5375  lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
5376 
5378  li(scratch, Operand(encoding_mask));
5379  Check(eq, kUnexpectedStringType, at, Operand(scratch));
5380 
5381  // TODO(plind): requires Smi size check code for mips32.
5382 
5383  ld(at, FieldMemOperand(string, String::kLengthOffset));
5384  Check(lt, kIndexIsTooLarge, index, Operand(at));
5385 
5386  DCHECK(Smi::FromInt(0) == 0);
5387  Check(ge, kIndexIsNegative, index, Operand(zero_reg));
5388 }
5389 
5390 
5391 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
5392  int num_double_arguments,
5393  Register scratch) {
5394  int frame_alignment = ActivationFrameAlignment();
5395 
5396  // n64: Up to eight simple arguments in a0..a3, a4..a7, No argument slots.
5397  // O32: Up to four simple arguments are passed in registers a0..a3.
5398  // Those four arguments must have reserved argument slots on the stack for
5399  // mips, even though those argument slots are not normally used.
5400  // Both ABIs: Remaining arguments are pushed on the stack, above (higher
5401  // address than) the (O32) argument slots. (arg slot calculation handled by
5402  // CalculateStackPassedWords()).
5403  int stack_passed_arguments = CalculateStackPassedWords(
5404  num_reg_arguments, num_double_arguments);
5405  if (frame_alignment > kPointerSize) {
5406  // Make stack end at alignment and make room for num_arguments - 4 words
5407  // and the original value of sp.
5408  mov(scratch, sp);
5409  Dsubu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
5410  DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
5411  And(sp, sp, Operand(-frame_alignment));
5412  sd(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
5413  } else {
5414  Dsubu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
5415  }
5416 }
5417 
5418 
5419 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
5420  Register scratch) {
5421  PrepareCallCFunction(num_reg_arguments, 0, scratch);
5422 }
5423 
5424 
5425 void MacroAssembler::CallCFunction(ExternalReference function,
5426  int num_reg_arguments,
5427  int num_double_arguments) {
5428  li(t8, Operand(function));
5429  CallCFunctionHelper(t8, num_reg_arguments, num_double_arguments);
5430 }
5431 
5432 
5433 void MacroAssembler::CallCFunction(Register function,
5434  int num_reg_arguments,
5435  int num_double_arguments) {
5436  CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
5437 }
5438 
5439 
5440 void MacroAssembler::CallCFunction(ExternalReference function,
5441  int num_arguments) {
5442  CallCFunction(function, num_arguments, 0);
5443 }
5444 
5445 
5446 void MacroAssembler::CallCFunction(Register function,
5447  int num_arguments) {
5448  CallCFunction(function, num_arguments, 0);
5449 }
5450 
5451 
5452 void MacroAssembler::CallCFunctionHelper(Register function,
5453  int num_reg_arguments,
5454  int num_double_arguments) {
5455  DCHECK(has_frame());
5456  // Make sure that the stack is aligned before calling a C function unless
5457  // running in the simulator. The simulator has its own alignment check which
5458  // provides more information.
5459  // The argument stots are presumed to have been set up by
5460  // PrepareCallCFunction. The C function must be called via t9, for mips ABI.
5461 
5462 #if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64
5463  if (emit_debug_code()) {
5464  int frame_alignment = base::OS::ActivationFrameAlignment();
5465  int frame_alignment_mask = frame_alignment - 1;
5466  if (frame_alignment > kPointerSize) {
5467  DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
5468  Label alignment_as_expected;
5469  And(at, sp, Operand(frame_alignment_mask));
5470  Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
5471  // Don't use Check here, as it will call Runtime_Abort possibly
5472  // re-entering here.
5473  stop("Unexpected alignment in CallCFunction");
5474  bind(&alignment_as_expected);
5475  }
5476  }
5477 #endif // V8_HOST_ARCH_MIPS
5478 
5479  // Just call directly. The function called cannot cause a GC, or
5480  // allow preemption, so the return address in the link register
5481  // stays correct.
5482 
5483  if (!function.is(t9)) {
5484  mov(t9, function);
5485  function = t9;
5486  }
5487 
5488  Call(function);
5489 
5490  int stack_passed_arguments = CalculateStackPassedWords(
5491  num_reg_arguments, num_double_arguments);
5492 
5493  if (base::OS::ActivationFrameAlignment() > kPointerSize) {
5494  ld(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
5495  } else {
5496  Daddu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
5497  }
5498 }
5499 
5500 
5501 #undef BRANCH_ARGS_CHECK
5502 
5503 
5504 void MacroAssembler::PatchRelocatedValue(Register li_location,
5505  Register scratch,
5506  Register new_value) {
5507  lwu(scratch, MemOperand(li_location));
5508  // At this point scratch is a lui(at, ...) instruction.
5509  if (emit_debug_code()) {
5510  And(scratch, scratch, kOpcodeMask);
5511  Check(eq, kTheInstructionToPatchShouldBeALui,
5512  scratch, Operand(LUI));
5513  lwu(scratch, MemOperand(li_location));
5514  }
5515  dsrl32(t9, new_value, 0);
5516  Ins(scratch, t9, 0, kImm16Bits);
5517  sw(scratch, MemOperand(li_location));
5518 
5519  lwu(scratch, MemOperand(li_location, kInstrSize));
5520  // scratch is now ori(at, ...).
5521  if (emit_debug_code()) {
5522  And(scratch, scratch, kOpcodeMask);
5523  Check(eq, kTheInstructionToPatchShouldBeAnOri,
5524  scratch, Operand(ORI));
5525  lwu(scratch, MemOperand(li_location, kInstrSize));
5526  }
5527  dsrl(t9, new_value, kImm16Bits);
5528  Ins(scratch, t9, 0, kImm16Bits);
5529  sw(scratch, MemOperand(li_location, kInstrSize));
5530 
5531  lwu(scratch, MemOperand(li_location, kInstrSize * 3));
5532  // scratch is now ori(at, ...).
5533  if (emit_debug_code()) {
5534  And(scratch, scratch, kOpcodeMask);
5535  Check(eq, kTheInstructionToPatchShouldBeAnOri,
5536  scratch, Operand(ORI));
5537  lwu(scratch, MemOperand(li_location, kInstrSize * 3));
5538  }
5539 
5540  Ins(scratch, new_value, 0, kImm16Bits);
5541  sw(scratch, MemOperand(li_location, kInstrSize * 3));
5542 
5543  // Update the I-cache so the new lui and ori can be executed.
5544  FlushICache(li_location, 4);
5545 }
5546 
5547 void MacroAssembler::GetRelocatedValue(Register li_location,
5548  Register value,
5549  Register scratch) {
5550  lwu(value, MemOperand(li_location));
5551  if (emit_debug_code()) {
5552  And(value, value, kOpcodeMask);
5553  Check(eq, kTheInstructionShouldBeALui,
5554  value, Operand(LUI));
5555  lwu(value, MemOperand(li_location));
5556  }
5557 
5558  // value now holds a lui instruction. Extract the immediate.
5559  andi(value, value, kImm16Mask);
5560  dsll32(value, value, kImm16Bits);
5561 
5562  lwu(scratch, MemOperand(li_location, kInstrSize));
5563  if (emit_debug_code()) {
5564  And(scratch, scratch, kOpcodeMask);
5565  Check(eq, kTheInstructionShouldBeAnOri,
5566  scratch, Operand(ORI));
5567  lwu(scratch, MemOperand(li_location, kInstrSize));
5568  }
5569  // "scratch" now holds an ori instruction. Extract the immediate.
5570  andi(scratch, scratch, kImm16Mask);
5571  dsll32(scratch, scratch, 0);
5572 
5573  or_(value, value, scratch);
5574 
5575  lwu(scratch, MemOperand(li_location, kInstrSize * 3));
5576  if (emit_debug_code()) {
5577  And(scratch, scratch, kOpcodeMask);
5578  Check(eq, kTheInstructionShouldBeAnOri,
5579  scratch, Operand(ORI));
5580  lwu(scratch, MemOperand(li_location, kInstrSize * 3));
5581  }
5582  // "scratch" now holds an ori instruction. Extract the immediate.
5583  andi(scratch, scratch, kImm16Mask);
5584  dsll(scratch, scratch, kImm16Bits);
5585 
5586  or_(value, value, scratch);
5587  // Sign extend extracted address.
5588  dsra(value, value, kImm16Bits);
5589 }
5590 
5591 
5592 void MacroAssembler::CheckPageFlag(
5593  Register object,
5594  Register scratch,
5595  int mask,
5596  Condition cc,
5597  Label* condition_met) {
5598  And(scratch, object, Operand(~Page::kPageAlignmentMask));
5599  ld(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
5600  And(scratch, scratch, Operand(mask));
5601  Branch(condition_met, cc, scratch, Operand(zero_reg));
5602 }
5603 
5604 
5605 void MacroAssembler::CheckMapDeprecated(Handle<Map> map,
5606  Register scratch,
5607  Label* if_deprecated) {
5608  if (map->CanBeDeprecated()) {
5609  li(scratch, Operand(map));
5610  ld(scratch, FieldMemOperand(scratch, Map::kBitField3Offset));
5611  And(scratch, scratch, Operand(Map::Deprecated::kMask));
5612  Branch(if_deprecated, ne, scratch, Operand(zero_reg));
5613  }
5614 }
5615 
5616 
5617 void MacroAssembler::JumpIfBlack(Register object,
5618  Register scratch0,
5619  Register scratch1,
5620  Label* on_black) {
5621  HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern.
5622  DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
5623 }
5624 
5625 
5626 void MacroAssembler::HasColor(Register object,
5627  Register bitmap_scratch,
5628  Register mask_scratch,
5629  Label* has_color,
5630  int first_bit,
5631  int second_bit) {
5632  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t8));
5633  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t9));
5634 
5635  GetMarkBits(object, bitmap_scratch, mask_scratch);
5636 
5637  Label other_color;
5638  // Note that we are using a 4-byte aligned 8-byte load.
5639  Uld(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
5640  And(t8, t9, Operand(mask_scratch));
5641  Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg));
5642  // Shift left 1 by adding.
5643  Daddu(mask_scratch, mask_scratch, Operand(mask_scratch));
5644  And(t8, t9, Operand(mask_scratch));
5645  Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg));
5646 
5647  bind(&other_color);
5648 }
5649 
5650 
5651 // Detect some, but not all, common pointer-free objects. This is used by the
5652 // incremental write barrier which doesn't care about oddballs (they are always
5653 // marked black immediately so this code is not hit).
5654 void MacroAssembler::JumpIfDataObject(Register value,
5655  Register scratch,
5656  Label* not_data_object) {
5657  DCHECK(!AreAliased(value, scratch, t8, no_reg));
5658  Label is_data_object;
5659  ld(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
5660  LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
5661  Branch(&is_data_object, eq, t8, Operand(scratch));
5663  DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
5664  // If it's a string and it's not a cons string then it's an object containing
5665  // no GC pointers.
5666  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
5667  And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask));
5668  Branch(not_data_object, ne, t8, Operand(zero_reg));
5669  bind(&is_data_object);
5670 }
5671 
5672 
5673 void MacroAssembler::GetMarkBits(Register addr_reg,
5674  Register bitmap_reg,
5675  Register mask_reg) {
5676  DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
5677  // addr_reg is divided into fields:
5678  // |63 page base 20|19 high 8|7 shift 3|2 0|
5679  // 'high' gives the index of the cell holding color bits for the object.
5680  // 'shift' gives the offset in the cell for this object's color.
5681  And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask));
5682  Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2);
5683  const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
5684  Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits);
5685  dsll(t8, t8, Bitmap::kBytesPerCellLog2);
5686  Daddu(bitmap_reg, bitmap_reg, t8);
5687  li(t8, Operand(1));
5688  dsllv(mask_reg, t8, mask_reg);
5689 }
5690 
5691 
5692 void MacroAssembler::EnsureNotWhite(
5693  Register value,
5694  Register bitmap_scratch,
5695  Register mask_scratch,
5696  Register load_scratch,
5697  Label* value_is_white_and_not_data) {
5698  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, t8));
5699  GetMarkBits(value, bitmap_scratch, mask_scratch);
5700 
5701  // If the value is black or grey we don't need to do anything.
5702  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
5703  DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
5704  DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0);
5705  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
5706 
5707  Label done;
5708 
5709  // Since both black and grey have a 1 in the first position and white does
5710  // not have a 1 there we only need to check one bit.
5711  // Note that we are using a 4-byte aligned 8-byte load.
5712  Uld(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
5713  And(t8, mask_scratch, load_scratch);
5714  Branch(&done, ne, t8, Operand(zero_reg));
5715 
5716  if (emit_debug_code()) {
5717  // Check for impossible bit pattern.
5718  Label ok;
5719  // sll may overflow, making the check conservative.
5720  dsll(t8, mask_scratch, 1);
5721  And(t8, load_scratch, t8);
5722  Branch(&ok, eq, t8, Operand(zero_reg));
5723  stop("Impossible marking bit pattern");
5724  bind(&ok);
5725  }
5726 
5727  // Value is white. We check whether it is data that doesn't need scanning.
5728  // Currently only checks for HeapNumber and non-cons strings.
5729  Register map = load_scratch; // Holds map while checking type.
5730  Register length = load_scratch; // Holds length of object after testing type.
5731  Label is_data_object;
5732 
5733  // Check for heap-number
5734  ld(map, FieldMemOperand(value, HeapObject::kMapOffset));
5735  LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
5736  {
5737  Label skip;
5738  Branch(&skip, ne, t8, Operand(map));
5739  li(length, HeapNumber::kSize);
5740  Branch(&is_data_object);
5741  bind(&skip);
5742  }
5743 
5744  // Check for strings.
5746  DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
5747  // If it's a string and it's not a cons string then it's an object containing
5748  // no GC pointers.
5749  Register instance_type = load_scratch;
5750  lbu(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset));
5751  And(t8, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask));
5752  Branch(value_is_white_and_not_data, ne, t8, Operand(zero_reg));
5753  // It's a non-indirect (non-cons and non-slice) string.
5754  // If it's external, the length is just ExternalString::kSize.
5755  // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
5756  // External strings are the only ones with the kExternalStringTag bit
5757  // set.
5760  And(t8, instance_type, Operand(kExternalStringTag));
5761  {
5762  Label skip;
5763  Branch(&skip, eq, t8, Operand(zero_reg));
5764  li(length, ExternalString::kSize);
5765  Branch(&is_data_object);
5766  bind(&skip);
5767  }
5768 
5769  // Sequential string, either Latin1 or UC16.
5770  // For Latin1 (char-size of 1) we shift the smi tag away to get the length.
5771  // For UC16 (char-size of 2) we just leave the smi tag in place, thereby
5772  // getting the length multiplied by 2.
5774  DCHECK(kSmiTag == 0 && kSmiTagSize == 1);
5775  lw(t9, UntagSmiFieldMemOperand(value, String::kLengthOffset));
5776  And(t8, instance_type, Operand(kStringEncodingMask));
5777  {
5778  Label skip;
5779  Branch(&skip, ne, t8, Operand(zero_reg));
5780  // Adjust length for UC16.
5781  dsll(t9, t9, 1);
5782  bind(&skip);
5783  }
5784  Daddu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask));
5785  DCHECK(!length.is(t8));
5786  And(length, length, Operand(~kObjectAlignmentMask));
5787 
5788  bind(&is_data_object);
5789  // Value is a data object, and it is white. Mark it black. Since we know
5790  // that the object is white we can make it black by flipping one bit.
5791  Uld(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
5792  Or(t8, t8, Operand(mask_scratch));
5793  Usd(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
5794 
5795  And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask));
5796  Uld(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
5797  Daddu(t8, t8, Operand(length));
5798  Usd(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
5799 
5800  bind(&done);
5801 }
5802 
5803 
5804 void MacroAssembler::LoadInstanceDescriptors(Register map,
5805  Register descriptors) {
5806  ld(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
5807 }
5808 
5809 
5810 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
5811  ld(dst, FieldMemOperand(map, Map::kBitField3Offset));
5812  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
5813 }
5814 
5815 
5816 void MacroAssembler::EnumLength(Register dst, Register map) {
5817  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
5818  ld(dst, FieldMemOperand(map, Map::kBitField3Offset));
5819  And(dst, dst, Operand(Map::EnumLengthBits::kMask));
5820  SmiTag(dst);
5821 }
5822 
5823 
5824 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
5825  Register empty_fixed_array_value = a6;
5826  LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
5827  Label next, start;
5828  mov(a2, a0);
5829 
5830  // Check if the enum length field is properly initialized, indicating that
5831  // there is an enum cache.
5832  ld(a1, FieldMemOperand(a2, HeapObject::kMapOffset));
5833 
5834  EnumLength(a3, a1);
5835  Branch(
5836  call_runtime, eq, a3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel)));
5837 
5838  jmp(&start);
5839 
5840  bind(&next);
5841  ld(a1, FieldMemOperand(a2, HeapObject::kMapOffset));
5842 
5843  // For all objects but the receiver, check that the cache is empty.
5844  EnumLength(a3, a1);
5845  Branch(call_runtime, ne, a3, Operand(Smi::FromInt(0)));
5846 
5847  bind(&start);
5848 
5849  // Check that there are no elements. Register a2 contains the current JS
5850  // object we've reached through the prototype chain.
5851  Label no_elements;
5852  ld(a2, FieldMemOperand(a2, JSObject::kElementsOffset));
5853  Branch(&no_elements, eq, a2, Operand(empty_fixed_array_value));
5854 
5855  // Second chance, the object may be using the empty slow element dictionary.
5856  LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex);
5857  Branch(call_runtime, ne, a2, Operand(at));
5858 
5859  bind(&no_elements);
5860  ld(a2, FieldMemOperand(a1, Map::kPrototypeOffset));
5861  Branch(&next, ne, a2, Operand(null_value));
5862 }
5863 
5864 
5865 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
5866  DCHECK(!output_reg.is(input_reg));
5867  Label done;
5868  li(output_reg, Operand(255));
5869  // Normal branch: nop in delay slot.
5870  Branch(&done, gt, input_reg, Operand(output_reg));
5871  // Use delay slot in this branch.
5872  Branch(USE_DELAY_SLOT, &done, lt, input_reg, Operand(zero_reg));
5873  mov(output_reg, zero_reg); // In delay slot.
5874  mov(output_reg, input_reg); // Value is in range 0..255.
5875  bind(&done);
5876 }
5877 
5878 
5879 void MacroAssembler::ClampDoubleToUint8(Register result_reg,
5880  DoubleRegister input_reg,
5881  DoubleRegister temp_double_reg) {
5882  Label above_zero;
5883  Label done;
5884  Label in_bounds;
5885 
5886  Move(temp_double_reg, 0.0);
5887  BranchF(&above_zero, NULL, gt, input_reg, temp_double_reg);
5888 
5889  // Double value is less than zero, NaN or Inf, return 0.
5890  mov(result_reg, zero_reg);
5891  Branch(&done);
5892 
5893  // Double value is >= 255, return 255.
5894  bind(&above_zero);
5895  Move(temp_double_reg, 255.0);
5896  BranchF(&in_bounds, NULL, le, input_reg, temp_double_reg);
5897  li(result_reg, Operand(255));
5898  Branch(&done);
5899 
5900  // In 0-255 range, round and truncate.
5901  bind(&in_bounds);
5902  cvt_w_d(temp_double_reg, input_reg);
5903  mfc1(result_reg, temp_double_reg);
5904  bind(&done);
5905 }
5906 
5907 
5908 void MacroAssembler::TestJSArrayForAllocationMemento(
5909  Register receiver_reg,
5910  Register scratch_reg,
5911  Label* no_memento_found,
5912  Condition cond,
5913  Label* allocation_memento_present) {
5914  ExternalReference new_space_start =
5915  ExternalReference::new_space_start(isolate());
5916  ExternalReference new_space_allocation_top =
5917  ExternalReference::new_space_allocation_top_address(isolate());
5918  Daddu(scratch_reg, receiver_reg,
5919  Operand(JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
5920  Branch(no_memento_found, lt, scratch_reg, Operand(new_space_start));
5921  li(at, Operand(new_space_allocation_top));
5922  ld(at, MemOperand(at));
5923  Branch(no_memento_found, gt, scratch_reg, Operand(at));
5924  ld(scratch_reg, MemOperand(scratch_reg, -AllocationMemento::kSize));
5925  if (allocation_memento_present) {
5926  Branch(allocation_memento_present, cond, scratch_reg,
5927  Operand(isolate()->factory()->allocation_memento_map()));
5928  }
5929 }
5930 
5931 
5932 Register GetRegisterThatIsNotOneOf(Register reg1,
5933  Register reg2,
5934  Register reg3,
5935  Register reg4,
5936  Register reg5,
5937  Register reg6) {
5938  RegList regs = 0;
5939  if (reg1.is_valid()) regs |= reg1.bit();
5940  if (reg2.is_valid()) regs |= reg2.bit();
5941  if (reg3.is_valid()) regs |= reg3.bit();
5942  if (reg4.is_valid()) regs |= reg4.bit();
5943  if (reg5.is_valid()) regs |= reg5.bit();
5944  if (reg6.is_valid()) regs |= reg6.bit();
5945 
5946  for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
5947  Register candidate = Register::FromAllocationIndex(i);
5948  if (regs & candidate.bit()) continue;
5949  return candidate;
5950  }
5951  UNREACHABLE();
5952  return no_reg;
5953 }
5954 
5955 
5956 void MacroAssembler::JumpIfDictionaryInPrototypeChain(
5957  Register object,
5958  Register scratch0,
5959  Register scratch1,
5960  Label* found) {
5961  DCHECK(!scratch1.is(scratch0));
5962  Factory* factory = isolate()->factory();
5963  Register current = scratch0;
5964  Label loop_again;
5965 
5966  // Scratch contained elements pointer.
5967  Move(current, object);
5968 
5969  // Loop based on the map going up the prototype chain.
5970  bind(&loop_again);
5971  ld(current, FieldMemOperand(current, HeapObject::kMapOffset));
5972  lb(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
5973  DecodeField<Map::ElementsKindBits>(scratch1);
5974  Branch(found, eq, scratch1, Operand(DICTIONARY_ELEMENTS));
5975  ld(current, FieldMemOperand(current, Map::kPrototypeOffset));
5976  Branch(&loop_again, ne, current, Operand(factory->null_value()));
5977 }
5978 
5979 
5980 bool AreAliased(Register reg1,
5981  Register reg2,
5982  Register reg3,
5983  Register reg4,
5984  Register reg5,
5985  Register reg6,
5986  Register reg7,
5987  Register reg8) {
5988  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
5989  reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
5990  reg7.is_valid() + reg8.is_valid();
5991 
5992  RegList regs = 0;
5993  if (reg1.is_valid()) regs |= reg1.bit();
5994  if (reg2.is_valid()) regs |= reg2.bit();
5995  if (reg3.is_valid()) regs |= reg3.bit();
5996  if (reg4.is_valid()) regs |= reg4.bit();
5997  if (reg5.is_valid()) regs |= reg5.bit();
5998  if (reg6.is_valid()) regs |= reg6.bit();
5999  if (reg7.is_valid()) regs |= reg7.bit();
6000  if (reg8.is_valid()) regs |= reg8.bit();
6001  int n_of_non_aliasing_regs = NumRegs(regs);
6002 
6003  return n_of_valid_regs != n_of_non_aliasing_regs;
6004 }
6005 
6006 
6007 CodePatcher::CodePatcher(byte* address,
6008  int instructions,
6009  FlushICache flush_cache)
6010  : address_(address),
6011  size_(instructions * Assembler::kInstrSize),
6012  masm_(NULL, address, size_ + Assembler::kGap),
6013  flush_cache_(flush_cache) {
6014  // Create a new macro assembler pointing to the address of the code to patch.
6015  // The size is adjusted with kGap on order for the assembler to generate size
6016  // bytes of instructions without failing with buffer size constraints.
6017  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
6018 }
6019 
6020 
6021 CodePatcher::~CodePatcher() {
6022  // Indicate that code has changed.
6023  if (flush_cache_ == FLUSH) {
6024  CpuFeatures::FlushICache(address_, size_);
6025  }
6026  // Check that the code was patched as expected.
6027  DCHECK(masm_.pc_ == address_ + size_);
6028  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
6029 }
6030 
6031 
6032 void CodePatcher::Emit(Instr instr) {
6033  masm()->emit(instr);
6034 }
6035 
6036 
6037 void CodePatcher::Emit(Address addr) {
6038  // masm()->emit(reinterpret_cast<Instr>(addr));
6039 }
6040 
6041 
6042 void CodePatcher::ChangeBranchCondition(Condition cond) {
6043  Instr instr = Assembler::instr_at(masm_.pc_);
6044  DCHECK(Assembler::IsBranch(instr));
6045  uint32_t opcode = Assembler::GetOpcodeField(instr);
6046  // Currently only the 'eq' and 'ne' cond values are supported and the simple
6047  // branch instructions (with opcode being the branch type).
6048  // There are some special cases (see Assembler::IsBranch()) so extending this
6049  // would be tricky.
6050  DCHECK(opcode == BEQ ||
6051  opcode == BNE ||
6052  opcode == BLEZ ||
6053  opcode == BGTZ ||
6054  opcode == BEQL ||
6055  opcode == BNEL ||
6056  opcode == BLEZL ||
6057  opcode == BGTZL);
6058  opcode = (cond == eq) ? BEQ : BNE;
6059  instr = (instr & ~kOpcodeMask) | opcode;
6060  masm_.emit(instr);
6061 }
6062 
6063 
6064 void MacroAssembler::TruncatingDiv(Register result,
6065  Register dividend,
6066  int32_t divisor) {
6067  DCHECK(!dividend.is(result));
6068  DCHECK(!dividend.is(at));
6069  DCHECK(!result.is(at));
6070  base::MagicNumbersForDivision<uint32_t> mag =
6071  base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
6072  li(at, Operand(mag.multiplier));
6073  Mulh(result, dividend, Operand(at));
6074  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
6075  if (divisor > 0 && neg) {
6076  Addu(result, result, Operand(dividend));
6077  }
6078  if (divisor < 0 && !neg && mag.multiplier > 0) {
6079  Subu(result, result, Operand(dividend));
6080  }
6081  if (mag.shift > 0) sra(result, result, mag.shift);
6082  srl(at, dividend, 31);
6083  Addu(result, result, Operand(at));
6084 }
6085 
6086 
6087 } } // namespace v8::internal
6088 
6089 #endif // V8_TARGET_ARCH_MIPS64
#define kDoubleRegZero
#define cp
#define kLithiumScratchDouble
const int kPageSizeBits
Definition: build_config.h:159
MacroAssembler(Isolate *isolate, void *buffer, int size)
static const AbiVariants kMipsAbi
@ kMips64r6
@ kMips64r2
@ kN64
const bool IsMipsSoftFloatABI
#define UNIMPLEMENTED_MIPS()
static const ArchVariants kArchVariant
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi space(in MBytes)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define kNumSafepointSavedRegisters
Definition: frames-arm64.h:28
#define kSafepointSavedRegisters
Definition: frames-arm64.h:27
#define UNREACHABLE()
Definition: logging.h:30
#define CHECK(condition)
Definition: logging.h:36
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
InvokeFlag
@ JUMP_FUNCTION
@ CALL_FUNCTION
AllocationFlags
@ RESULT_CONTAINS_TOP
@ SIZE_IN_WORDS
@ NO_ALLOCATION_FLAGS
@ TAG_OBJECT
#define STATIC_ASSERT(test)
Definition: macros.h:311
unsigned short uint16_t
Definition: unicode.cc:23
signed short int16_t
Definition: unicode.cc:22
int int32_t
Definition: unicode.cc:24
bool IsPowerOfTwo32(uint32_t value)
Definition: bits.h:77
MagicNumbersForDivision< T > SignedDivisionByConstant(T d)
Matcher< Node * > IsBranch(const Matcher< Node * > &value_matcher, const Matcher< Node * > &control_matcher)
static int Push(SpecialRPOStackFrame *stack, int depth, BasicBlock *child, int unvisited)
Definition: scheduler.cc:773
const intptr_t kHeapObjectTagMask
Definition: v8.h:5739
const int kPointerSize
Definition: globals.h:129
const FPURegister f14
const uint32_t kStringEncodingMask
Definition: objects.h:555
const Register r2
@ DONT_DO_SMI_CHECK
Definition: globals.h:640
@ DO_SMI_CHECK
Definition: globals.h:641
const int kImm16Bits
const FPUControlRegister FCSR
@ kSeqStringTag
Definition: objects.h:563
@ kConsStringTag
Definition: objects.h:564
@ kExternalStringTag
Definition: objects.h:565
const FPURegister f31
const RegList kJSCallerSaved
Definition: frames-arm.h:24
const int kSmiShift
bool AreAliased(const CPURegister &reg1, const CPURegister &reg2, const CPURegister &reg3=NoReg, const CPURegister &reg4=NoReg, const CPURegister &reg5=NoReg, const CPURegister &reg6=NoReg, const CPURegister &reg7=NoReg, const CPURegister &reg8=NoReg)
const int kSafepointRegisterStackIndexMap[kNumRegs]
Definition: frames-mips.h:92
TypeImpl< ZoneTypeConfig > Type
@ kDontCheckForInexactConversion
const SwVfpRegister s1
const int kSmiTagSize
Definition: v8.h:5743
const SwVfpRegister s2
const int kDoubleSizeLog2
Definition: globals.h:138
const int kNumSafepointRegisters
Definition: frames-arm.h:67
const int kDoubleSize
Definition: globals.h:127
const FPURegister f2
const uint32_t kNotStringTag
Definition: objects.h:545
const SwVfpRegister s0
const Register fp
DwVfpRegister DoubleRegister
const uint32_t kFCSRUnderflowFlagMask
const Address kZapValue
Definition: globals.h:269
const Register sp
const int kPointerSizeLog2
Definition: globals.h:147
const uint32_t kStringTag
Definition: objects.h:544
@ LAST_NONCALLABLE_SPEC_OBJECT_TYPE
Definition: objects.h:785
@ FIRST_NONCALLABLE_SPEC_OBJECT_TYPE
Definition: objects.h:784
@ FIRST_NONSTRING_TYPE
Definition: objects.h:758
@ LAST_NAME_TYPE
Definition: objects.h:755
@ JS_FUNCTION_TYPE
Definition: objects.h:749
@ FAST_HOLEY_SMI_ELEMENTS
Definition: elements-kind.h:17
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
const uint32_t kOneByteStringTag
Definition: objects.h:557
MemOperand FieldMemOperand(Register object, int offset)
const intptr_t kObjectAlignmentMask
Definition: globals.h:227
const FPURegister f12
const SwVfpRegister s3
const uint32_t kFCSRInvalidOpFlagMask
int NumRegs(RegList reglist)
Definition: frames.cc:1582
static const int kInvalidEnumCacheSentinel
const char * GetBailoutReason(BailoutReason reason)
Condition NegateCondition(Condition cond)
Definition: constants-arm.h:86
const uint32_t kStringRepresentationMask
Definition: objects.h:561
uint32_t RegList
Definition: frames.h:18
const SwVfpRegister s6
byte * Address
Definition: globals.h:101
const uint32_t kFCSROverflowFlagMask
const Register r1
static bool SmiValuesAre32Bits()
Definition: v8.h:5808
const int kImm28Mask
const int kHiMask
const int kHeapObjectTag
Definition: v8.h:5737
const Register no_reg
MemOperand UntagSmiFieldMemOperand(Register object, int offset)
const uint32_t kIsIndirectStringTag
Definition: objects.h:569
int TenToThe(int exponent)
Definition: utils.h:733
kFeedbackVectorOffset flag
Definition: objects-inl.h:5418
Register ToRegister(int num)
const uint32_t kInternalizedTag
Definition: objects.h:551
static const int kNumberDictionaryProbes
Definition: codegen.h:149
const uint32_t kFCSRInexactFlagMask
const intptr_t kSmiTagMask
Definition: v8.h:5744
const uint32_t kIsNotInternalizedMask
Definition: objects.h:549
const int kOpcodeMask
const uint32_t kNaNOrInfinityLowerBoundUpper32
Definition: globals.h:658
const int kLuiShift
const int kSmiTag
Definition: v8.h:5742
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2=no_reg, Register reg3=no_reg, Register reg4=no_reg, Register reg5=no_reg, Register reg6=no_reg)
static const int kNoCodeAgeSequenceLength
const uint32_t kHoleNanLower32
Definition: globals.h:657
const uint32_t kIsNotStringMask
Definition: objects.h:543
bool IsAligned(T value, U alignment)
Definition: utils.h:123
int NumberOfBitsSet(uint32_t x)
Definition: assembler.h:1073
const int kCharSize
Definition: globals.h:122
const uint32_t kFCSRFlagMask
@ kPointersToHereAreAlwaysInteresting
void CopyBytes(uint8_t *target, uint8_t *source)
const intptr_t kDoubleAlignmentMask
Definition: globals.h:235
const uint32_t kIsIndirectStringMask
Definition: objects.h:568
const FPURegister f0
MemOperand UntagSmiMemOperand(Register object, int offset)
PerThreadAssertScopeDebugOnly< DEFERRED_HANDLE_DEREFERENCE_ASSERT, true > AllowDeferredHandleDereference
Definition: assert-scope.h:130
const FPURegister f13
const int kNumRegisters
Definition: constants-arm.h:34
const int kCArgSlotCount
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
@ None
Definition: v8.h:2211
static Handle< Value > Throw(Isolate *isolate, const char *message)
Definition: d8.cc:72
@ NONE
bool is(Register reg) const