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