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_MIPS64
8
9#include "src/base/division-by-constant.h"
10#include "src/bootstrapper.h"
11#include "src/codegen.h"
12#include "src/debug/debug.h"
13#include "src/mips64/macro-assembler-mips64.h"
14#include "src/register-configuration.h"
15#include "src/runtime/runtime.h"
16
17namespace v8 {
18namespace internal {
19
20// Floating point constants.
21const uint64_t kDoubleSignMask = Double::kSignMask;
22const uint32_t kDoubleExponentShift = HeapNumber::kMantissaBits;
23const uint32_t kDoubleNaNShift = kDoubleExponentShift - 1;
24const uint64_t kDoubleNaNMask = Double::kExponentMask | (1L << kDoubleNaNShift);
25
26const uint32_t kSingleSignMask = kBinary32SignMask;
27const uint32_t kSingleExponentMask = kBinary32ExponentMask;
28const uint32_t kSingleExponentShift = kBinary32ExponentShift;
29const uint32_t kSingleNaNShift = kSingleExponentShift - 1;
30const uint32_t kSingleNaNMask = kSingleExponentMask | (1 << kSingleNaNShift);
31
32MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
33                               CodeObjectRequired create_code_object)
34    : Assembler(arg_isolate, buffer, size),
35      generating_stub_(false),
36      has_frame_(false),
37      has_double_zero_reg_set_(false) {
38  if (create_code_object == CodeObjectRequired::kYes) {
39    code_object_ =
40        Handle<Object>::New(isolate()->heap()->undefined_value(), isolate());
41  }
42}
43
44void MacroAssembler::Load(Register dst,
45                          const MemOperand& src,
46                          Representation r) {
47  DCHECK(!r.IsDouble());
48  if (r.IsInteger8()) {
49    lb(dst, src);
50  } else if (r.IsUInteger8()) {
51    lbu(dst, src);
52  } else if (r.IsInteger16()) {
53    lh(dst, src);
54  } else if (r.IsUInteger16()) {
55    lhu(dst, src);
56  } else if (r.IsInteger32()) {
57    lw(dst, src);
58  } else {
59    ld(dst, src);
60  }
61}
62
63
64void MacroAssembler::Store(Register src,
65                           const MemOperand& dst,
66                           Representation r) {
67  DCHECK(!r.IsDouble());
68  if (r.IsInteger8() || r.IsUInteger8()) {
69    sb(src, dst);
70  } else if (r.IsInteger16() || r.IsUInteger16()) {
71    sh(src, dst);
72  } else if (r.IsInteger32()) {
73    sw(src, dst);
74  } else {
75    if (r.IsHeapObject()) {
76      AssertNotSmi(src);
77    } else if (r.IsSmi()) {
78      AssertSmi(src);
79    }
80    sd(src, dst);
81  }
82}
83
84
85void MacroAssembler::LoadRoot(Register destination,
86                              Heap::RootListIndex index) {
87  ld(destination, MemOperand(s6, index << kPointerSizeLog2));
88}
89
90
91void MacroAssembler::LoadRoot(Register destination,
92                              Heap::RootListIndex index,
93                              Condition cond,
94                              Register src1, const Operand& src2) {
95  Branch(2, NegateCondition(cond), src1, src2);
96  ld(destination, MemOperand(s6, index << kPointerSizeLog2));
97}
98
99
100void MacroAssembler::StoreRoot(Register source,
101                               Heap::RootListIndex index) {
102  DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
103  sd(source, MemOperand(s6, index << kPointerSizeLog2));
104}
105
106
107void MacroAssembler::StoreRoot(Register source,
108                               Heap::RootListIndex index,
109                               Condition cond,
110                               Register src1, const Operand& src2) {
111  DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
112  Branch(2, NegateCondition(cond), src1, src2);
113  sd(source, MemOperand(s6, index << kPointerSizeLog2));
114}
115
116void MacroAssembler::PushCommonFrame(Register marker_reg) {
117  if (marker_reg.is_valid()) {
118    Push(ra, fp, marker_reg);
119    Daddu(fp, sp, Operand(kPointerSize));
120  } else {
121    Push(ra, fp);
122    mov(fp, sp);
123  }
124}
125
126void MacroAssembler::PopCommonFrame(Register marker_reg) {
127  if (marker_reg.is_valid()) {
128    Pop(ra, fp, marker_reg);
129  } else {
130    Pop(ra, fp);
131  }
132}
133
134void MacroAssembler::PushStandardFrame(Register function_reg) {
135  int offset = -StandardFrameConstants::kContextOffset;
136  if (function_reg.is_valid()) {
137    Push(ra, fp, cp, function_reg);
138    offset += kPointerSize;
139  } else {
140    Push(ra, fp, cp);
141  }
142  Daddu(fp, sp, Operand(offset));
143}
144
145// Push and pop all registers that can hold pointers.
146void MacroAssembler::PushSafepointRegisters() {
147  // Safepoints expect a block of kNumSafepointRegisters values on the
148  // stack, so adjust the stack for unsaved registers.
149  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
150  DCHECK(num_unsaved >= 0);
151  if (num_unsaved > 0) {
152    Dsubu(sp, sp, Operand(num_unsaved * kPointerSize));
153  }
154  MultiPush(kSafepointSavedRegisters);
155}
156
157
158void MacroAssembler::PopSafepointRegisters() {
159  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
160  MultiPop(kSafepointSavedRegisters);
161  if (num_unsaved > 0) {
162    Daddu(sp, sp, Operand(num_unsaved * kPointerSize));
163  }
164}
165
166
167void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
168  sd(src, SafepointRegisterSlot(dst));
169}
170
171
172void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
173  ld(dst, SafepointRegisterSlot(src));
174}
175
176
177int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
178  // The registers are pushed starting with the highest encoding,
179  // which means that lowest encodings are closest to the stack pointer.
180  return kSafepointRegisterStackIndexMap[reg_code];
181}
182
183
184MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
185  return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
186}
187
188
189MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
190  UNIMPLEMENTED_MIPS();
191  // General purpose registers are pushed last on the stack.
192  int doubles_size = DoubleRegister::kMaxNumRegisters * kDoubleSize;
193  int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
194  return MemOperand(sp, doubles_size + register_offset);
195}
196
197
198void MacroAssembler::InNewSpace(Register object,
199                                Register scratch,
200                                Condition cc,
201                                Label* branch) {
202  DCHECK(cc == eq || cc == ne);
203  const int mask =
204      1 << MemoryChunk::IN_FROM_SPACE | 1 << MemoryChunk::IN_TO_SPACE;
205  CheckPageFlag(object, scratch, mask, cc, branch);
206}
207
208
209// Clobbers object, dst, value, and ra, if (ra_status == kRAHasBeenSaved)
210// The register 'object' contains a heap object pointer.  The heap object
211// tag is shifted away.
212void MacroAssembler::RecordWriteField(
213    Register object,
214    int offset,
215    Register value,
216    Register dst,
217    RAStatus ra_status,
218    SaveFPRegsMode save_fp,
219    RememberedSetAction remembered_set_action,
220    SmiCheck smi_check,
221    PointersToHereCheck pointers_to_here_check_for_value) {
222  DCHECK(!AreAliased(value, dst, t8, object));
223  // First, check if a write barrier is even needed. The tests below
224  // catch stores of Smis.
225  Label done;
226
227  // Skip barrier if writing a smi.
228  if (smi_check == INLINE_SMI_CHECK) {
229    JumpIfSmi(value, &done);
230  }
231
232  // Although the object register is tagged, the offset is relative to the start
233  // of the object, so so offset must be a multiple of kPointerSize.
234  DCHECK(IsAligned(offset, kPointerSize));
235
236  Daddu(dst, object, Operand(offset - kHeapObjectTag));
237  if (emit_debug_code()) {
238    Label ok;
239    And(t8, dst, Operand((1 << kPointerSizeLog2) - 1));
240    Branch(&ok, eq, t8, Operand(zero_reg));
241    stop("Unaligned cell in write barrier");
242    bind(&ok);
243  }
244
245  RecordWrite(object,
246              dst,
247              value,
248              ra_status,
249              save_fp,
250              remembered_set_action,
251              OMIT_SMI_CHECK,
252              pointers_to_here_check_for_value);
253
254  bind(&done);
255
256  // Clobber clobbered input registers when running with the debug-code flag
257  // turned on to provoke errors.
258  if (emit_debug_code()) {
259    li(value, Operand(bit_cast<int64_t>(kZapValue + 4)));
260    li(dst, Operand(bit_cast<int64_t>(kZapValue + 8)));
261  }
262}
263
264
265// Clobbers object, dst, map, and ra, if (ra_status == kRAHasBeenSaved)
266void MacroAssembler::RecordWriteForMap(Register object,
267                                       Register map,
268                                       Register dst,
269                                       RAStatus ra_status,
270                                       SaveFPRegsMode fp_mode) {
271  if (emit_debug_code()) {
272    DCHECK(!dst.is(at));
273    ld(dst, FieldMemOperand(map, HeapObject::kMapOffset));
274    Check(eq,
275          kWrongAddressOrValuePassedToRecordWrite,
276          dst,
277          Operand(isolate()->factory()->meta_map()));
278  }
279
280  if (!FLAG_incremental_marking) {
281    return;
282  }
283
284  if (emit_debug_code()) {
285    ld(at, FieldMemOperand(object, HeapObject::kMapOffset));
286    Check(eq,
287          kWrongAddressOrValuePassedToRecordWrite,
288          map,
289          Operand(at));
290  }
291
292  Label done;
293
294  // A single check of the map's pages interesting flag suffices, since it is
295  // only set during incremental collection, and then it's also guaranteed that
296  // the from object's page's interesting flag is also set.  This optimization
297  // relies on the fact that maps can never be in new space.
298  CheckPageFlag(map,
299                map,  // Used as scratch.
300                MemoryChunk::kPointersToHereAreInterestingMask,
301                eq,
302                &done);
303
304  Daddu(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag));
305  if (emit_debug_code()) {
306    Label ok;
307    And(at, dst, Operand((1 << kPointerSizeLog2) - 1));
308    Branch(&ok, eq, at, Operand(zero_reg));
309    stop("Unaligned cell in write barrier");
310    bind(&ok);
311  }
312
313  // Record the actual write.
314  if (ra_status == kRAHasNotBeenSaved) {
315    push(ra);
316  }
317  RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
318                       fp_mode);
319  CallStub(&stub);
320  if (ra_status == kRAHasNotBeenSaved) {
321    pop(ra);
322  }
323
324  bind(&done);
325
326  // Count number of write barriers in generated code.
327  isolate()->counters()->write_barriers_static()->Increment();
328  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, at, dst);
329
330  // Clobber clobbered registers when running with the debug-code flag
331  // turned on to provoke errors.
332  if (emit_debug_code()) {
333    li(dst, Operand(bit_cast<int64_t>(kZapValue + 12)));
334    li(map, Operand(bit_cast<int64_t>(kZapValue + 16)));
335  }
336}
337
338
339// Clobbers object, address, value, and ra, if (ra_status == kRAHasBeenSaved)
340// The register 'object' contains a heap object pointer.  The heap object
341// tag is shifted away.
342void MacroAssembler::RecordWrite(
343    Register object,
344    Register address,
345    Register value,
346    RAStatus ra_status,
347    SaveFPRegsMode fp_mode,
348    RememberedSetAction remembered_set_action,
349    SmiCheck smi_check,
350    PointersToHereCheck pointers_to_here_check_for_value) {
351  DCHECK(!AreAliased(object, address, value, t8));
352  DCHECK(!AreAliased(object, address, value, t9));
353
354  if (emit_debug_code()) {
355    ld(at, MemOperand(address));
356    Assert(
357        eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value));
358  }
359
360  if (remembered_set_action == OMIT_REMEMBERED_SET &&
361      !FLAG_incremental_marking) {
362    return;
363  }
364
365  // First, check if a write barrier is even needed. The tests below
366  // catch stores of smis and stores into the young generation.
367  Label done;
368
369  if (smi_check == INLINE_SMI_CHECK) {
370    DCHECK_EQ(0, kSmiTag);
371    JumpIfSmi(value, &done);
372  }
373
374  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
375    CheckPageFlag(value,
376                  value,  // Used as scratch.
377                  MemoryChunk::kPointersToHereAreInterestingMask,
378                  eq,
379                  &done);
380  }
381  CheckPageFlag(object,
382                value,  // Used as scratch.
383                MemoryChunk::kPointersFromHereAreInterestingMask,
384                eq,
385                &done);
386
387  // Record the actual write.
388  if (ra_status == kRAHasNotBeenSaved) {
389    push(ra);
390  }
391  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
392                       fp_mode);
393  CallStub(&stub);
394  if (ra_status == kRAHasNotBeenSaved) {
395    pop(ra);
396  }
397
398  bind(&done);
399
400  // Count number of write barriers in generated code.
401  isolate()->counters()->write_barriers_static()->Increment();
402  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, at,
403                   value);
404
405  // Clobber clobbered registers when running with the debug-code flag
406  // turned on to provoke errors.
407  if (emit_debug_code()) {
408    li(address, Operand(bit_cast<int64_t>(kZapValue + 12)));
409    li(value, Operand(bit_cast<int64_t>(kZapValue + 16)));
410  }
411}
412
413void MacroAssembler::RecordWriteCodeEntryField(Register js_function,
414                                               Register code_entry,
415                                               Register scratch) {
416  const int offset = JSFunction::kCodeEntryOffset;
417
418  // Since a code entry (value) is always in old space, we don't need to update
419  // remembered set. If incremental marking is off, there is nothing for us to
420  // do.
421  if (!FLAG_incremental_marking) return;
422
423  DCHECK(js_function.is(a1));
424  DCHECK(code_entry.is(a4));
425  DCHECK(scratch.is(a5));
426  AssertNotSmi(js_function);
427
428  if (emit_debug_code()) {
429    Daddu(scratch, js_function, Operand(offset - kHeapObjectTag));
430    ld(at, MemOperand(scratch));
431    Assert(eq, kWrongAddressOrValuePassedToRecordWrite, at,
432           Operand(code_entry));
433  }
434
435  // First, check if a write barrier is even needed. The tests below
436  // catch stores of Smis and stores into young gen.
437  Label done;
438
439  CheckPageFlag(code_entry, scratch,
440                MemoryChunk::kPointersToHereAreInterestingMask, eq, &done);
441  CheckPageFlag(js_function, scratch,
442                MemoryChunk::kPointersFromHereAreInterestingMask, eq, &done);
443
444  const Register dst = scratch;
445  Daddu(dst, js_function, Operand(offset - kHeapObjectTag));
446
447  // Save caller-saved registers. js_function and code_entry are in the
448  // caller-saved register list.
449  DCHECK(kJSCallerSaved & js_function.bit());
450  DCHECK(kJSCallerSaved & code_entry.bit());
451  MultiPush(kJSCallerSaved | ra.bit());
452
453  int argument_count = 3;
454
455  PrepareCallCFunction(argument_count, code_entry);
456
457  Move(a0, js_function);
458  Move(a1, dst);
459  li(a2, Operand(ExternalReference::isolate_address(isolate())));
460
461  {
462    AllowExternalCallThatCantCauseGC scope(this);
463    CallCFunction(
464        ExternalReference::incremental_marking_record_write_code_entry_function(
465            isolate()),
466        argument_count);
467  }
468
469  // Restore caller-saved registers.
470  MultiPop(kJSCallerSaved | ra.bit());
471
472  bind(&done);
473}
474
475void MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
476                                         Register address,
477                                         Register scratch,
478                                         SaveFPRegsMode fp_mode,
479                                         RememberedSetFinalAction and_then) {
480  Label done;
481  if (emit_debug_code()) {
482    Label ok;
483    JumpIfNotInNewSpace(object, scratch, &ok);
484    stop("Remembered set pointer is in new space");
485    bind(&ok);
486  }
487  // Load store buffer top.
488  ExternalReference store_buffer =
489      ExternalReference::store_buffer_top(isolate());
490  li(t8, Operand(store_buffer));
491  ld(scratch, MemOperand(t8));
492  // Store pointer to buffer and increment buffer top.
493  sd(address, MemOperand(scratch));
494  Daddu(scratch, scratch, kPointerSize);
495  // Write back new top of buffer.
496  sd(scratch, MemOperand(t8));
497  // Call stub on end of buffer.
498  // Check for end of buffer.
499  And(t8, scratch, Operand(StoreBuffer::kStoreBufferMask));
500  DCHECK(!scratch.is(t8));
501  if (and_then == kFallThroughAtEnd) {
502    Branch(&done, ne, t8, Operand(zero_reg));
503  } else {
504    DCHECK(and_then == kReturnAtEnd);
505    Ret(ne, t8, Operand(zero_reg));
506  }
507  push(ra);
508  StoreBufferOverflowStub store_buffer_overflow(isolate(), fp_mode);
509  CallStub(&store_buffer_overflow);
510  pop(ra);
511  bind(&done);
512  if (and_then == kReturnAtEnd) {
513    Ret();
514  }
515}
516
517
518// -----------------------------------------------------------------------------
519// Allocation support.
520
521
522void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
523                                            Register scratch,
524                                            Label* miss) {
525  Label same_contexts;
526  Register temporary = t8;
527
528  DCHECK(!holder_reg.is(scratch));
529  DCHECK(!holder_reg.is(at));
530  DCHECK(!scratch.is(at));
531
532  // Load current lexical context from the active StandardFrame, which
533  // may require crawling past STUB frames.
534  Label load_context;
535  Label has_context;
536  mov(at, fp);
537  bind(&load_context);
538  ld(scratch, MemOperand(at, CommonFrameConstants::kContextOrFrameTypeOffset));
539  // Passing temporary register, otherwise JumpIfNotSmi modifies register at.
540  JumpIfNotSmi(scratch, &has_context, temporary);
541  ld(at, MemOperand(at, CommonFrameConstants::kCallerFPOffset));
542  Branch(&load_context);
543  bind(&has_context);
544
545  // In debug mode, make sure the lexical context is set.
546#ifdef DEBUG
547  Check(ne, kWeShouldNotHaveAnEmptyLexicalContext,
548      scratch, Operand(zero_reg));
549#endif
550
551  // Load the native context of the current context.
552  ld(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX));
553
554  // Check the context is a native context.
555  if (emit_debug_code()) {
556    push(holder_reg);  // Temporarily save holder on the stack.
557    // Read the first word and compare to the native_context_map.
558    ld(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
559    LoadRoot(at, Heap::kNativeContextMapRootIndex);
560    Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
561          holder_reg, Operand(at));
562    pop(holder_reg);  // Restore holder.
563  }
564
565  // Check if both contexts are the same.
566  ld(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
567  Branch(&same_contexts, eq, scratch, Operand(at));
568
569  // Check the context is a native context.
570  if (emit_debug_code()) {
571    push(holder_reg);  // Temporarily save holder on the stack.
572    mov(holder_reg, at);  // Move at to its holding place.
573    LoadRoot(at, Heap::kNullValueRootIndex);
574    Check(ne, kJSGlobalProxyContextShouldNotBeNull,
575          holder_reg, Operand(at));
576
577    ld(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
578    LoadRoot(at, Heap::kNativeContextMapRootIndex);
579    Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
580          holder_reg, Operand(at));
581    // Restore at is not needed. at is reloaded below.
582    pop(holder_reg);  // Restore holder.
583    // Restore at to holder's context.
584    ld(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
585  }
586
587  // Check that the security token in the calling global object is
588  // compatible with the security token in the receiving global
589  // object.
590  int token_offset = Context::kHeaderSize +
591                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
592
593  ld(scratch, FieldMemOperand(scratch, token_offset));
594  ld(at, FieldMemOperand(at, token_offset));
595  Branch(miss, ne, scratch, Operand(at));
596
597  bind(&same_contexts);
598}
599
600
601// Compute the hash code from the untagged key.  This must be kept in sync with
602// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
603// code-stub-hydrogen.cc
604void MacroAssembler::GetNumberHash(Register reg0, Register scratch) {
605  // First of all we assign the hash seed to scratch.
606  LoadRoot(scratch, Heap::kHashSeedRootIndex);
607  SmiUntag(scratch);
608
609  // Xor original key with a seed.
610  xor_(reg0, reg0, scratch);
611
612  // Compute the hash code from the untagged key.  This must be kept in sync
613  // with ComputeIntegerHash in utils.h.
614  //
615  // hash = ~hash + (hash << 15);
616  // The algorithm uses 32-bit integer values.
617  nor(scratch, reg0, zero_reg);
618  Lsa(reg0, scratch, reg0, 15);
619
620  // hash = hash ^ (hash >> 12);
621  srl(at, reg0, 12);
622  xor_(reg0, reg0, at);
623
624  // hash = hash + (hash << 2);
625  Lsa(reg0, reg0, reg0, 2);
626
627  // hash = hash ^ (hash >> 4);
628  srl(at, reg0, 4);
629  xor_(reg0, reg0, at);
630
631  // hash = hash * 2057;
632  sll(scratch, reg0, 11);
633  Lsa(reg0, reg0, reg0, 3);
634  addu(reg0, reg0, scratch);
635
636  // hash = hash ^ (hash >> 16);
637  srl(at, reg0, 16);
638  xor_(reg0, reg0, at);
639  And(reg0, reg0, Operand(0x3fffffff));
640}
641
642
643void MacroAssembler::LoadFromNumberDictionary(Label* miss,
644                                              Register elements,
645                                              Register key,
646                                              Register result,
647                                              Register reg0,
648                                              Register reg1,
649                                              Register reg2) {
650  // Register use:
651  //
652  // elements - holds the slow-case elements of the receiver on entry.
653  //            Unchanged unless 'result' is the same register.
654  //
655  // key      - holds the smi key on entry.
656  //            Unchanged unless 'result' is the same register.
657  //
658  //
659  // result   - holds the result on exit if the load succeeded.
660  //            Allowed to be the same as 'key' or 'result'.
661  //            Unchanged on bailout so 'key' or 'result' can be used
662  //            in further computation.
663  //
664  // Scratch registers:
665  //
666  // reg0 - holds the untagged key on entry and holds the hash once computed.
667  //
668  // reg1 - Used to hold the capacity mask of the dictionary.
669  //
670  // reg2 - Used for the index into the dictionary.
671  // at   - Temporary (avoid MacroAssembler instructions also using 'at').
672  Label done;
673
674  GetNumberHash(reg0, reg1);
675
676  // Compute the capacity mask.
677  ld(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset));
678  SmiUntag(reg1, reg1);
679  Dsubu(reg1, reg1, Operand(1));
680
681  // Generate an unrolled loop that performs a few probes before giving up.
682  for (int i = 0; i < kNumberDictionaryProbes; i++) {
683    // Use reg2 for index calculations and keep the hash intact in reg0.
684    mov(reg2, reg0);
685    // Compute the masked index: (hash + i + i * i) & mask.
686    if (i > 0) {
687      Daddu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i)));
688    }
689    and_(reg2, reg2, reg1);
690
691    // Scale the index by multiplying by the element size.
692    DCHECK(SeededNumberDictionary::kEntrySize == 3);
693    Dlsa(reg2, reg2, reg2, 1);  // reg2 = reg2 * 3.
694
695    // Check if the key is identical to the name.
696    Dlsa(reg2, elements, reg2, kPointerSizeLog2);
697
698    ld(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset));
699    if (i != kNumberDictionaryProbes - 1) {
700      Branch(&done, eq, key, Operand(at));
701    } else {
702      Branch(miss, ne, key, Operand(at));
703    }
704  }
705
706  bind(&done);
707  // Check that the value is a field property.
708  // reg2: elements + (index * kPointerSize).
709  const int kDetailsOffset =
710      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
711  ld(reg1, FieldMemOperand(reg2, kDetailsOffset));
712  DCHECK_EQ(DATA, 0);
713  And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
714  Branch(miss, ne, at, Operand(zero_reg));
715
716  // Get the value at the masked, scaled index and return.
717  const int kValueOffset =
718      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
719  ld(result, FieldMemOperand(reg2, kValueOffset));
720}
721
722
723// ---------------------------------------------------------------------------
724// Instruction macros.
725
726void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) {
727  if (rt.is_reg()) {
728    addu(rd, rs, rt.rm());
729  } else {
730    if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
731      addiu(rd, rs, static_cast<int32_t>(rt.imm64_));
732    } else {
733      // li handles the relocation.
734      DCHECK(!rs.is(at));
735      li(at, rt);
736      addu(rd, rs, at);
737    }
738  }
739}
740
741
742void MacroAssembler::Daddu(Register rd, Register rs, const Operand& rt) {
743  if (rt.is_reg()) {
744    daddu(rd, rs, rt.rm());
745  } else {
746    if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
747      daddiu(rd, rs, static_cast<int32_t>(rt.imm64_));
748    } else {
749      // li handles the relocation.
750      DCHECK(!rs.is(at));
751      li(at, rt);
752      daddu(rd, rs, at);
753    }
754  }
755}
756
757
758void MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) {
759  if (rt.is_reg()) {
760    subu(rd, rs, rt.rm());
761  } else {
762    if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
763      addiu(rd, rs, static_cast<int32_t>(
764                        -rt.imm64_));  // No subiu instr, use addiu(x, y, -imm).
765    } else {
766      // li handles the relocation.
767      DCHECK(!rs.is(at));
768      li(at, rt);
769      subu(rd, rs, at);
770    }
771  }
772}
773
774
775void MacroAssembler::Dsubu(Register rd, Register rs, const Operand& rt) {
776  if (rt.is_reg()) {
777    dsubu(rd, rs, rt.rm());
778  } else {
779    if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
780      daddiu(rd, rs,
781             static_cast<int32_t>(
782                 -rt.imm64_));  // No subiu instr, use addiu(x, y, -imm).
783    } else {
784      // li handles the relocation.
785      DCHECK(!rs.is(at));
786      li(at, rt);
787      dsubu(rd, rs, at);
788    }
789  }
790}
791
792
793void MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) {
794  if (rt.is_reg()) {
795    mul(rd, rs, rt.rm());
796  } else {
797    // li handles the relocation.
798    DCHECK(!rs.is(at));
799    li(at, rt);
800    mul(rd, rs, at);
801  }
802}
803
804
805void MacroAssembler::Mulh(Register rd, Register rs, const Operand& rt) {
806  if (rt.is_reg()) {
807    if (kArchVariant != kMips64r6) {
808      mult(rs, rt.rm());
809      mfhi(rd);
810    } else {
811      muh(rd, rs, rt.rm());
812    }
813  } else {
814    // li handles the relocation.
815    DCHECK(!rs.is(at));
816    li(at, rt);
817    if (kArchVariant != kMips64r6) {
818      mult(rs, at);
819      mfhi(rd);
820    } else {
821      muh(rd, rs, at);
822    }
823  }
824}
825
826
827void MacroAssembler::Mulhu(Register rd, Register rs, const Operand& rt) {
828  if (rt.is_reg()) {
829    if (kArchVariant != kMips64r6) {
830      multu(rs, rt.rm());
831      mfhi(rd);
832    } else {
833      muhu(rd, rs, rt.rm());
834    }
835  } else {
836    // li handles the relocation.
837    DCHECK(!rs.is(at));
838    li(at, rt);
839    if (kArchVariant != kMips64r6) {
840      multu(rs, at);
841      mfhi(rd);
842    } else {
843      muhu(rd, rs, at);
844    }
845  }
846}
847
848
849void MacroAssembler::Dmul(Register rd, Register rs, const Operand& rt) {
850  if (rt.is_reg()) {
851    if (kArchVariant == kMips64r6) {
852      dmul(rd, rs, rt.rm());
853    } else {
854      dmult(rs, rt.rm());
855      mflo(rd);
856    }
857  } else {
858    // li handles the relocation.
859    DCHECK(!rs.is(at));
860    li(at, rt);
861    if (kArchVariant == kMips64r6) {
862      dmul(rd, rs, at);
863    } else {
864      dmult(rs, at);
865      mflo(rd);
866    }
867  }
868}
869
870
871void MacroAssembler::Dmulh(Register rd, Register rs, const Operand& rt) {
872  if (rt.is_reg()) {
873    if (kArchVariant == kMips64r6) {
874      dmuh(rd, rs, rt.rm());
875    } else {
876      dmult(rs, rt.rm());
877      mfhi(rd);
878    }
879  } else {
880    // li handles the relocation.
881    DCHECK(!rs.is(at));
882    li(at, rt);
883    if (kArchVariant == kMips64r6) {
884      dmuh(rd, rs, at);
885    } else {
886      dmult(rs, at);
887      mfhi(rd);
888    }
889  }
890}
891
892
893void MacroAssembler::Mult(Register rs, const Operand& rt) {
894  if (rt.is_reg()) {
895    mult(rs, rt.rm());
896  } else {
897    // li handles the relocation.
898    DCHECK(!rs.is(at));
899    li(at, rt);
900    mult(rs, at);
901  }
902}
903
904
905void MacroAssembler::Dmult(Register rs, const Operand& rt) {
906  if (rt.is_reg()) {
907    dmult(rs, rt.rm());
908  } else {
909    // li handles the relocation.
910    DCHECK(!rs.is(at));
911    li(at, rt);
912    dmult(rs, at);
913  }
914}
915
916
917void MacroAssembler::Multu(Register rs, const Operand& rt) {
918  if (rt.is_reg()) {
919    multu(rs, rt.rm());
920  } else {
921    // li handles the relocation.
922    DCHECK(!rs.is(at));
923    li(at, rt);
924    multu(rs, at);
925  }
926}
927
928
929void MacroAssembler::Dmultu(Register rs, const Operand& rt) {
930  if (rt.is_reg()) {
931    dmultu(rs, rt.rm());
932  } else {
933    // li handles the relocation.
934    DCHECK(!rs.is(at));
935    li(at, rt);
936    dmultu(rs, at);
937  }
938}
939
940
941void MacroAssembler::Div(Register rs, const Operand& rt) {
942  if (rt.is_reg()) {
943    div(rs, rt.rm());
944  } else {
945    // li handles the relocation.
946    DCHECK(!rs.is(at));
947    li(at, rt);
948    div(rs, at);
949  }
950}
951
952
953void MacroAssembler::Div(Register res, Register rs, const Operand& rt) {
954  if (rt.is_reg()) {
955    if (kArchVariant != kMips64r6) {
956      div(rs, rt.rm());
957      mflo(res);
958    } else {
959      div(res, rs, rt.rm());
960    }
961  } else {
962    // li handles the relocation.
963    DCHECK(!rs.is(at));
964    li(at, rt);
965    if (kArchVariant != kMips64r6) {
966      div(rs, at);
967      mflo(res);
968    } else {
969      div(res, rs, at);
970    }
971  }
972}
973
974
975void MacroAssembler::Mod(Register rd, Register rs, const Operand& rt) {
976  if (rt.is_reg()) {
977    if (kArchVariant != kMips64r6) {
978      div(rs, rt.rm());
979      mfhi(rd);
980    } else {
981      mod(rd, rs, rt.rm());
982    }
983  } else {
984    // li handles the relocation.
985    DCHECK(!rs.is(at));
986    li(at, rt);
987    if (kArchVariant != kMips64r6) {
988      div(rs, at);
989      mfhi(rd);
990    } else {
991      mod(rd, rs, at);
992    }
993  }
994}
995
996
997void MacroAssembler::Modu(Register rd, Register rs, const Operand& rt) {
998  if (rt.is_reg()) {
999    if (kArchVariant != kMips64r6) {
1000      divu(rs, rt.rm());
1001      mfhi(rd);
1002    } else {
1003      modu(rd, rs, rt.rm());
1004    }
1005  } else {
1006    // li handles the relocation.
1007    DCHECK(!rs.is(at));
1008    li(at, rt);
1009    if (kArchVariant != kMips64r6) {
1010      divu(rs, at);
1011      mfhi(rd);
1012    } else {
1013      modu(rd, rs, at);
1014    }
1015  }
1016}
1017
1018
1019void MacroAssembler::Ddiv(Register rs, const Operand& rt) {
1020  if (rt.is_reg()) {
1021    ddiv(rs, rt.rm());
1022  } else {
1023    // li handles the relocation.
1024    DCHECK(!rs.is(at));
1025    li(at, rt);
1026    ddiv(rs, at);
1027  }
1028}
1029
1030
1031void MacroAssembler::Ddiv(Register rd, Register rs, const Operand& rt) {
1032  if (kArchVariant != kMips64r6) {
1033    if (rt.is_reg()) {
1034      ddiv(rs, rt.rm());
1035      mflo(rd);
1036    } else {
1037      // li handles the relocation.
1038      DCHECK(!rs.is(at));
1039      li(at, rt);
1040      ddiv(rs, at);
1041      mflo(rd);
1042    }
1043  } else {
1044    if (rt.is_reg()) {
1045      ddiv(rd, rs, rt.rm());
1046    } else {
1047      // li handles the relocation.
1048      DCHECK(!rs.is(at));
1049      li(at, rt);
1050      ddiv(rd, rs, at);
1051    }
1052  }
1053}
1054
1055
1056void MacroAssembler::Divu(Register rs, const Operand& rt) {
1057  if (rt.is_reg()) {
1058    divu(rs, rt.rm());
1059  } else {
1060    // li handles the relocation.
1061    DCHECK(!rs.is(at));
1062    li(at, rt);
1063    divu(rs, at);
1064  }
1065}
1066
1067
1068void MacroAssembler::Divu(Register res, Register rs, const Operand& rt) {
1069  if (rt.is_reg()) {
1070    if (kArchVariant != kMips64r6) {
1071      divu(rs, rt.rm());
1072      mflo(res);
1073    } else {
1074      divu(res, rs, rt.rm());
1075    }
1076  } else {
1077    // li handles the relocation.
1078    DCHECK(!rs.is(at));
1079    li(at, rt);
1080    if (kArchVariant != kMips64r6) {
1081      divu(rs, at);
1082      mflo(res);
1083    } else {
1084      divu(res, rs, at);
1085    }
1086  }
1087}
1088
1089
1090void MacroAssembler::Ddivu(Register rs, const Operand& rt) {
1091  if (rt.is_reg()) {
1092    ddivu(rs, rt.rm());
1093  } else {
1094    // li handles the relocation.
1095    DCHECK(!rs.is(at));
1096    li(at, rt);
1097    ddivu(rs, at);
1098  }
1099}
1100
1101
1102void MacroAssembler::Ddivu(Register res, Register rs, const Operand& rt) {
1103  if (rt.is_reg()) {
1104    if (kArchVariant != kMips64r6) {
1105      ddivu(rs, rt.rm());
1106      mflo(res);
1107    } else {
1108      ddivu(res, rs, rt.rm());
1109    }
1110  } else {
1111    // li handles the relocation.
1112    DCHECK(!rs.is(at));
1113    li(at, rt);
1114    if (kArchVariant != kMips64r6) {
1115      ddivu(rs, at);
1116      mflo(res);
1117    } else {
1118      ddivu(res, rs, at);
1119    }
1120  }
1121}
1122
1123
1124void MacroAssembler::Dmod(Register rd, Register rs, const Operand& rt) {
1125  if (kArchVariant != kMips64r6) {
1126    if (rt.is_reg()) {
1127      ddiv(rs, rt.rm());
1128      mfhi(rd);
1129    } else {
1130      // li handles the relocation.
1131      DCHECK(!rs.is(at));
1132      li(at, rt);
1133      ddiv(rs, at);
1134      mfhi(rd);
1135    }
1136  } else {
1137    if (rt.is_reg()) {
1138      dmod(rd, rs, rt.rm());
1139    } else {
1140      // li handles the relocation.
1141      DCHECK(!rs.is(at));
1142      li(at, rt);
1143      dmod(rd, rs, at);
1144    }
1145  }
1146}
1147
1148
1149void MacroAssembler::Dmodu(Register rd, Register rs, const Operand& rt) {
1150  if (kArchVariant != kMips64r6) {
1151    if (rt.is_reg()) {
1152      ddivu(rs, rt.rm());
1153      mfhi(rd);
1154    } else {
1155      // li handles the relocation.
1156      DCHECK(!rs.is(at));
1157      li(at, rt);
1158      ddivu(rs, at);
1159      mfhi(rd);
1160    }
1161  } else {
1162    if (rt.is_reg()) {
1163      dmodu(rd, rs, rt.rm());
1164    } else {
1165      // li handles the relocation.
1166      DCHECK(!rs.is(at));
1167      li(at, rt);
1168      dmodu(rd, rs, at);
1169    }
1170  }
1171}
1172
1173
1174void MacroAssembler::And(Register rd, Register rs, const Operand& rt) {
1175  if (rt.is_reg()) {
1176    and_(rd, rs, rt.rm());
1177  } else {
1178    if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
1179      andi(rd, rs, static_cast<int32_t>(rt.imm64_));
1180    } else {
1181      // li handles the relocation.
1182      DCHECK(!rs.is(at));
1183      li(at, rt);
1184      and_(rd, rs, at);
1185    }
1186  }
1187}
1188
1189
1190void MacroAssembler::Or(Register rd, Register rs, const Operand& rt) {
1191  if (rt.is_reg()) {
1192    or_(rd, rs, rt.rm());
1193  } else {
1194    if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
1195      ori(rd, rs, static_cast<int32_t>(rt.imm64_));
1196    } else {
1197      // li handles the relocation.
1198      DCHECK(!rs.is(at));
1199      li(at, rt);
1200      or_(rd, rs, at);
1201    }
1202  }
1203}
1204
1205
1206void MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) {
1207  if (rt.is_reg()) {
1208    xor_(rd, rs, rt.rm());
1209  } else {
1210    if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
1211      xori(rd, rs, static_cast<int32_t>(rt.imm64_));
1212    } else {
1213      // li handles the relocation.
1214      DCHECK(!rs.is(at));
1215      li(at, rt);
1216      xor_(rd, rs, at);
1217    }
1218  }
1219}
1220
1221
1222void MacroAssembler::Nor(Register rd, Register rs, const Operand& rt) {
1223  if (rt.is_reg()) {
1224    nor(rd, rs, rt.rm());
1225  } else {
1226    // li handles the relocation.
1227    DCHECK(!rs.is(at));
1228    li(at, rt);
1229    nor(rd, rs, at);
1230  }
1231}
1232
1233
1234void MacroAssembler::Neg(Register rs, const Operand& rt) {
1235  DCHECK(rt.is_reg());
1236  DCHECK(!at.is(rs));
1237  DCHECK(!at.is(rt.rm()));
1238  li(at, -1);
1239  xor_(rs, rt.rm(), at);
1240}
1241
1242
1243void MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) {
1244  if (rt.is_reg()) {
1245    slt(rd, rs, rt.rm());
1246  } else {
1247    if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
1248      slti(rd, rs, static_cast<int32_t>(rt.imm64_));
1249    } else {
1250      // li handles the relocation.
1251      DCHECK(!rs.is(at));
1252      li(at, rt);
1253      slt(rd, rs, at);
1254    }
1255  }
1256}
1257
1258
1259void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) {
1260  if (rt.is_reg()) {
1261    sltu(rd, rs, rt.rm());
1262  } else {
1263    if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) {
1264      sltiu(rd, rs, static_cast<int32_t>(rt.imm64_));
1265    } else {
1266      // li handles the relocation.
1267      DCHECK(!rs.is(at));
1268      li(at, rt);
1269      sltu(rd, rs, at);
1270    }
1271  }
1272}
1273
1274
1275void MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) {
1276  if (rt.is_reg()) {
1277    rotrv(rd, rs, rt.rm());
1278  } else {
1279    int64_t ror_value = rt.imm64_ % 32;
1280    if (ror_value < 0) {
1281      ror_value += 32;
1282    }
1283    rotr(rd, rs, ror_value);
1284  }
1285}
1286
1287
1288void MacroAssembler::Dror(Register rd, Register rs, const Operand& rt) {
1289  if (rt.is_reg()) {
1290    drotrv(rd, rs, rt.rm());
1291  } else {
1292    int64_t dror_value = rt.imm64_ % 64;
1293    if (dror_value < 0) dror_value += 64;
1294    if (dror_value <= 31) {
1295      drotr(rd, rs, dror_value);
1296    } else {
1297      drotr32(rd, rs, dror_value - 32);
1298    }
1299  }
1300}
1301
1302
1303void MacroAssembler::Pref(int32_t hint, const MemOperand& rs) {
1304    pref(hint, rs);
1305}
1306
1307
1308void MacroAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa,
1309                         Register scratch) {
1310  DCHECK(sa >= 1 && sa <= 31);
1311  if (kArchVariant == kMips64r6 && sa <= 4) {
1312    lsa(rd, rt, rs, sa - 1);
1313  } else {
1314    Register tmp = rd.is(rt) ? scratch : rd;
1315    DCHECK(!tmp.is(rt));
1316    sll(tmp, rs, sa);
1317    Addu(rd, rt, tmp);
1318  }
1319}
1320
1321
1322void MacroAssembler::Dlsa(Register rd, Register rt, Register rs, uint8_t sa,
1323                          Register scratch) {
1324  DCHECK(sa >= 1 && sa <= 31);
1325  if (kArchVariant == kMips64r6 && sa <= 4) {
1326    dlsa(rd, rt, rs, sa - 1);
1327  } else {
1328    Register tmp = rd.is(rt) ? scratch : rd;
1329    DCHECK(!tmp.is(rt));
1330    dsll(tmp, rs, sa);
1331    Daddu(rd, rt, tmp);
1332  }
1333}
1334
1335
1336// ------------Pseudo-instructions-------------
1337
1338// Change endianness
1339void MacroAssembler::ByteSwapSigned(Register reg, int operand_size) {
1340  DCHECK(operand_size == 1 || operand_size == 2 || operand_size == 4 ||
1341         operand_size == 8);
1342  DCHECK(kArchVariant == kMips64r6 || kArchVariant == kMips64r2);
1343  if (operand_size == 1) {
1344    seb(reg, reg);
1345    sll(reg, reg, 0);
1346    dsbh(reg, reg);
1347    dshd(reg, reg);
1348  } else if (operand_size == 2) {
1349    seh(reg, reg);
1350    sll(reg, reg, 0);
1351    dsbh(reg, reg);
1352    dshd(reg, reg);
1353  } else if (operand_size == 4) {
1354    sll(reg, reg, 0);
1355    dsbh(reg, reg);
1356    dshd(reg, reg);
1357  } else {
1358    dsbh(reg, reg);
1359    dshd(reg, reg);
1360  }
1361}
1362
1363void MacroAssembler::ByteSwapUnsigned(Register reg, int operand_size) {
1364  DCHECK(operand_size == 1 || operand_size == 2 || operand_size == 4);
1365  if (operand_size == 1) {
1366    andi(reg, reg, 0xFF);
1367    dsbh(reg, reg);
1368    dshd(reg, reg);
1369  } else if (operand_size == 2) {
1370    andi(reg, reg, 0xFFFF);
1371    dsbh(reg, reg);
1372    dshd(reg, reg);
1373  } else {
1374    dsll32(reg, reg, 0);
1375    dsrl32(reg, reg, 0);
1376    dsbh(reg, reg);
1377    dshd(reg, reg);
1378  }
1379}
1380
1381void MacroAssembler::Ulw(Register rd, const MemOperand& rs) {
1382  DCHECK(!rd.is(at));
1383  DCHECK(!rs.rm().is(at));
1384  if (kArchVariant == kMips64r6) {
1385    lw(rd, rs);
1386  } else {
1387    DCHECK(kArchVariant == kMips64r2);
1388    if (is_int16(rs.offset() + kMipsLwrOffset) &&
1389        is_int16(rs.offset() + kMipsLwlOffset)) {
1390      if (!rd.is(rs.rm())) {
1391        lwr(rd, MemOperand(rs.rm(), rs.offset() + kMipsLwrOffset));
1392        lwl(rd, MemOperand(rs.rm(), rs.offset() + kMipsLwlOffset));
1393      } else {
1394        lwr(at, MemOperand(rs.rm(), rs.offset() + kMipsLwrOffset));
1395        lwl(at, MemOperand(rs.rm(), rs.offset() + kMipsLwlOffset));
1396        mov(rd, at);
1397      }
1398    } else {  // Offset > 16 bits, use multiple instructions to load.
1399      LoadRegPlusOffsetToAt(rs);
1400      lwr(rd, MemOperand(at, kMipsLwrOffset));
1401      lwl(rd, MemOperand(at, kMipsLwlOffset));
1402    }
1403  }
1404}
1405
1406void MacroAssembler::Ulwu(Register rd, const MemOperand& rs) {
1407  if (kArchVariant == kMips64r6) {
1408    lwu(rd, rs);
1409  } else {
1410    DCHECK(kArchVariant == kMips64r2);
1411    Ulw(rd, rs);
1412    Dext(rd, rd, 0, 32);
1413  }
1414}
1415
1416
1417void MacroAssembler::Usw(Register rd, const MemOperand& rs) {
1418  DCHECK(!rd.is(at));
1419  DCHECK(!rs.rm().is(at));
1420  if (kArchVariant == kMips64r6) {
1421    sw(rd, rs);
1422  } else {
1423    DCHECK(kArchVariant == kMips64r2);
1424    if (is_int16(rs.offset() + kMipsSwrOffset) &&
1425        is_int16(rs.offset() + kMipsSwlOffset)) {
1426      swr(rd, MemOperand(rs.rm(), rs.offset() + kMipsSwrOffset));
1427      swl(rd, MemOperand(rs.rm(), rs.offset() + kMipsSwlOffset));
1428    } else {
1429      LoadRegPlusOffsetToAt(rs);
1430      swr(rd, MemOperand(at, kMipsSwrOffset));
1431      swl(rd, MemOperand(at, kMipsSwlOffset));
1432    }
1433  }
1434}
1435
1436void MacroAssembler::Ulh(Register rd, const MemOperand& rs) {
1437  DCHECK(!rd.is(at));
1438  DCHECK(!rs.rm().is(at));
1439  if (kArchVariant == kMips64r6) {
1440    lh(rd, rs);
1441  } else {
1442    DCHECK(kArchVariant == kMips64r2);
1443    if (is_int16(rs.offset()) && is_int16(rs.offset() + 1)) {
1444#if defined(V8_TARGET_LITTLE_ENDIAN)
1445      lbu(at, rs);
1446      lb(rd, MemOperand(rs.rm(), rs.offset() + 1));
1447#elif defined(V8_TARGET_BIG_ENDIAN)
1448      lbu(at, MemOperand(rs.rm(), rs.offset() + 1));
1449      lb(rd, rs);
1450#endif
1451    } else {  // Offset > 16 bits, use multiple instructions to load.
1452      LoadRegPlusOffsetToAt(rs);
1453#if defined(V8_TARGET_LITTLE_ENDIAN)
1454      lb(rd, MemOperand(at, 1));
1455      lbu(at, MemOperand(at, 0));
1456#elif defined(V8_TARGET_BIG_ENDIAN)
1457      lb(rd, MemOperand(at, 0));
1458      lbu(at, MemOperand(at, 1));
1459#endif
1460    }
1461    dsll(rd, rd, 8);
1462    or_(rd, rd, at);
1463  }
1464}
1465
1466void MacroAssembler::Ulhu(Register rd, const MemOperand& rs) {
1467  DCHECK(!rd.is(at));
1468  DCHECK(!rs.rm().is(at));
1469  if (kArchVariant == kMips64r6) {
1470    lhu(rd, rs);
1471  } else {
1472    DCHECK(kArchVariant == kMips64r2);
1473    if (is_int16(rs.offset()) && is_int16(rs.offset() + 1)) {
1474#if defined(V8_TARGET_LITTLE_ENDIAN)
1475      lbu(at, rs);
1476      lbu(rd, MemOperand(rs.rm(), rs.offset() + 1));
1477#elif defined(V8_TARGET_BIG_ENDIAN)
1478      lbu(at, MemOperand(rs.rm(), rs.offset() + 1));
1479      lbu(rd, rs);
1480#endif
1481    } else {  // Offset > 16 bits, use multiple instructions to load.
1482      LoadRegPlusOffsetToAt(rs);
1483#if defined(V8_TARGET_LITTLE_ENDIAN)
1484      lbu(rd, MemOperand(at, 1));
1485      lbu(at, MemOperand(at, 0));
1486#elif defined(V8_TARGET_BIG_ENDIAN)
1487      lbu(rd, MemOperand(at, 0));
1488      lbu(at, MemOperand(at, 1));
1489#endif
1490    }
1491    dsll(rd, rd, 8);
1492    or_(rd, rd, at);
1493  }
1494}
1495
1496void MacroAssembler::Ush(Register rd, const MemOperand& rs, Register scratch) {
1497  DCHECK(!rd.is(at));
1498  DCHECK(!rs.rm().is(at));
1499  DCHECK(!rs.rm().is(scratch));
1500  DCHECK(!scratch.is(at));
1501  if (kArchVariant == kMips64r6) {
1502    sh(rd, rs);
1503  } else {
1504    DCHECK(kArchVariant == kMips64r2);
1505    MemOperand source = rs;
1506    // If offset > 16 bits, load address to at with offset 0.
1507    if (!is_int16(rs.offset()) || !is_int16(rs.offset() + 1)) {
1508      LoadRegPlusOffsetToAt(rs);
1509      source = MemOperand(at, 0);
1510    }
1511
1512    if (!scratch.is(rd)) {
1513      mov(scratch, rd);
1514    }
1515
1516#if defined(V8_TARGET_LITTLE_ENDIAN)
1517    sb(scratch, source);
1518    srl(scratch, scratch, 8);
1519    sb(scratch, MemOperand(source.rm(), source.offset() + 1));
1520#elif defined(V8_TARGET_BIG_ENDIAN)
1521    sb(scratch, MemOperand(source.rm(), source.offset() + 1));
1522    srl(scratch, scratch, 8);
1523    sb(scratch, source);
1524#endif
1525  }
1526}
1527
1528void MacroAssembler::Uld(Register rd, const MemOperand& rs) {
1529  DCHECK(!rd.is(at));
1530  DCHECK(!rs.rm().is(at));
1531  if (kArchVariant == kMips64r6) {
1532    ld(rd, rs);
1533  } else {
1534    DCHECK(kArchVariant == kMips64r2);
1535    if (is_int16(rs.offset() + kMipsLdrOffset) &&
1536        is_int16(rs.offset() + kMipsLdlOffset)) {
1537      if (!rd.is(rs.rm())) {
1538        ldr(rd, MemOperand(rs.rm(), rs.offset() + kMipsLdrOffset));
1539        ldl(rd, MemOperand(rs.rm(), rs.offset() + kMipsLdlOffset));
1540      } else {
1541        ldr(at, MemOperand(rs.rm(), rs.offset() + kMipsLdrOffset));
1542        ldl(at, MemOperand(rs.rm(), rs.offset() + kMipsLdlOffset));
1543        mov(rd, at);
1544      }
1545    } else {  // Offset > 16 bits, use multiple instructions to load.
1546      LoadRegPlusOffsetToAt(rs);
1547      ldr(rd, MemOperand(at, kMipsLdrOffset));
1548      ldl(rd, MemOperand(at, kMipsLdlOffset));
1549    }
1550  }
1551}
1552
1553
1554// Load consequent 32-bit word pair in 64-bit reg. and put first word in low
1555// bits,
1556// second word in high bits.
1557void MacroAssembler::LoadWordPair(Register rd, const MemOperand& rs,
1558                                  Register scratch) {
1559  lwu(rd, rs);
1560  lw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2));
1561  dsll32(scratch, scratch, 0);
1562  Daddu(rd, rd, scratch);
1563}
1564
1565void MacroAssembler::Usd(Register rd, const MemOperand& rs) {
1566  DCHECK(!rd.is(at));
1567  DCHECK(!rs.rm().is(at));
1568  if (kArchVariant == kMips64r6) {
1569    sd(rd, rs);
1570  } else {
1571    DCHECK(kArchVariant == kMips64r2);
1572    if (is_int16(rs.offset() + kMipsSdrOffset) &&
1573        is_int16(rs.offset() + kMipsSdlOffset)) {
1574      sdr(rd, MemOperand(rs.rm(), rs.offset() + kMipsSdrOffset));
1575      sdl(rd, MemOperand(rs.rm(), rs.offset() + kMipsSdlOffset));
1576    } else {
1577      LoadRegPlusOffsetToAt(rs);
1578      sdr(rd, MemOperand(at, kMipsSdrOffset));
1579      sdl(rd, MemOperand(at, kMipsSdlOffset));
1580    }
1581  }
1582}
1583
1584
1585// Do 64-bit store as two consequent 32-bit stores to unaligned address.
1586void MacroAssembler::StoreWordPair(Register rd, const MemOperand& rs,
1587                                   Register scratch) {
1588  sw(rd, rs);
1589  dsrl32(scratch, rd, 0);
1590  sw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2));
1591}
1592
1593void MacroAssembler::Ulwc1(FPURegister fd, const MemOperand& rs,
1594                           Register scratch) {
1595  if (kArchVariant == kMips64r6) {
1596    lwc1(fd, rs);
1597  } else {
1598    DCHECK(kArchVariant == kMips64r2);
1599    Ulw(scratch, rs);
1600    mtc1(scratch, fd);
1601  }
1602}
1603
1604void MacroAssembler::Uswc1(FPURegister fd, const MemOperand& rs,
1605                           Register scratch) {
1606  if (kArchVariant == kMips64r6) {
1607    swc1(fd, rs);
1608  } else {
1609    DCHECK(kArchVariant == kMips64r2);
1610    mfc1(scratch, fd);
1611    Usw(scratch, rs);
1612  }
1613}
1614
1615void MacroAssembler::Uldc1(FPURegister fd, const MemOperand& rs,
1616                           Register scratch) {
1617  DCHECK(!scratch.is(at));
1618  if (kArchVariant == kMips64r6) {
1619    ldc1(fd, rs);
1620  } else {
1621    DCHECK(kArchVariant == kMips64r2);
1622    Uld(scratch, rs);
1623    dmtc1(scratch, fd);
1624  }
1625}
1626
1627void MacroAssembler::Usdc1(FPURegister fd, const MemOperand& rs,
1628                           Register scratch) {
1629  DCHECK(!scratch.is(at));
1630  if (kArchVariant == kMips64r6) {
1631    sdc1(fd, rs);
1632  } else {
1633    DCHECK(kArchVariant == kMips64r2);
1634    dmfc1(scratch, fd);
1635    Usd(scratch, rs);
1636  }
1637}
1638
1639void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) {
1640  AllowDeferredHandleDereference smi_check;
1641  if (value->IsSmi()) {
1642    li(dst, Operand(value), mode);
1643  } else {
1644    DCHECK(value->IsHeapObject());
1645    if (isolate()->heap()->InNewSpace(*value)) {
1646      Handle<Cell> cell = isolate()->factory()->NewCell(value);
1647      li(dst, Operand(cell));
1648      ld(dst, FieldMemOperand(dst, Cell::kValueOffset));
1649    } else {
1650      li(dst, Operand(value));
1651    }
1652  }
1653}
1654
1655static inline int64_t ShiftAndFixSignExtension(int64_t imm, int bitnum) {
1656  if ((imm >> (bitnum - 1)) & 0x1) {
1657    imm = (imm >> bitnum) + 1;
1658  } else {
1659    imm = imm >> bitnum;
1660  }
1661  return imm;
1662}
1663
1664bool MacroAssembler::LiLower32BitHelper(Register rd, Operand j) {
1665  bool higher_bits_sign_extended = false;
1666  if (is_int16(j.imm64_)) {
1667    daddiu(rd, zero_reg, (j.imm64_ & kImm16Mask));
1668  } else if (!(j.imm64_ & kHiMask)) {
1669    ori(rd, zero_reg, (j.imm64_ & kImm16Mask));
1670  } else if (!(j.imm64_ & kImm16Mask)) {
1671    lui(rd, (j.imm64_ >> kLuiShift) & kImm16Mask);
1672    if ((j.imm64_ >> (kLuiShift + 15)) & 0x1) {
1673      higher_bits_sign_extended = true;
1674    }
1675  } else {
1676    lui(rd, (j.imm64_ >> kLuiShift) & kImm16Mask);
1677    ori(rd, rd, (j.imm64_ & kImm16Mask));
1678    if ((j.imm64_ >> (kLuiShift + 15)) & 0x1) {
1679      higher_bits_sign_extended = true;
1680    }
1681  }
1682  return higher_bits_sign_extended;
1683}
1684
1685void MacroAssembler::li(Register rd, Operand j, LiFlags mode) {
1686  DCHECK(!j.is_reg());
1687  BlockTrampolinePoolScope block_trampoline_pool(this);
1688  if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) {
1689    // Normal load of an immediate value which does not need Relocation Info.
1690    if (is_int32(j.imm64_)) {
1691      LiLower32BitHelper(rd, j);
1692    } else {
1693      if (kArchVariant == kMips64r6) {
1694        int64_t imm = j.imm64_;
1695        bool higher_bits_sign_extended = LiLower32BitHelper(rd, j);
1696        imm = ShiftAndFixSignExtension(imm, 32);
1697        // If LUI writes 1s to higher bits, we need both DAHI/DATI.
1698        if ((imm & kImm16Mask) ||
1699            (higher_bits_sign_extended && (j.imm64_ > 0))) {
1700          dahi(rd, imm & kImm16Mask);
1701        }
1702        imm = ShiftAndFixSignExtension(imm, 16);
1703        if ((!is_int48(j.imm64_) && (imm & kImm16Mask)) ||
1704            (higher_bits_sign_extended && (j.imm64_ > 0))) {
1705          dati(rd, imm & kImm16Mask);
1706        }
1707      } else {
1708        if (is_int48(j.imm64_)) {
1709          if ((j.imm64_ >> 32) & kImm16Mask) {
1710            lui(rd, (j.imm64_ >> 32) & kImm16Mask);
1711            if ((j.imm64_ >> 16) & kImm16Mask) {
1712              ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
1713            }
1714          } else {
1715            ori(rd, zero_reg, (j.imm64_ >> 16) & kImm16Mask);
1716          }
1717          dsll(rd, rd, 16);
1718          if (j.imm64_ & kImm16Mask) {
1719            ori(rd, rd, j.imm64_ & kImm16Mask);
1720          }
1721        } else {
1722          lui(rd, (j.imm64_ >> 48) & kImm16Mask);
1723          if ((j.imm64_ >> 32) & kImm16Mask) {
1724            ori(rd, rd, (j.imm64_ >> 32) & kImm16Mask);
1725          }
1726          if ((j.imm64_ >> 16) & kImm16Mask) {
1727            dsll(rd, rd, 16);
1728            ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
1729            if (j.imm64_ & kImm16Mask) {
1730              dsll(rd, rd, 16);
1731              ori(rd, rd, j.imm64_ & kImm16Mask);
1732            } else {
1733              dsll(rd, rd, 16);
1734            }
1735          } else {
1736            if (j.imm64_ & kImm16Mask) {
1737              dsll32(rd, rd, 0);
1738              ori(rd, rd, j.imm64_ & kImm16Mask);
1739            } else {
1740              dsll32(rd, rd, 0);
1741            }
1742          }
1743        }
1744      }
1745    }
1746  } else if (MustUseReg(j.rmode_)) {
1747    RecordRelocInfo(j.rmode_, j.imm64_);
1748    lui(rd, (j.imm64_ >> 32) & kImm16Mask);
1749    ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
1750    dsll(rd, rd, 16);
1751    ori(rd, rd, j.imm64_ & kImm16Mask);
1752  } else if (mode == ADDRESS_LOAD)  {
1753    // We always need the same number of instructions as we may need to patch
1754    // this code to load another value which may need all 4 instructions.
1755    lui(rd, (j.imm64_ >> 32) & kImm16Mask);
1756    ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
1757    dsll(rd, rd, 16);
1758    ori(rd, rd, j.imm64_ & kImm16Mask);
1759  } else {
1760    if (kArchVariant == kMips64r6) {
1761      int64_t imm = j.imm64_;
1762      lui(rd, (imm >> kLuiShift) & kImm16Mask);
1763      if (imm & kImm16Mask) {
1764        ori(rd, rd, (imm & kImm16Mask));
1765      }
1766      if ((imm >> 31) & 0x1) {
1767        imm = (imm >> 32) + 1;
1768      } else {
1769        imm = imm >> 32;
1770      }
1771      dahi(rd, imm & kImm16Mask);
1772      if ((imm >> 15) & 0x1) {
1773        imm = (imm >> 16) + 1;
1774      } else {
1775        imm = imm >> 16;
1776      }
1777      dati(rd, imm & kImm16Mask);
1778    } else {
1779      lui(rd, (j.imm64_ >> 48) & kImm16Mask);
1780      ori(rd, rd, (j.imm64_ >> 32) & kImm16Mask);
1781      dsll(rd, rd, 16);
1782      ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask);
1783      dsll(rd, rd, 16);
1784      ori(rd, rd, j.imm64_ & kImm16Mask);
1785    }
1786  }
1787}
1788
1789
1790void MacroAssembler::MultiPush(RegList regs) {
1791  int16_t num_to_push = NumberOfBitsSet(regs);
1792  int16_t stack_offset = num_to_push * kPointerSize;
1793
1794  Dsubu(sp, sp, Operand(stack_offset));
1795  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
1796    if ((regs & (1 << i)) != 0) {
1797      stack_offset -= kPointerSize;
1798      sd(ToRegister(i), MemOperand(sp, stack_offset));
1799    }
1800  }
1801}
1802
1803
1804void MacroAssembler::MultiPushReversed(RegList regs) {
1805  int16_t num_to_push = NumberOfBitsSet(regs);
1806  int16_t stack_offset = num_to_push * kPointerSize;
1807
1808  Dsubu(sp, sp, Operand(stack_offset));
1809  for (int16_t i = 0; i < kNumRegisters; i++) {
1810    if ((regs & (1 << i)) != 0) {
1811      stack_offset -= kPointerSize;
1812      sd(ToRegister(i), MemOperand(sp, stack_offset));
1813    }
1814  }
1815}
1816
1817
1818void MacroAssembler::MultiPop(RegList regs) {
1819  int16_t stack_offset = 0;
1820
1821  for (int16_t i = 0; i < kNumRegisters; i++) {
1822    if ((regs & (1 << i)) != 0) {
1823      ld(ToRegister(i), MemOperand(sp, stack_offset));
1824      stack_offset += kPointerSize;
1825    }
1826  }
1827  daddiu(sp, sp, stack_offset);
1828}
1829
1830
1831void MacroAssembler::MultiPopReversed(RegList regs) {
1832  int16_t stack_offset = 0;
1833
1834  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
1835    if ((regs & (1 << i)) != 0) {
1836      ld(ToRegister(i), MemOperand(sp, stack_offset));
1837      stack_offset += kPointerSize;
1838    }
1839  }
1840  daddiu(sp, sp, stack_offset);
1841}
1842
1843
1844void MacroAssembler::MultiPushFPU(RegList regs) {
1845  int16_t num_to_push = NumberOfBitsSet(regs);
1846  int16_t stack_offset = num_to_push * kDoubleSize;
1847
1848  Dsubu(sp, sp, Operand(stack_offset));
1849  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
1850    if ((regs & (1 << i)) != 0) {
1851      stack_offset -= kDoubleSize;
1852      sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1853    }
1854  }
1855}
1856
1857
1858void MacroAssembler::MultiPushReversedFPU(RegList regs) {
1859  int16_t num_to_push = NumberOfBitsSet(regs);
1860  int16_t stack_offset = num_to_push * kDoubleSize;
1861
1862  Dsubu(sp, sp, Operand(stack_offset));
1863  for (int16_t i = 0; i < kNumRegisters; i++) {
1864    if ((regs & (1 << i)) != 0) {
1865      stack_offset -= kDoubleSize;
1866      sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1867    }
1868  }
1869}
1870
1871
1872void MacroAssembler::MultiPopFPU(RegList regs) {
1873  int16_t stack_offset = 0;
1874
1875  for (int16_t i = 0; i < kNumRegisters; i++) {
1876    if ((regs & (1 << i)) != 0) {
1877      ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1878      stack_offset += kDoubleSize;
1879    }
1880  }
1881  daddiu(sp, sp, stack_offset);
1882}
1883
1884
1885void MacroAssembler::MultiPopReversedFPU(RegList regs) {
1886  int16_t stack_offset = 0;
1887
1888  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
1889    if ((regs & (1 << i)) != 0) {
1890      ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1891      stack_offset += kDoubleSize;
1892    }
1893  }
1894  daddiu(sp, sp, stack_offset);
1895}
1896
1897
1898void MacroAssembler::Ext(Register rt,
1899                         Register rs,
1900                         uint16_t pos,
1901                         uint16_t size) {
1902  DCHECK(pos < 32);
1903  DCHECK(pos + size < 33);
1904  ext_(rt, rs, pos, size);
1905}
1906
1907
1908void MacroAssembler::Dext(Register rt, Register rs, uint16_t pos,
1909                          uint16_t size) {
1910  DCHECK(pos < 32);
1911  DCHECK(pos + size < 33);
1912  dext_(rt, rs, pos, size);
1913}
1914
1915
1916void MacroAssembler::Dextm(Register rt, Register rs, uint16_t pos,
1917                           uint16_t size) {
1918  DCHECK(pos < 32);
1919  DCHECK(size <= 64);
1920  dextm(rt, rs, pos, size);
1921}
1922
1923
1924void MacroAssembler::Dextu(Register rt, Register rs, uint16_t pos,
1925                           uint16_t size) {
1926  DCHECK(pos >= 32 && pos < 64);
1927  DCHECK(size < 33);
1928  dextu(rt, rs, pos, size);
1929}
1930
1931
1932void MacroAssembler::Dins(Register rt, Register rs, uint16_t pos,
1933                          uint16_t size) {
1934  DCHECK(pos < 32);
1935  DCHECK(pos + size <= 32);
1936  DCHECK(size != 0);
1937  dins_(rt, rs, pos, size);
1938}
1939
1940
1941void MacroAssembler::Ins(Register rt,
1942                         Register rs,
1943                         uint16_t pos,
1944                         uint16_t size) {
1945  DCHECK(pos < 32);
1946  DCHECK(pos + size <= 32);
1947  DCHECK(size != 0);
1948  ins_(rt, rs, pos, size);
1949}
1950
1951
1952void MacroAssembler::Cvt_d_uw(FPURegister fd, FPURegister fs) {
1953  // Move the data from fs to t8.
1954  mfc1(t8, fs);
1955  Cvt_d_uw(fd, t8);
1956}
1957
1958
1959void MacroAssembler::Cvt_d_uw(FPURegister fd, Register rs) {
1960  // Convert rs to a FP value in fd.
1961  DCHECK(!rs.is(t9));
1962  DCHECK(!rs.is(at));
1963
1964  // Zero extend int32 in rs.
1965  Dext(t9, rs, 0, 32);
1966  dmtc1(t9, fd);
1967  cvt_d_l(fd, fd);
1968}
1969
1970
1971void MacroAssembler::Cvt_d_ul(FPURegister fd, FPURegister fs) {
1972  // Move the data from fs to t8.
1973  dmfc1(t8, fs);
1974  Cvt_d_ul(fd, t8);
1975}
1976
1977
1978void MacroAssembler::Cvt_d_ul(FPURegister fd, Register rs) {
1979  // Convert rs to a FP value in fd.
1980
1981  DCHECK(!rs.is(t9));
1982  DCHECK(!rs.is(at));
1983
1984  Label msb_clear, conversion_done;
1985
1986  Branch(&msb_clear, ge, rs, Operand(zero_reg));
1987
1988  // Rs >= 2^63
1989  andi(t9, rs, 1);
1990  dsrl(rs, rs, 1);
1991  or_(t9, t9, rs);
1992  dmtc1(t9, fd);
1993  cvt_d_l(fd, fd);
1994  Branch(USE_DELAY_SLOT, &conversion_done);
1995  add_d(fd, fd, fd);  // In delay slot.
1996
1997  bind(&msb_clear);
1998  // Rs < 2^63, we can do simple conversion.
1999  dmtc1(rs, fd);
2000  cvt_d_l(fd, fd);
2001
2002  bind(&conversion_done);
2003}
2004
2005void MacroAssembler::Cvt_s_uw(FPURegister fd, FPURegister fs) {
2006  // Move the data from fs to t8.
2007  mfc1(t8, fs);
2008  Cvt_s_uw(fd, t8);
2009}
2010
2011void MacroAssembler::Cvt_s_uw(FPURegister fd, Register rs) {
2012  // Convert rs to a FP value in fd.
2013  DCHECK(!rs.is(t9));
2014  DCHECK(!rs.is(at));
2015
2016  // Zero extend int32 in rs.
2017  Dext(t9, rs, 0, 32);
2018  dmtc1(t9, fd);
2019  cvt_s_l(fd, fd);
2020}
2021
2022void MacroAssembler::Cvt_s_ul(FPURegister fd, FPURegister fs) {
2023  // Move the data from fs to t8.
2024  dmfc1(t8, fs);
2025  Cvt_s_ul(fd, t8);
2026}
2027
2028
2029void MacroAssembler::Cvt_s_ul(FPURegister fd, Register rs) {
2030  // Convert rs to a FP value in fd.
2031
2032  DCHECK(!rs.is(t9));
2033  DCHECK(!rs.is(at));
2034
2035  Label positive, conversion_done;
2036
2037  Branch(&positive, ge, rs, Operand(zero_reg));
2038
2039  // Rs >= 2^31.
2040  andi(t9, rs, 1);
2041  dsrl(rs, rs, 1);
2042  or_(t9, t9, rs);
2043  dmtc1(t9, fd);
2044  cvt_s_l(fd, fd);
2045  Branch(USE_DELAY_SLOT, &conversion_done);
2046  add_s(fd, fd, fd);  // In delay slot.
2047
2048  bind(&positive);
2049  // Rs < 2^31, we can do simple conversion.
2050  dmtc1(rs, fd);
2051  cvt_s_l(fd, fd);
2052
2053  bind(&conversion_done);
2054}
2055
2056
2057void MacroAssembler::Round_l_d(FPURegister fd, FPURegister fs) {
2058  round_l_d(fd, fs);
2059}
2060
2061
2062void MacroAssembler::Floor_l_d(FPURegister fd, FPURegister fs) {
2063  floor_l_d(fd, fs);
2064}
2065
2066
2067void MacroAssembler::Ceil_l_d(FPURegister fd, FPURegister fs) {
2068  ceil_l_d(fd, fs);
2069}
2070
2071
2072void MacroAssembler::Trunc_l_d(FPURegister fd, FPURegister fs) {
2073  trunc_l_d(fd, fs);
2074}
2075
2076
2077void MacroAssembler::Trunc_l_ud(FPURegister fd,
2078                                FPURegister fs,
2079                                FPURegister scratch) {
2080  // Load to GPR.
2081  dmfc1(t8, fs);
2082  // Reset sign bit.
2083  li(at, 0x7fffffffffffffff);
2084  and_(t8, t8, at);
2085  dmtc1(t8, fs);
2086  trunc_l_d(fd, fs);
2087}
2088
2089
2090void MacroAssembler::Trunc_uw_d(FPURegister fd,
2091                                FPURegister fs,
2092                                FPURegister scratch) {
2093  Trunc_uw_d(fs, t8, scratch);
2094  mtc1(t8, fd);
2095}
2096
2097void MacroAssembler::Trunc_uw_s(FPURegister fd, FPURegister fs,
2098                                FPURegister scratch) {
2099  Trunc_uw_s(fs, t8, scratch);
2100  mtc1(t8, fd);
2101}
2102
2103void MacroAssembler::Trunc_ul_d(FPURegister fd, FPURegister fs,
2104                                FPURegister scratch, Register result) {
2105  Trunc_ul_d(fs, t8, scratch, result);
2106  dmtc1(t8, fd);
2107}
2108
2109
2110void MacroAssembler::Trunc_ul_s(FPURegister fd, FPURegister fs,
2111                                FPURegister scratch, Register result) {
2112  Trunc_ul_s(fs, t8, scratch, result);
2113  dmtc1(t8, fd);
2114}
2115
2116
2117void MacroAssembler::Trunc_w_d(FPURegister fd, FPURegister fs) {
2118  trunc_w_d(fd, fs);
2119}
2120
2121
2122void MacroAssembler::Round_w_d(FPURegister fd, FPURegister fs) {
2123  round_w_d(fd, fs);
2124}
2125
2126
2127void MacroAssembler::Floor_w_d(FPURegister fd, FPURegister fs) {
2128  floor_w_d(fd, fs);
2129}
2130
2131
2132void MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) {
2133  ceil_w_d(fd, fs);
2134}
2135
2136
2137void MacroAssembler::Trunc_uw_d(FPURegister fd,
2138                                Register rs,
2139                                FPURegister scratch) {
2140  DCHECK(!fd.is(scratch));
2141  DCHECK(!rs.is(at));
2142
2143  // Load 2^31 into scratch as its float representation.
2144  li(at, 0x41E00000);
2145  mtc1(zero_reg, scratch);
2146  mthc1(at, scratch);
2147  // Test if scratch > fd.
2148  // If fd < 2^31 we can convert it normally.
2149  Label simple_convert;
2150  BranchF(&simple_convert, NULL, lt, fd, scratch);
2151
2152  // First we subtract 2^31 from fd, then trunc it to rs
2153  // and add 2^31 to rs.
2154  sub_d(scratch, fd, scratch);
2155  trunc_w_d(scratch, scratch);
2156  mfc1(rs, scratch);
2157  Or(rs, rs, 1 << 31);
2158
2159  Label done;
2160  Branch(&done);
2161  // Simple conversion.
2162  bind(&simple_convert);
2163  trunc_w_d(scratch, fd);
2164  mfc1(rs, scratch);
2165
2166  bind(&done);
2167}
2168
2169void MacroAssembler::Trunc_uw_s(FPURegister fd, Register rs,
2170                                FPURegister scratch) {
2171  DCHECK(!fd.is(scratch));
2172  DCHECK(!rs.is(at));
2173
2174  // Load 2^31 into scratch as its float representation.
2175  li(at, 0x4F000000);
2176  mtc1(at, scratch);
2177  // Test if scratch > fd.
2178  // If fd < 2^31 we can convert it normally.
2179  Label simple_convert;
2180  BranchF32(&simple_convert, NULL, lt, fd, scratch);
2181
2182  // First we subtract 2^31 from fd, then trunc it to rs
2183  // and add 2^31 to rs.
2184  sub_s(scratch, fd, scratch);
2185  trunc_w_s(scratch, scratch);
2186  mfc1(rs, scratch);
2187  Or(rs, rs, 1 << 31);
2188
2189  Label done;
2190  Branch(&done);
2191  // Simple conversion.
2192  bind(&simple_convert);
2193  trunc_w_s(scratch, fd);
2194  mfc1(rs, scratch);
2195
2196  bind(&done);
2197}
2198
2199void MacroAssembler::Trunc_ul_d(FPURegister fd, Register rs,
2200                                FPURegister scratch, Register result) {
2201  DCHECK(!fd.is(scratch));
2202  DCHECK(!AreAliased(rs, result, at));
2203
2204  Label simple_convert, done, fail;
2205  if (result.is_valid()) {
2206    mov(result, zero_reg);
2207    Move(scratch, -1.0);
2208    // If fd =< -1 or unordered, then the conversion fails.
2209    BranchF(&fail, &fail, le, fd, scratch);
2210  }
2211
2212  // Load 2^63 into scratch as its double representation.
2213  li(at, 0x43e0000000000000);
2214  dmtc1(at, scratch);
2215
2216  // Test if scratch > fd.
2217  // If fd < 2^63 we can convert it normally.
2218  BranchF(&simple_convert, nullptr, lt, fd, scratch);
2219
2220  // First we subtract 2^63 from fd, then trunc it to rs
2221  // and add 2^63 to rs.
2222  sub_d(scratch, fd, scratch);
2223  trunc_l_d(scratch, scratch);
2224  dmfc1(rs, scratch);
2225  Or(rs, rs, Operand(1UL << 63));
2226  Branch(&done);
2227
2228  // Simple conversion.
2229  bind(&simple_convert);
2230  trunc_l_d(scratch, fd);
2231  dmfc1(rs, scratch);
2232
2233  bind(&done);
2234  if (result.is_valid()) {
2235    // Conversion is failed if the result is negative.
2236    addiu(at, zero_reg, -1);
2237    dsrl(at, at, 1);  // Load 2^62.
2238    dmfc1(result, scratch);
2239    xor_(result, result, at);
2240    Slt(result, zero_reg, result);
2241  }
2242
2243  bind(&fail);
2244}
2245
2246
2247void MacroAssembler::Trunc_ul_s(FPURegister fd, Register rs,
2248                                FPURegister scratch, Register result) {
2249  DCHECK(!fd.is(scratch));
2250  DCHECK(!AreAliased(rs, result, at));
2251
2252  Label simple_convert, done, fail;
2253  if (result.is_valid()) {
2254    mov(result, zero_reg);
2255    Move(scratch, -1.0f);
2256    // If fd =< -1 or unordered, then the conversion fails.
2257    BranchF32(&fail, &fail, le, fd, scratch);
2258  }
2259
2260  // Load 2^63 into scratch as its float representation.
2261  li(at, 0x5f000000);
2262  mtc1(at, scratch);
2263
2264  // Test if scratch > fd.
2265  // If fd < 2^63 we can convert it normally.
2266  BranchF32(&simple_convert, nullptr, lt, fd, scratch);
2267
2268  // First we subtract 2^63 from fd, then trunc it to rs
2269  // and add 2^63 to rs.
2270  sub_s(scratch, fd, scratch);
2271  trunc_l_s(scratch, scratch);
2272  dmfc1(rs, scratch);
2273  Or(rs, rs, Operand(1UL << 63));
2274  Branch(&done);
2275
2276  // Simple conversion.
2277  bind(&simple_convert);
2278  trunc_l_s(scratch, fd);
2279  dmfc1(rs, scratch);
2280
2281  bind(&done);
2282  if (result.is_valid()) {
2283    // Conversion is failed if the result is negative or unordered.
2284    addiu(at, zero_reg, -1);
2285    dsrl(at, at, 1);  // Load 2^62.
2286    dmfc1(result, scratch);
2287    xor_(result, result, at);
2288    Slt(result, zero_reg, result);
2289  }
2290
2291  bind(&fail);
2292}
2293
2294
2295void MacroAssembler::Madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
2296    FPURegister ft, FPURegister scratch) {
2297  if (0) {  // TODO(plind): find reasonable arch-variant symbol names.
2298    madd_d(fd, fr, fs, ft);
2299  } else {
2300    // Can not change source regs's value.
2301    DCHECK(!fr.is(scratch) && !fs.is(scratch) && !ft.is(scratch));
2302    mul_d(scratch, fs, ft);
2303    add_d(fd, fr, scratch);
2304  }
2305}
2306
2307
2308void MacroAssembler::BranchFCommon(SecondaryField sizeField, Label* target,
2309                                   Label* nan, Condition cond, FPURegister cmp1,
2310                                   FPURegister cmp2, BranchDelaySlot bd) {
2311  BlockTrampolinePoolScope block_trampoline_pool(this);
2312  if (cond == al) {
2313    Branch(bd, target);
2314    return;
2315  }
2316
2317  if (kArchVariant == kMips64r6) {
2318    sizeField = sizeField == D ? L : W;
2319  }
2320
2321  DCHECK(nan || target);
2322  // Check for unordered (NaN) cases.
2323  if (nan) {
2324    bool long_branch = nan->is_bound() ? is_near(nan) : is_trampoline_emitted();
2325    if (kArchVariant != kMips64r6) {
2326      if (long_branch) {
2327        Label skip;
2328        c(UN, sizeField, cmp1, cmp2);
2329        bc1f(&skip);
2330        nop();
2331        BranchLong(nan, bd);
2332        bind(&skip);
2333      } else {
2334        c(UN, sizeField, cmp1, cmp2);
2335        bc1t(nan);
2336        if (bd == PROTECT) {
2337          nop();
2338        }
2339      }
2340    } else {
2341      // Use kDoubleCompareReg for comparison result. It has to be unavailable
2342      // to lithium
2343      // register allocator.
2344      DCHECK(!cmp1.is(kDoubleCompareReg) && !cmp2.is(kDoubleCompareReg));
2345      if (long_branch) {
2346        Label skip;
2347        cmp(UN, sizeField, kDoubleCompareReg, cmp1, cmp2);
2348        bc1eqz(&skip, kDoubleCompareReg);
2349        nop();
2350        BranchLong(nan, bd);
2351        bind(&skip);
2352      } else {
2353        cmp(UN, sizeField, kDoubleCompareReg, cmp1, cmp2);
2354        bc1nez(nan, kDoubleCompareReg);
2355        if (bd == PROTECT) {
2356          nop();
2357        }
2358      }
2359    }
2360  }
2361
2362  if (target) {
2363    bool long_branch =
2364        target->is_bound() ? is_near(target) : is_trampoline_emitted();
2365    if (long_branch) {
2366      Label skip;
2367      Condition neg_cond = NegateFpuCondition(cond);
2368      BranchShortF(sizeField, &skip, neg_cond, cmp1, cmp2, bd);
2369      BranchLong(target, bd);
2370      bind(&skip);
2371    } else {
2372      BranchShortF(sizeField, target, cond, cmp1, cmp2, bd);
2373    }
2374  }
2375}
2376
2377
2378void MacroAssembler::BranchShortF(SecondaryField sizeField, Label* target,
2379                                  Condition cc, FPURegister cmp1,
2380                                  FPURegister cmp2, BranchDelaySlot bd) {
2381  if (kArchVariant != kMips64r6) {
2382    BlockTrampolinePoolScope block_trampoline_pool(this);
2383    if (target) {
2384      // Here NaN cases were either handled by this function or are assumed to
2385      // have been handled by the caller.
2386      switch (cc) {
2387        case lt:
2388          c(OLT, sizeField, cmp1, cmp2);
2389          bc1t(target);
2390          break;
2391        case ult:
2392          c(ULT, sizeField, cmp1, cmp2);
2393          bc1t(target);
2394          break;
2395        case gt:
2396          c(ULE, sizeField, cmp1, cmp2);
2397          bc1f(target);
2398          break;
2399        case ugt:
2400          c(OLE, sizeField, cmp1, cmp2);
2401          bc1f(target);
2402          break;
2403        case ge:
2404          c(ULT, sizeField, cmp1, cmp2);
2405          bc1f(target);
2406          break;
2407        case uge:
2408          c(OLT, sizeField, cmp1, cmp2);
2409          bc1f(target);
2410          break;
2411        case le:
2412          c(OLE, sizeField, cmp1, cmp2);
2413          bc1t(target);
2414          break;
2415        case ule:
2416          c(ULE, sizeField, cmp1, cmp2);
2417          bc1t(target);
2418          break;
2419        case eq:
2420          c(EQ, sizeField, cmp1, cmp2);
2421          bc1t(target);
2422          break;
2423        case ueq:
2424          c(UEQ, sizeField, cmp1, cmp2);
2425          bc1t(target);
2426          break;
2427        case ne:  // Unordered or not equal.
2428          c(EQ, sizeField, cmp1, cmp2);
2429          bc1f(target);
2430          break;
2431        case ogl:
2432          c(UEQ, sizeField, cmp1, cmp2);
2433          bc1f(target);
2434          break;
2435        default:
2436          CHECK(0);
2437      }
2438    }
2439  } else {
2440    BlockTrampolinePoolScope block_trampoline_pool(this);
2441    if (target) {
2442      // Here NaN cases were either handled by this function or are assumed to
2443      // have been handled by the caller.
2444      // Unsigned conditions are treated as their signed counterpart.
2445      // Use kDoubleCompareReg for comparison result, it is valid in fp64 (FR =
2446      // 1) mode.
2447      DCHECK(!cmp1.is(kDoubleCompareReg) && !cmp2.is(kDoubleCompareReg));
2448      switch (cc) {
2449        case lt:
2450          cmp(OLT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2451          bc1nez(target, kDoubleCompareReg);
2452          break;
2453        case ult:
2454          cmp(ULT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2455          bc1nez(target, kDoubleCompareReg);
2456          break;
2457        case gt:
2458          cmp(ULE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2459          bc1eqz(target, kDoubleCompareReg);
2460          break;
2461        case ugt:
2462          cmp(OLE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2463          bc1eqz(target, kDoubleCompareReg);
2464          break;
2465        case ge:
2466          cmp(ULT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2467          bc1eqz(target, kDoubleCompareReg);
2468          break;
2469        case uge:
2470          cmp(OLT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2471          bc1eqz(target, kDoubleCompareReg);
2472          break;
2473        case le:
2474          cmp(OLE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2475          bc1nez(target, kDoubleCompareReg);
2476          break;
2477        case ule:
2478          cmp(ULE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2479          bc1nez(target, kDoubleCompareReg);
2480          break;
2481        case eq:
2482          cmp(EQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2483          bc1nez(target, kDoubleCompareReg);
2484          break;
2485        case ueq:
2486          cmp(UEQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2487          bc1nez(target, kDoubleCompareReg);
2488          break;
2489        case ne:
2490          cmp(EQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2491          bc1eqz(target, kDoubleCompareReg);
2492          break;
2493        case ogl:
2494          cmp(UEQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2495          bc1eqz(target, kDoubleCompareReg);
2496          break;
2497        default:
2498          CHECK(0);
2499      }
2500    }
2501  }
2502
2503  if (bd == PROTECT) {
2504    nop();
2505  }
2506}
2507
2508
2509void MacroAssembler::FmoveLow(FPURegister dst, Register src_low) {
2510  DCHECK(!src_low.is(at));
2511  mfhc1(at, dst);
2512  mtc1(src_low, dst);
2513  mthc1(at, dst);
2514}
2515
2516
2517void MacroAssembler::Move(FPURegister dst, float imm) {
2518  li(at, Operand(bit_cast<int32_t>(imm)));
2519  mtc1(at, dst);
2520}
2521
2522
2523void MacroAssembler::Move(FPURegister dst, double imm) {
2524  static const DoubleRepresentation minus_zero(-0.0);
2525  static const DoubleRepresentation zero(0.0);
2526  DoubleRepresentation value_rep(imm);
2527  // Handle special values first.
2528  if (value_rep == zero && has_double_zero_reg_set_) {
2529    mov_d(dst, kDoubleRegZero);
2530  } else if (value_rep == minus_zero && has_double_zero_reg_set_) {
2531    neg_d(dst, kDoubleRegZero);
2532  } else {
2533    uint32_t lo, hi;
2534    DoubleAsTwoUInt32(imm, &lo, &hi);
2535    // Move the low part of the double into the lower bits of the corresponding
2536    // FPU register.
2537    if (lo != 0) {
2538      if (!(lo & kImm16Mask)) {
2539        lui(at, (lo >> kLuiShift) & kImm16Mask);
2540        mtc1(at, dst);
2541      } else if (!(lo & kHiMask)) {
2542        ori(at, zero_reg, lo & kImm16Mask);
2543        mtc1(at, dst);
2544      } else {
2545        lui(at, (lo >> kLuiShift) & kImm16Mask);
2546        ori(at, at, lo & kImm16Mask);
2547        mtc1(at, dst);
2548      }
2549    } else {
2550      mtc1(zero_reg, dst);
2551    }
2552    // Move the high part of the double into the high bits of the corresponding
2553    // FPU register.
2554    if (hi != 0) {
2555      if (!(hi & kImm16Mask)) {
2556        lui(at, (hi >> kLuiShift) & kImm16Mask);
2557        mthc1(at, dst);
2558      } else if (!(hi & kHiMask)) {
2559        ori(at, zero_reg, hi & kImm16Mask);
2560        mthc1(at, dst);
2561      } else {
2562        lui(at, (hi >> kLuiShift) & kImm16Mask);
2563        ori(at, at, hi & kImm16Mask);
2564        mthc1(at, dst);
2565      }
2566    } else {
2567      mthc1(zero_reg, dst);
2568    }
2569    if (dst.is(kDoubleRegZero)) has_double_zero_reg_set_ = true;
2570  }
2571}
2572
2573
2574void MacroAssembler::Movz(Register rd, Register rs, Register rt) {
2575  if (kArchVariant == kMips64r6) {
2576    Label done;
2577    Branch(&done, ne, rt, Operand(zero_reg));
2578    mov(rd, rs);
2579    bind(&done);
2580  } else {
2581    movz(rd, rs, rt);
2582  }
2583}
2584
2585
2586void MacroAssembler::Movn(Register rd, Register rs, Register rt) {
2587  if (kArchVariant == kMips64r6) {
2588    Label done;
2589    Branch(&done, eq, rt, Operand(zero_reg));
2590    mov(rd, rs);
2591    bind(&done);
2592  } else {
2593    movn(rd, rs, rt);
2594  }
2595}
2596
2597
2598void MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) {
2599  movt(rd, rs, cc);
2600}
2601
2602
2603void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) {
2604  movf(rd, rs, cc);
2605}
2606
2607#define __ masm->
2608
2609static bool ZeroHelper_d(MacroAssembler* masm, MaxMinKind kind, FPURegister dst,
2610                         FPURegister src1, FPURegister src2, Label* equal) {
2611  if (src1.is(src2)) {
2612    __ Move(dst, src1);
2613    return true;
2614  }
2615
2616  Label other, compare_not_equal;
2617  FPURegister left, right;
2618  if (kind == MaxMinKind::kMin) {
2619    left = src1;
2620    right = src2;
2621  } else {
2622    left = src2;
2623    right = src1;
2624  }
2625
2626  __ BranchF64(&compare_not_equal, nullptr, ne, src1, src2);
2627  // Left and right hand side are equal, check for -0 vs. +0.
2628  __ dmfc1(t8, src1);
2629  __ Branch(&other, eq, t8, Operand(0x8000000000000000));
2630  __ Move_d(dst, right);
2631  __ Branch(equal);
2632  __ bind(&other);
2633  __ Move_d(dst, left);
2634  __ Branch(equal);
2635  __ bind(&compare_not_equal);
2636  return false;
2637}
2638
2639static bool ZeroHelper_s(MacroAssembler* masm, MaxMinKind kind, FPURegister dst,
2640                         FPURegister src1, FPURegister src2, Label* equal) {
2641  if (src1.is(src2)) {
2642    __ Move(dst, src1);
2643    return true;
2644  }
2645
2646  Label other, compare_not_equal;
2647  FPURegister left, right;
2648  if (kind == MaxMinKind::kMin) {
2649    left = src1;
2650    right = src2;
2651  } else {
2652    left = src2;
2653    right = src1;
2654  }
2655
2656  __ BranchF32(&compare_not_equal, nullptr, ne, src1, src2);
2657  // Left and right hand side are equal, check for -0 vs. +0.
2658  __ FmoveLow(t8, src1);
2659  __ dsll32(t8, t8, 0);
2660  __ Branch(&other, eq, t8, Operand(0x8000000000000000));
2661  __ Move_s(dst, right);
2662  __ Branch(equal);
2663  __ bind(&other);
2664  __ Move_s(dst, left);
2665  __ Branch(equal);
2666  __ bind(&compare_not_equal);
2667  return false;
2668}
2669
2670#undef __
2671
2672void MacroAssembler::MinNaNCheck_d(FPURegister dst, FPURegister src1,
2673                                   FPURegister src2, Label* nan) {
2674  if (nan) {
2675    BranchF64(nullptr, nan, eq, src1, src2);
2676  }
2677  if (kArchVariant >= kMips64r6) {
2678    min_d(dst, src1, src2);
2679  } else {
2680    Label skip;
2681    if (!ZeroHelper_d(this, MaxMinKind::kMin, dst, src1, src2, &skip)) {
2682      if (dst.is(src1)) {
2683        BranchF64(&skip, nullptr, le, src1, src2);
2684        Move_d(dst, src2);
2685      } else if (dst.is(src2)) {
2686        BranchF64(&skip, nullptr, ge, src1, src2);
2687        Move_d(dst, src1);
2688      } else {
2689        Label right;
2690        BranchF64(&right, nullptr, gt, src1, src2);
2691        Move_d(dst, src1);
2692        Branch(&skip);
2693        bind(&right);
2694        Move_d(dst, src2);
2695      }
2696    }
2697    bind(&skip);
2698  }
2699}
2700
2701void MacroAssembler::MaxNaNCheck_d(FPURegister dst, FPURegister src1,
2702                                   FPURegister src2, Label* nan) {
2703  if (nan) {
2704    BranchF64(nullptr, nan, eq, src1, src2);
2705  }
2706  if (kArchVariant >= kMips64r6) {
2707    max_d(dst, src1, src2);
2708  } else {
2709    Label skip;
2710    if (!ZeroHelper_d(this, MaxMinKind::kMax, dst, src1, src2, &skip)) {
2711      if (dst.is(src1)) {
2712        BranchF64(&skip, nullptr, ge, src1, src2);
2713        Move_d(dst, src2);
2714      } else if (dst.is(src2)) {
2715        BranchF64(&skip, nullptr, le, src1, src2);
2716        Move_d(dst, src1);
2717      } else {
2718        Label right;
2719        BranchF64(&right, nullptr, lt, src1, src2);
2720        Move_d(dst, src1);
2721        Branch(&skip);
2722        bind(&right);
2723        Move_d(dst, src2);
2724      }
2725    }
2726    bind(&skip);
2727  }
2728}
2729
2730void MacroAssembler::MinNaNCheck_s(FPURegister dst, FPURegister src1,
2731                                   FPURegister src2, Label* nan) {
2732  if (nan) {
2733    BranchF32(nullptr, nan, eq, src1, src2);
2734  }
2735  if (kArchVariant >= kMips64r6) {
2736    min_s(dst, src1, src2);
2737  } else {
2738    Label skip;
2739    if (!ZeroHelper_s(this, MaxMinKind::kMin, dst, src1, src2, &skip)) {
2740      if (dst.is(src1)) {
2741        BranchF32(&skip, nullptr, le, src1, src2);
2742        Move_s(dst, src2);
2743      } else if (dst.is(src2)) {
2744        BranchF32(&skip, nullptr, ge, src1, src2);
2745        Move_s(dst, src1);
2746      } else {
2747        Label right;
2748        BranchF32(&right, nullptr, gt, src1, src2);
2749        Move_s(dst, src1);
2750        Branch(&skip);
2751        bind(&right);
2752        Move_s(dst, src2);
2753      }
2754    }
2755    bind(&skip);
2756  }
2757}
2758
2759void MacroAssembler::MaxNaNCheck_s(FPURegister dst, FPURegister src1,
2760                                   FPURegister src2, Label* nan) {
2761  if (nan) {
2762    BranchF32(nullptr, nan, eq, src1, src2);
2763  }
2764  if (kArchVariant >= kMips64r6) {
2765    max_s(dst, src1, src2);
2766  } else {
2767    Label skip;
2768    if (!ZeroHelper_s(this, MaxMinKind::kMax, dst, src1, src2, &skip)) {
2769      if (dst.is(src1)) {
2770        BranchF32(&skip, nullptr, ge, src1, src2);
2771        Move_s(dst, src2);
2772      } else if (dst.is(src2)) {
2773        BranchF32(&skip, nullptr, le, src1, src2);
2774        Move_s(dst, src1);
2775      } else {
2776        Label right;
2777        BranchF32(&right, nullptr, lt, src1, src2);
2778        Move_s(dst, src1);
2779        Branch(&skip);
2780        bind(&right);
2781        Move_s(dst, src2);
2782      }
2783    }
2784    bind(&skip);
2785  }
2786}
2787
2788void MacroAssembler::Clz(Register rd, Register rs) {
2789  clz(rd, rs);
2790}
2791
2792
2793void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
2794                                     Register result,
2795                                     DoubleRegister double_input,
2796                                     Register scratch,
2797                                     DoubleRegister double_scratch,
2798                                     Register except_flag,
2799                                     CheckForInexactConversion check_inexact) {
2800  DCHECK(!result.is(scratch));
2801  DCHECK(!double_input.is(double_scratch));
2802  DCHECK(!except_flag.is(scratch));
2803
2804  Label done;
2805
2806  // Clear the except flag (0 = no exception)
2807  mov(except_flag, zero_reg);
2808
2809  // Test for values that can be exactly represented as a signed 32-bit integer.
2810  cvt_w_d(double_scratch, double_input);
2811  mfc1(result, double_scratch);
2812  cvt_d_w(double_scratch, double_scratch);
2813  BranchF(&done, NULL, eq, double_input, double_scratch);
2814
2815  int32_t except_mask = kFCSRFlagMask;  // Assume interested in all exceptions.
2816
2817  if (check_inexact == kDontCheckForInexactConversion) {
2818    // Ignore inexact exceptions.
2819    except_mask &= ~kFCSRInexactFlagMask;
2820  }
2821
2822  // Save FCSR.
2823  cfc1(scratch, FCSR);
2824  // Disable FPU exceptions.
2825  ctc1(zero_reg, FCSR);
2826
2827  // Do operation based on rounding mode.
2828  switch (rounding_mode) {
2829    case kRoundToNearest:
2830      Round_w_d(double_scratch, double_input);
2831      break;
2832    case kRoundToZero:
2833      Trunc_w_d(double_scratch, double_input);
2834      break;
2835    case kRoundToPlusInf:
2836      Ceil_w_d(double_scratch, double_input);
2837      break;
2838    case kRoundToMinusInf:
2839      Floor_w_d(double_scratch, double_input);
2840      break;
2841  }  // End of switch-statement.
2842
2843  // Retrieve FCSR.
2844  cfc1(except_flag, FCSR);
2845  // Restore FCSR.
2846  ctc1(scratch, FCSR);
2847  // Move the converted value into the result register.
2848  mfc1(result, double_scratch);
2849
2850  // Check for fpu exceptions.
2851  And(except_flag, except_flag, Operand(except_mask));
2852
2853  bind(&done);
2854}
2855
2856
2857void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
2858                                                DoubleRegister double_input,
2859                                                Label* done) {
2860  DoubleRegister single_scratch = kLithiumScratchDouble.low();
2861  Register scratch = at;
2862  Register scratch2 = t9;
2863
2864  // Clear cumulative exception flags and save the FCSR.
2865  cfc1(scratch2, FCSR);
2866  ctc1(zero_reg, FCSR);
2867  // Try a conversion to a signed integer.
2868  trunc_w_d(single_scratch, double_input);
2869  mfc1(result, single_scratch);
2870  // Retrieve and restore the FCSR.
2871  cfc1(scratch, FCSR);
2872  ctc1(scratch2, FCSR);
2873  // Check for overflow and NaNs.
2874  And(scratch,
2875      scratch,
2876      kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask);
2877  // If we had no exceptions we are done.
2878  Branch(done, eq, scratch, Operand(zero_reg));
2879}
2880
2881
2882void MacroAssembler::TruncateDoubleToI(Register result,
2883                                       DoubleRegister double_input) {
2884  Label done;
2885
2886  TryInlineTruncateDoubleToI(result, double_input, &done);
2887
2888  // If we fell through then inline version didn't succeed - call stub instead.
2889  push(ra);
2890  Dsubu(sp, sp, Operand(kDoubleSize));  // Put input on stack.
2891  sdc1(double_input, MemOperand(sp, 0));
2892
2893  DoubleToIStub stub(isolate(), sp, result, 0, true, true);
2894  CallStub(&stub);
2895
2896  Daddu(sp, sp, Operand(kDoubleSize));
2897  pop(ra);
2898
2899  bind(&done);
2900}
2901
2902
2903void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) {
2904  Label done;
2905  DoubleRegister double_scratch = f12;
2906  DCHECK(!result.is(object));
2907
2908  ldc1(double_scratch,
2909       MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag));
2910  TryInlineTruncateDoubleToI(result, double_scratch, &done);
2911
2912  // If we fell through then inline version didn't succeed - call stub instead.
2913  push(ra);
2914  DoubleToIStub stub(isolate(),
2915                     object,
2916                     result,
2917                     HeapNumber::kValueOffset - kHeapObjectTag,
2918                     true,
2919                     true);
2920  CallStub(&stub);
2921  pop(ra);
2922
2923  bind(&done);
2924}
2925
2926
2927void MacroAssembler::TruncateNumberToI(Register object,
2928                                       Register result,
2929                                       Register heap_number_map,
2930                                       Register scratch,
2931                                       Label* not_number) {
2932  Label done;
2933  DCHECK(!result.is(object));
2934
2935  UntagAndJumpIfSmi(result, object, &done);
2936  JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number);
2937  TruncateHeapNumberToI(result, object);
2938
2939  bind(&done);
2940}
2941
2942
2943void MacroAssembler::GetLeastBitsFromSmi(Register dst,
2944                                         Register src,
2945                                         int num_least_bits) {
2946  // Ext(dst, src, kSmiTagSize, num_least_bits);
2947  SmiUntag(dst, src);
2948  And(dst, dst, Operand((1 << num_least_bits) - 1));
2949}
2950
2951
2952void MacroAssembler::GetLeastBitsFromInt32(Register dst,
2953                                           Register src,
2954                                           int num_least_bits) {
2955  DCHECK(!src.is(dst));
2956  And(dst, src, Operand((1 << num_least_bits) - 1));
2957}
2958
2959
2960// Emulated condtional branches do not emit a nop in the branch delay slot.
2961//
2962// BRANCH_ARGS_CHECK checks that conditional jump arguments are correct.
2963#define BRANCH_ARGS_CHECK(cond, rs, rt) DCHECK(                                \
2964    (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) ||          \
2965    (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg))))
2966
2967
2968void MacroAssembler::Branch(int32_t offset, BranchDelaySlot bdslot) {
2969  DCHECK(kArchVariant == kMips64r6 ? is_int26(offset) : is_int16(offset));
2970  BranchShort(offset, bdslot);
2971}
2972
2973
2974void MacroAssembler::Branch(int32_t offset, Condition cond, Register rs,
2975                            const Operand& rt, BranchDelaySlot bdslot) {
2976  bool is_near = BranchShortCheck(offset, nullptr, cond, rs, rt, bdslot);
2977  DCHECK(is_near);
2978  USE(is_near);
2979}
2980
2981
2982void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) {
2983  if (L->is_bound()) {
2984    if (is_near_branch(L)) {
2985      BranchShort(L, bdslot);
2986    } else {
2987      BranchLong(L, bdslot);
2988    }
2989  } else {
2990    if (is_trampoline_emitted()) {
2991      BranchLong(L, bdslot);
2992    } else {
2993      BranchShort(L, bdslot);
2994    }
2995  }
2996}
2997
2998
2999void MacroAssembler::Branch(Label* L, Condition cond, Register rs,
3000                            const Operand& rt,
3001                            BranchDelaySlot bdslot) {
3002  if (L->is_bound()) {
3003    if (!BranchShortCheck(0, L, cond, rs, rt, bdslot)) {
3004      if (cond != cc_always) {
3005        Label skip;
3006        Condition neg_cond = NegateCondition(cond);
3007        BranchShort(&skip, neg_cond, rs, rt);
3008        BranchLong(L, bdslot);
3009        bind(&skip);
3010      } else {
3011        BranchLong(L, bdslot);
3012      }
3013    }
3014  } else {
3015    if (is_trampoline_emitted()) {
3016      if (cond != cc_always) {
3017        Label skip;
3018        Condition neg_cond = NegateCondition(cond);
3019        BranchShort(&skip, neg_cond, rs, rt);
3020        BranchLong(L, bdslot);
3021        bind(&skip);
3022      } else {
3023        BranchLong(L, bdslot);
3024      }
3025    } else {
3026      BranchShort(L, cond, rs, rt, bdslot);
3027    }
3028  }
3029}
3030
3031
3032void MacroAssembler::Branch(Label* L,
3033                            Condition cond,
3034                            Register rs,
3035                            Heap::RootListIndex index,
3036                            BranchDelaySlot bdslot) {
3037  LoadRoot(at, index);
3038  Branch(L, cond, rs, Operand(at), bdslot);
3039}
3040
3041
3042void MacroAssembler::BranchShortHelper(int16_t offset, Label* L,
3043                                       BranchDelaySlot bdslot) {
3044  DCHECK(L == nullptr || offset == 0);
3045  offset = GetOffset(offset, L, OffsetSize::kOffset16);
3046  b(offset);
3047
3048  // Emit a nop in the branch delay slot if required.
3049  if (bdslot == PROTECT)
3050    nop();
3051}
3052
3053
3054void MacroAssembler::BranchShortHelperR6(int32_t offset, Label* L) {
3055  DCHECK(L == nullptr || offset == 0);
3056  offset = GetOffset(offset, L, OffsetSize::kOffset26);
3057  bc(offset);
3058}
3059
3060
3061void MacroAssembler::BranchShort(int32_t offset, BranchDelaySlot bdslot) {
3062  if (kArchVariant == kMips64r6 && bdslot == PROTECT) {
3063    DCHECK(is_int26(offset));
3064    BranchShortHelperR6(offset, nullptr);
3065  } else {
3066    DCHECK(is_int16(offset));
3067    BranchShortHelper(offset, nullptr, bdslot);
3068  }
3069}
3070
3071
3072void MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) {
3073  if (kArchVariant == kMips64r6 && bdslot == PROTECT) {
3074    BranchShortHelperR6(0, L);
3075  } else {
3076    BranchShortHelper(0, L, bdslot);
3077  }
3078}
3079
3080
3081static inline bool IsZero(const Operand& rt) {
3082  if (rt.is_reg()) {
3083    return rt.rm().is(zero_reg);
3084  } else {
3085    return rt.immediate() == 0;
3086  }
3087}
3088
3089
3090int32_t MacroAssembler::GetOffset(int32_t offset, Label* L, OffsetSize bits) {
3091  if (L) {
3092    offset = branch_offset_helper(L, bits) >> 2;
3093  } else {
3094    DCHECK(is_intn(offset, bits));
3095  }
3096  return offset;
3097}
3098
3099
3100Register MacroAssembler::GetRtAsRegisterHelper(const Operand& rt,
3101                                               Register scratch) {
3102  Register r2 = no_reg;
3103  if (rt.is_reg()) {
3104    r2 = rt.rm_;
3105  } else {
3106    r2 = scratch;
3107    li(r2, rt);
3108  }
3109
3110  return r2;
3111}
3112
3113
3114bool MacroAssembler::BranchShortHelperR6(int32_t offset, Label* L,
3115                                         Condition cond, Register rs,
3116                                         const Operand& rt) {
3117  DCHECK(L == nullptr || offset == 0);
3118  Register scratch = rs.is(at) ? t8 : at;
3119  OffsetSize bits = OffsetSize::kOffset16;
3120
3121  // Be careful to always use shifted_branch_offset only just before the
3122  // branch instruction, as the location will be remember for patching the
3123  // target.
3124  {
3125    BlockTrampolinePoolScope block_trampoline_pool(this);
3126    switch (cond) {
3127      case cc_always:
3128        bits = OffsetSize::kOffset26;
3129        if (!is_near(L, bits)) return false;
3130        offset = GetOffset(offset, L, bits);
3131        bc(offset);
3132        break;
3133      case eq:
3134        if (rs.code() == rt.rm_.reg_code) {
3135          // Pre R6 beq is used here to make the code patchable. Otherwise bc
3136          // should be used which has no condition field so is not patchable.
3137          bits = OffsetSize::kOffset16;
3138          if (!is_near(L, bits)) return false;
3139          scratch = GetRtAsRegisterHelper(rt, scratch);
3140          offset = GetOffset(offset, L, bits);
3141          beq(rs, scratch, offset);
3142          nop();
3143        } else if (IsZero(rt)) {
3144          bits = OffsetSize::kOffset21;
3145          if (!is_near(L, bits)) return false;
3146          offset = GetOffset(offset, L, bits);
3147          beqzc(rs, offset);
3148        } else {
3149          // We don't want any other register but scratch clobbered.
3150          bits = OffsetSize::kOffset16;
3151          if (!is_near(L, bits)) return false;
3152          scratch = GetRtAsRegisterHelper(rt, scratch);
3153          offset = GetOffset(offset, L, bits);
3154          beqc(rs, scratch, offset);
3155        }
3156        break;
3157      case ne:
3158        if (rs.code() == rt.rm_.reg_code) {
3159          // Pre R6 bne is used here to make the code patchable. Otherwise we
3160          // should not generate any instruction.
3161          bits = OffsetSize::kOffset16;
3162          if (!is_near(L, bits)) return false;
3163          scratch = GetRtAsRegisterHelper(rt, scratch);
3164          offset = GetOffset(offset, L, bits);
3165          bne(rs, scratch, offset);
3166          nop();
3167        } else if (IsZero(rt)) {
3168          bits = OffsetSize::kOffset21;
3169          if (!is_near(L, bits)) return false;
3170          offset = GetOffset(offset, L, bits);
3171          bnezc(rs, offset);
3172        } else {
3173          // We don't want any other register but scratch clobbered.
3174          bits = OffsetSize::kOffset16;
3175          if (!is_near(L, bits)) return false;
3176          scratch = GetRtAsRegisterHelper(rt, scratch);
3177          offset = GetOffset(offset, L, bits);
3178          bnec(rs, scratch, offset);
3179        }
3180        break;
3181
3182      // Signed comparison.
3183      case greater:
3184        // rs > rt
3185        if (rs.code() == rt.rm_.reg_code) {
3186          break;  // No code needs to be emitted.
3187        } else if (rs.is(zero_reg)) {
3188          bits = OffsetSize::kOffset16;
3189          if (!is_near(L, bits)) return false;
3190          scratch = GetRtAsRegisterHelper(rt, scratch);
3191          offset = GetOffset(offset, L, bits);
3192          bltzc(scratch, offset);
3193        } else if (IsZero(rt)) {
3194          bits = OffsetSize::kOffset16;
3195          if (!is_near(L, bits)) return false;
3196          offset = GetOffset(offset, L, bits);
3197          bgtzc(rs, offset);
3198        } else {
3199          bits = OffsetSize::kOffset16;
3200          if (!is_near(L, bits)) return false;
3201          scratch = GetRtAsRegisterHelper(rt, scratch);
3202          DCHECK(!rs.is(scratch));
3203          offset = GetOffset(offset, L, bits);
3204          bltc(scratch, rs, offset);
3205        }
3206        break;
3207      case greater_equal:
3208        // rs >= rt
3209        if (rs.code() == rt.rm_.reg_code) {
3210          bits = OffsetSize::kOffset26;
3211          if (!is_near(L, bits)) return false;
3212          offset = GetOffset(offset, L, bits);
3213          bc(offset);
3214        } else if (rs.is(zero_reg)) {
3215          bits = OffsetSize::kOffset16;
3216          if (!is_near(L, bits)) return false;
3217          scratch = GetRtAsRegisterHelper(rt, scratch);
3218          offset = GetOffset(offset, L, bits);
3219          blezc(scratch, offset);
3220        } else if (IsZero(rt)) {
3221          bits = OffsetSize::kOffset16;
3222          if (!is_near(L, bits)) return false;
3223          offset = GetOffset(offset, L, bits);
3224          bgezc(rs, offset);
3225        } else {
3226          bits = OffsetSize::kOffset16;
3227          if (!is_near(L, bits)) return false;
3228          scratch = GetRtAsRegisterHelper(rt, scratch);
3229          DCHECK(!rs.is(scratch));
3230          offset = GetOffset(offset, L, bits);
3231          bgec(rs, scratch, offset);
3232        }
3233        break;
3234      case less:
3235        // rs < rt
3236        if (rs.code() == rt.rm_.reg_code) {
3237          break;  // No code needs to be emitted.
3238        } else if (rs.is(zero_reg)) {
3239          bits = OffsetSize::kOffset16;
3240          if (!is_near(L, bits)) return false;
3241          scratch = GetRtAsRegisterHelper(rt, scratch);
3242          offset = GetOffset(offset, L, bits);
3243          bgtzc(scratch, offset);
3244        } else if (IsZero(rt)) {
3245          bits = OffsetSize::kOffset16;
3246          if (!is_near(L, bits)) return false;
3247          offset = GetOffset(offset, L, bits);
3248          bltzc(rs, offset);
3249        } else {
3250          bits = OffsetSize::kOffset16;
3251          if (!is_near(L, bits)) return false;
3252          scratch = GetRtAsRegisterHelper(rt, scratch);
3253          DCHECK(!rs.is(scratch));
3254          offset = GetOffset(offset, L, bits);
3255          bltc(rs, scratch, offset);
3256        }
3257        break;
3258      case less_equal:
3259        // rs <= rt
3260        if (rs.code() == rt.rm_.reg_code) {
3261          bits = OffsetSize::kOffset26;
3262          if (!is_near(L, bits)) return false;
3263          offset = GetOffset(offset, L, bits);
3264          bc(offset);
3265        } else if (rs.is(zero_reg)) {
3266          bits = OffsetSize::kOffset16;
3267          if (!is_near(L, bits)) return false;
3268          scratch = GetRtAsRegisterHelper(rt, scratch);
3269          offset = GetOffset(offset, L, bits);
3270          bgezc(scratch, offset);
3271        } else if (IsZero(rt)) {
3272          bits = OffsetSize::kOffset16;
3273          if (!is_near(L, bits)) return false;
3274          offset = GetOffset(offset, L, bits);
3275          blezc(rs, offset);
3276        } else {
3277          bits = OffsetSize::kOffset16;
3278          if (!is_near(L, bits)) return false;
3279          scratch = GetRtAsRegisterHelper(rt, scratch);
3280          DCHECK(!rs.is(scratch));
3281          offset = GetOffset(offset, L, bits);
3282          bgec(scratch, rs, offset);
3283        }
3284        break;
3285
3286      // Unsigned comparison.
3287      case Ugreater:
3288        // rs > rt
3289        if (rs.code() == rt.rm_.reg_code) {
3290          break;  // No code needs to be emitted.
3291        } else if (rs.is(zero_reg)) {
3292          bits = OffsetSize::kOffset21;
3293          if (!is_near(L, bits)) return false;
3294          scratch = GetRtAsRegisterHelper(rt, scratch);
3295          offset = GetOffset(offset, L, bits);
3296          bnezc(scratch, offset);
3297        } else if (IsZero(rt)) {
3298          bits = OffsetSize::kOffset21;
3299          if (!is_near(L, bits)) return false;
3300          offset = GetOffset(offset, L, bits);
3301          bnezc(rs, offset);
3302        } else {
3303          bits = OffsetSize::kOffset16;
3304          if (!is_near(L, bits)) return false;
3305          scratch = GetRtAsRegisterHelper(rt, scratch);
3306          DCHECK(!rs.is(scratch));
3307          offset = GetOffset(offset, L, bits);
3308          bltuc(scratch, rs, offset);
3309        }
3310        break;
3311      case Ugreater_equal:
3312        // rs >= rt
3313        if (rs.code() == rt.rm_.reg_code) {
3314          bits = OffsetSize::kOffset26;
3315          if (!is_near(L, bits)) return false;
3316          offset = GetOffset(offset, L, bits);
3317          bc(offset);
3318        } else if (rs.is(zero_reg)) {
3319          bits = OffsetSize::kOffset21;
3320          if (!is_near(L, bits)) return false;
3321          scratch = GetRtAsRegisterHelper(rt, scratch);
3322          offset = GetOffset(offset, L, bits);
3323          beqzc(scratch, offset);
3324        } else if (IsZero(rt)) {
3325          bits = OffsetSize::kOffset26;
3326          if (!is_near(L, bits)) return false;
3327          offset = GetOffset(offset, L, bits);
3328          bc(offset);
3329        } else {
3330          bits = OffsetSize::kOffset16;
3331          if (!is_near(L, bits)) return false;
3332          scratch = GetRtAsRegisterHelper(rt, scratch);
3333          DCHECK(!rs.is(scratch));
3334          offset = GetOffset(offset, L, bits);
3335          bgeuc(rs, scratch, offset);
3336        }
3337        break;
3338      case Uless:
3339        // rs < rt
3340        if (rs.code() == rt.rm_.reg_code) {
3341          break;  // No code needs to be emitted.
3342        } else if (rs.is(zero_reg)) {
3343          bits = OffsetSize::kOffset21;
3344          if (!is_near(L, bits)) return false;
3345          scratch = GetRtAsRegisterHelper(rt, scratch);
3346          offset = GetOffset(offset, L, bits);
3347          bnezc(scratch, offset);
3348        } else if (IsZero(rt)) {
3349          break;  // No code needs to be emitted.
3350        } else {
3351          bits = OffsetSize::kOffset16;
3352          if (!is_near(L, bits)) return false;
3353          scratch = GetRtAsRegisterHelper(rt, scratch);
3354          DCHECK(!rs.is(scratch));
3355          offset = GetOffset(offset, L, bits);
3356          bltuc(rs, scratch, offset);
3357        }
3358        break;
3359      case Uless_equal:
3360        // rs <= rt
3361        if (rs.code() == rt.rm_.reg_code) {
3362          bits = OffsetSize::kOffset26;
3363          if (!is_near(L, bits)) return false;
3364          offset = GetOffset(offset, L, bits);
3365          bc(offset);
3366        } else if (rs.is(zero_reg)) {
3367          bits = OffsetSize::kOffset26;
3368          if (!is_near(L, bits)) return false;
3369          scratch = GetRtAsRegisterHelper(rt, scratch);
3370          offset = GetOffset(offset, L, bits);
3371          bc(offset);
3372        } else if (IsZero(rt)) {
3373          bits = OffsetSize::kOffset21;
3374          if (!is_near(L, bits)) return false;
3375          offset = GetOffset(offset, L, bits);
3376          beqzc(rs, offset);
3377        } else {
3378          bits = OffsetSize::kOffset16;
3379          if (!is_near(L, bits)) return false;
3380          scratch = GetRtAsRegisterHelper(rt, scratch);
3381          DCHECK(!rs.is(scratch));
3382          offset = GetOffset(offset, L, bits);
3383          bgeuc(scratch, rs, offset);
3384        }
3385        break;
3386      default:
3387        UNREACHABLE();
3388    }
3389  }
3390  CheckTrampolinePoolQuick(1);
3391  return true;
3392}
3393
3394
3395bool MacroAssembler::BranchShortHelper(int16_t offset, Label* L, Condition cond,
3396                                       Register rs, const Operand& rt,
3397                                       BranchDelaySlot bdslot) {
3398  DCHECK(L == nullptr || offset == 0);
3399  if (!is_near(L, OffsetSize::kOffset16)) return false;
3400
3401  Register scratch = at;
3402  int32_t offset32;
3403
3404  // Be careful to always use shifted_branch_offset only just before the
3405  // branch instruction, as the location will be remember for patching the
3406  // target.
3407  {
3408    BlockTrampolinePoolScope block_trampoline_pool(this);
3409    switch (cond) {
3410      case cc_always:
3411        offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3412        b(offset32);
3413        break;
3414      case eq:
3415        if (IsZero(rt)) {
3416          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3417          beq(rs, zero_reg, offset32);
3418        } else {
3419          // We don't want any other register but scratch clobbered.
3420          scratch = GetRtAsRegisterHelper(rt, scratch);
3421          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3422          beq(rs, scratch, offset32);
3423        }
3424        break;
3425      case ne:
3426        if (IsZero(rt)) {
3427          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3428          bne(rs, zero_reg, offset32);
3429        } else {
3430          // We don't want any other register but scratch clobbered.
3431          scratch = GetRtAsRegisterHelper(rt, scratch);
3432          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3433          bne(rs, scratch, offset32);
3434        }
3435        break;
3436
3437      // Signed comparison.
3438      case greater:
3439        if (IsZero(rt)) {
3440          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3441          bgtz(rs, offset32);
3442        } else {
3443          Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3444          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3445          bne(scratch, zero_reg, offset32);
3446        }
3447        break;
3448      case greater_equal:
3449        if (IsZero(rt)) {
3450          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3451          bgez(rs, offset32);
3452        } else {
3453          Slt(scratch, rs, rt);
3454          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3455          beq(scratch, zero_reg, offset32);
3456        }
3457        break;
3458      case less:
3459        if (IsZero(rt)) {
3460          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3461          bltz(rs, offset32);
3462        } else {
3463          Slt(scratch, rs, rt);
3464          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3465          bne(scratch, zero_reg, offset32);
3466        }
3467        break;
3468      case less_equal:
3469        if (IsZero(rt)) {
3470          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3471          blez(rs, offset32);
3472        } else {
3473          Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3474          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3475          beq(scratch, zero_reg, offset32);
3476        }
3477        break;
3478
3479      // Unsigned comparison.
3480      case Ugreater:
3481        if (IsZero(rt)) {
3482          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3483          bne(rs, zero_reg, offset32);
3484        } else {
3485          Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3486          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3487          bne(scratch, zero_reg, offset32);
3488        }
3489        break;
3490      case Ugreater_equal:
3491        if (IsZero(rt)) {
3492          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3493          b(offset32);
3494        } else {
3495          Sltu(scratch, rs, rt);
3496          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3497          beq(scratch, zero_reg, offset32);
3498        }
3499        break;
3500      case Uless:
3501        if (IsZero(rt)) {
3502          return true;  // No code needs to be emitted.
3503        } else {
3504          Sltu(scratch, rs, rt);
3505          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3506          bne(scratch, zero_reg, offset32);
3507        }
3508        break;
3509      case Uless_equal:
3510        if (IsZero(rt)) {
3511          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3512          beq(rs, zero_reg, offset32);
3513        } else {
3514          Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3515          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3516          beq(scratch, zero_reg, offset32);
3517        }
3518        break;
3519      default:
3520        UNREACHABLE();
3521    }
3522  }
3523
3524  // Emit a nop in the branch delay slot if required.
3525  if (bdslot == PROTECT)
3526    nop();
3527
3528  return true;
3529}
3530
3531
3532bool MacroAssembler::BranchShortCheck(int32_t offset, Label* L, Condition cond,
3533                                      Register rs, const Operand& rt,
3534                                      BranchDelaySlot bdslot) {
3535  BRANCH_ARGS_CHECK(cond, rs, rt);
3536
3537  if (!L) {
3538    if (kArchVariant == kMips64r6 && bdslot == PROTECT) {
3539      DCHECK(is_int26(offset));
3540      return BranchShortHelperR6(offset, nullptr, cond, rs, rt);
3541    } else {
3542      DCHECK(is_int16(offset));
3543      return BranchShortHelper(offset, nullptr, cond, rs, rt, bdslot);
3544    }
3545  } else {
3546    DCHECK(offset == 0);
3547    if (kArchVariant == kMips64r6 && bdslot == PROTECT) {
3548      return BranchShortHelperR6(0, L, cond, rs, rt);
3549    } else {
3550      return BranchShortHelper(0, L, cond, rs, rt, bdslot);
3551    }
3552  }
3553  return false;
3554}
3555
3556
3557void MacroAssembler::BranchShort(int32_t offset, Condition cond, Register rs,
3558                                 const Operand& rt, BranchDelaySlot bdslot) {
3559  BranchShortCheck(offset, nullptr, cond, rs, rt, bdslot);
3560}
3561
3562
3563void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
3564                                 const Operand& rt, BranchDelaySlot bdslot) {
3565  BranchShortCheck(0, L, cond, rs, rt, bdslot);
3566}
3567
3568
3569void MacroAssembler::BranchAndLink(int32_t offset, BranchDelaySlot bdslot) {
3570  BranchAndLinkShort(offset, bdslot);
3571}
3572
3573
3574void MacroAssembler::BranchAndLink(int32_t offset, Condition cond, Register rs,
3575                                   const Operand& rt, BranchDelaySlot bdslot) {
3576  bool is_near = BranchAndLinkShortCheck(offset, nullptr, cond, rs, rt, bdslot);
3577  DCHECK(is_near);
3578  USE(is_near);
3579}
3580
3581
3582void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) {
3583  if (L->is_bound()) {
3584    if (is_near_branch(L)) {
3585      BranchAndLinkShort(L, bdslot);
3586    } else {
3587      BranchAndLinkLong(L, bdslot);
3588    }
3589  } else {
3590    if (is_trampoline_emitted()) {
3591      BranchAndLinkLong(L, bdslot);
3592    } else {
3593      BranchAndLinkShort(L, bdslot);
3594    }
3595  }
3596}
3597
3598
3599void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs,
3600                                   const Operand& rt,
3601                                   BranchDelaySlot bdslot) {
3602  if (L->is_bound()) {
3603    if (!BranchAndLinkShortCheck(0, L, cond, rs, rt, bdslot)) {
3604      Label skip;
3605      Condition neg_cond = NegateCondition(cond);
3606      BranchShort(&skip, neg_cond, rs, rt);
3607      BranchAndLinkLong(L, bdslot);
3608      bind(&skip);
3609    }
3610  } else {
3611    if (is_trampoline_emitted()) {
3612      Label skip;
3613      Condition neg_cond = NegateCondition(cond);
3614      BranchShort(&skip, neg_cond, rs, rt);
3615      BranchAndLinkLong(L, bdslot);
3616      bind(&skip);
3617    } else {
3618      BranchAndLinkShortCheck(0, L, cond, rs, rt, bdslot);
3619    }
3620  }
3621}
3622
3623
3624void MacroAssembler::BranchAndLinkShortHelper(int16_t offset, Label* L,
3625                                              BranchDelaySlot bdslot) {
3626  DCHECK(L == nullptr || offset == 0);
3627  offset = GetOffset(offset, L, OffsetSize::kOffset16);
3628  bal(offset);
3629
3630  // Emit a nop in the branch delay slot if required.
3631  if (bdslot == PROTECT)
3632    nop();
3633}
3634
3635
3636void MacroAssembler::BranchAndLinkShortHelperR6(int32_t offset, Label* L) {
3637  DCHECK(L == nullptr || offset == 0);
3638  offset = GetOffset(offset, L, OffsetSize::kOffset26);
3639  balc(offset);
3640}
3641
3642
3643void MacroAssembler::BranchAndLinkShort(int32_t offset,
3644                                        BranchDelaySlot bdslot) {
3645  if (kArchVariant == kMips64r6 && bdslot == PROTECT) {
3646    DCHECK(is_int26(offset));
3647    BranchAndLinkShortHelperR6(offset, nullptr);
3648  } else {
3649    DCHECK(is_int16(offset));
3650    BranchAndLinkShortHelper(offset, nullptr, bdslot);
3651  }
3652}
3653
3654
3655void MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) {
3656  if (kArchVariant == kMips64r6 && bdslot == PROTECT) {
3657    BranchAndLinkShortHelperR6(0, L);
3658  } else {
3659    BranchAndLinkShortHelper(0, L, bdslot);
3660  }
3661}
3662
3663
3664bool MacroAssembler::BranchAndLinkShortHelperR6(int32_t offset, Label* L,
3665                                                Condition cond, Register rs,
3666                                                const Operand& rt) {
3667  DCHECK(L == nullptr || offset == 0);
3668  Register scratch = rs.is(at) ? t8 : at;
3669  OffsetSize bits = OffsetSize::kOffset16;
3670
3671  BlockTrampolinePoolScope block_trampoline_pool(this);
3672  DCHECK((cond == cc_always && is_int26(offset)) || is_int16(offset));
3673  switch (cond) {
3674    case cc_always:
3675      bits = OffsetSize::kOffset26;
3676      if (!is_near(L, bits)) return false;
3677      offset = GetOffset(offset, L, bits);
3678      balc(offset);
3679      break;
3680    case eq:
3681      if (!is_near(L, bits)) return false;
3682      Subu(scratch, rs, rt);
3683      offset = GetOffset(offset, L, bits);
3684      beqzalc(scratch, offset);
3685      break;
3686    case ne:
3687      if (!is_near(L, bits)) return false;
3688      Subu(scratch, rs, rt);
3689      offset = GetOffset(offset, L, bits);
3690      bnezalc(scratch, offset);
3691      break;
3692
3693    // Signed comparison.
3694    case greater:
3695      // rs > rt
3696      if (rs.code() == rt.rm_.reg_code) {
3697        break;  // No code needs to be emitted.
3698      } else if (rs.is(zero_reg)) {
3699        if (!is_near(L, bits)) return false;
3700        scratch = GetRtAsRegisterHelper(rt, scratch);
3701        offset = GetOffset(offset, L, bits);
3702        bltzalc(scratch, offset);
3703      } else if (IsZero(rt)) {
3704        if (!is_near(L, bits)) return false;
3705        offset = GetOffset(offset, L, bits);
3706        bgtzalc(rs, offset);
3707      } else {
3708        if (!is_near(L, bits)) return false;
3709        Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3710        offset = GetOffset(offset, L, bits);
3711        bnezalc(scratch, offset);
3712      }
3713      break;
3714    case greater_equal:
3715      // rs >= rt
3716      if (rs.code() == rt.rm_.reg_code) {
3717        bits = OffsetSize::kOffset26;
3718        if (!is_near(L, bits)) return false;
3719        offset = GetOffset(offset, L, bits);
3720        balc(offset);
3721      } else if (rs.is(zero_reg)) {
3722        if (!is_near(L, bits)) return false;
3723        scratch = GetRtAsRegisterHelper(rt, scratch);
3724        offset = GetOffset(offset, L, bits);
3725        blezalc(scratch, offset);
3726      } else if (IsZero(rt)) {
3727        if (!is_near(L, bits)) return false;
3728        offset = GetOffset(offset, L, bits);
3729        bgezalc(rs, offset);
3730      } else {
3731        if (!is_near(L, bits)) return false;
3732        Slt(scratch, rs, rt);
3733        offset = GetOffset(offset, L, bits);
3734        beqzalc(scratch, offset);
3735      }
3736      break;
3737    case less:
3738      // rs < rt
3739      if (rs.code() == rt.rm_.reg_code) {
3740        break;  // No code needs to be emitted.
3741      } else if (rs.is(zero_reg)) {
3742        if (!is_near(L, bits)) return false;
3743        scratch = GetRtAsRegisterHelper(rt, scratch);
3744        offset = GetOffset(offset, L, bits);
3745        bgtzalc(scratch, offset);
3746      } else if (IsZero(rt)) {
3747        if (!is_near(L, bits)) return false;
3748        offset = GetOffset(offset, L, bits);
3749        bltzalc(rs, offset);
3750      } else {
3751        if (!is_near(L, bits)) return false;
3752        Slt(scratch, rs, rt);
3753        offset = GetOffset(offset, L, bits);
3754        bnezalc(scratch, offset);
3755      }
3756      break;
3757    case less_equal:
3758      // rs <= r2
3759      if (rs.code() == rt.rm_.reg_code) {
3760        bits = OffsetSize::kOffset26;
3761        if (!is_near(L, bits)) return false;
3762        offset = GetOffset(offset, L, bits);
3763        balc(offset);
3764      } else if (rs.is(zero_reg)) {
3765        if (!is_near(L, bits)) return false;
3766        scratch = GetRtAsRegisterHelper(rt, scratch);
3767        offset = GetOffset(offset, L, bits);
3768        bgezalc(scratch, offset);
3769      } else if (IsZero(rt)) {
3770        if (!is_near(L, bits)) return false;
3771        offset = GetOffset(offset, L, bits);
3772        blezalc(rs, offset);
3773      } else {
3774        if (!is_near(L, bits)) return false;
3775        Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3776        offset = GetOffset(offset, L, bits);
3777        beqzalc(scratch, offset);
3778      }
3779      break;
3780
3781
3782    // Unsigned comparison.
3783    case Ugreater:
3784      // rs > r2
3785      if (!is_near(L, bits)) return false;
3786      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3787      offset = GetOffset(offset, L, bits);
3788      bnezalc(scratch, offset);
3789      break;
3790    case Ugreater_equal:
3791      // rs >= r2
3792      if (!is_near(L, bits)) return false;
3793      Sltu(scratch, rs, rt);
3794      offset = GetOffset(offset, L, bits);
3795      beqzalc(scratch, offset);
3796      break;
3797    case Uless:
3798      // rs < r2
3799      if (!is_near(L, bits)) return false;
3800      Sltu(scratch, rs, rt);
3801      offset = GetOffset(offset, L, bits);
3802      bnezalc(scratch, offset);
3803      break;
3804    case Uless_equal:
3805      // rs <= r2
3806      if (!is_near(L, bits)) return false;
3807      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3808      offset = GetOffset(offset, L, bits);
3809      beqzalc(scratch, offset);
3810      break;
3811    default:
3812      UNREACHABLE();
3813  }
3814  return true;
3815}
3816
3817
3818// Pre r6 we need to use a bgezal or bltzal, but they can't be used directly
3819// with the slt instructions. We could use sub or add instead but we would miss
3820// overflow cases, so we keep slt and add an intermediate third instruction.
3821bool MacroAssembler::BranchAndLinkShortHelper(int16_t offset, Label* L,
3822                                              Condition cond, Register rs,
3823                                              const Operand& rt,
3824                                              BranchDelaySlot bdslot) {
3825  DCHECK(L == nullptr || offset == 0);
3826  if (!is_near(L, OffsetSize::kOffset16)) return false;
3827
3828  Register scratch = t8;
3829  BlockTrampolinePoolScope block_trampoline_pool(this);
3830
3831  switch (cond) {
3832    case cc_always:
3833      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3834      bal(offset);
3835      break;
3836    case eq:
3837      bne(rs, GetRtAsRegisterHelper(rt, scratch), 2);
3838      nop();
3839      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3840      bal(offset);
3841      break;
3842    case ne:
3843      beq(rs, GetRtAsRegisterHelper(rt, scratch), 2);
3844      nop();
3845      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3846      bal(offset);
3847      break;
3848
3849    // Signed comparison.
3850    case greater:
3851      Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3852      addiu(scratch, scratch, -1);
3853      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3854      bgezal(scratch, offset);
3855      break;
3856    case greater_equal:
3857      Slt(scratch, rs, rt);
3858      addiu(scratch, scratch, -1);
3859      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3860      bltzal(scratch, offset);
3861      break;
3862    case less:
3863      Slt(scratch, rs, rt);
3864      addiu(scratch, scratch, -1);
3865      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3866      bgezal(scratch, offset);
3867      break;
3868    case less_equal:
3869      Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3870      addiu(scratch, scratch, -1);
3871      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3872      bltzal(scratch, offset);
3873      break;
3874
3875    // Unsigned comparison.
3876    case Ugreater:
3877      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3878      addiu(scratch, scratch, -1);
3879      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3880      bgezal(scratch, offset);
3881      break;
3882    case Ugreater_equal:
3883      Sltu(scratch, rs, rt);
3884      addiu(scratch, scratch, -1);
3885      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3886      bltzal(scratch, offset);
3887      break;
3888    case Uless:
3889      Sltu(scratch, rs, rt);
3890      addiu(scratch, scratch, -1);
3891      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3892      bgezal(scratch, offset);
3893      break;
3894    case Uless_equal:
3895      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3896      addiu(scratch, scratch, -1);
3897      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3898      bltzal(scratch, offset);
3899      break;
3900
3901    default:
3902      UNREACHABLE();
3903  }
3904
3905  // Emit a nop in the branch delay slot if required.
3906  if (bdslot == PROTECT)
3907    nop();
3908
3909  return true;
3910}
3911
3912
3913bool MacroAssembler::BranchAndLinkShortCheck(int32_t offset, Label* L,
3914                                             Condition cond, Register rs,
3915                                             const Operand& rt,
3916                                             BranchDelaySlot bdslot) {
3917  BRANCH_ARGS_CHECK(cond, rs, rt);
3918
3919  if (!L) {
3920    if (kArchVariant == kMips64r6 && bdslot == PROTECT) {
3921      DCHECK(is_int26(offset));
3922      return BranchAndLinkShortHelperR6(offset, nullptr, cond, rs, rt);
3923    } else {
3924      DCHECK(is_int16(offset));
3925      return BranchAndLinkShortHelper(offset, nullptr, cond, rs, rt, bdslot);
3926    }
3927  } else {
3928    DCHECK(offset == 0);
3929    if (kArchVariant == kMips64r6 && bdslot == PROTECT) {
3930      return BranchAndLinkShortHelperR6(0, L, cond, rs, rt);
3931    } else {
3932      return BranchAndLinkShortHelper(0, L, cond, rs, rt, bdslot);
3933    }
3934  }
3935  return false;
3936}
3937
3938
3939void MacroAssembler::Jump(Register target,
3940                          Condition cond,
3941                          Register rs,
3942                          const Operand& rt,
3943                          BranchDelaySlot bd) {
3944  BlockTrampolinePoolScope block_trampoline_pool(this);
3945  if (kArchVariant == kMips64r6 && bd == PROTECT) {
3946    if (cond == cc_always) {
3947      jic(target, 0);
3948    } else {
3949      BRANCH_ARGS_CHECK(cond, rs, rt);
3950      Branch(2, NegateCondition(cond), rs, rt);
3951      jic(target, 0);
3952    }
3953  } else {
3954    if (cond == cc_always) {
3955      jr(target);
3956    } else {
3957      BRANCH_ARGS_CHECK(cond, rs, rt);
3958      Branch(2, NegateCondition(cond), rs, rt);
3959      jr(target);
3960    }
3961    // Emit a nop in the branch delay slot if required.
3962    if (bd == PROTECT) nop();
3963  }
3964}
3965
3966
3967void MacroAssembler::Jump(intptr_t target,
3968                          RelocInfo::Mode rmode,
3969                          Condition cond,
3970                          Register rs,
3971                          const Operand& rt,
3972                          BranchDelaySlot bd) {
3973  Label skip;
3974  if (cond != cc_always) {
3975    Branch(USE_DELAY_SLOT, &skip, NegateCondition(cond), rs, rt);
3976  }
3977  // The first instruction of 'li' may be placed in the delay slot.
3978  // This is not an issue, t9 is expected to be clobbered anyway.
3979  li(t9, Operand(target, rmode));
3980  Jump(t9, al, zero_reg, Operand(zero_reg), bd);
3981  bind(&skip);
3982}
3983
3984
3985void MacroAssembler::Jump(Address target,
3986                          RelocInfo::Mode rmode,
3987                          Condition cond,
3988                          Register rs,
3989                          const Operand& rt,
3990                          BranchDelaySlot bd) {
3991  DCHECK(!RelocInfo::IsCodeTarget(rmode));
3992  Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd);
3993}
3994
3995
3996void MacroAssembler::Jump(Handle<Code> code,
3997                          RelocInfo::Mode rmode,
3998                          Condition cond,
3999                          Register rs,
4000                          const Operand& rt,
4001                          BranchDelaySlot bd) {
4002  DCHECK(RelocInfo::IsCodeTarget(rmode));
4003  AllowDeferredHandleDereference embedding_raw_address;
4004  Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd);
4005}
4006
4007
4008int MacroAssembler::CallSize(Register target,
4009                             Condition cond,
4010                             Register rs,
4011                             const Operand& rt,
4012                             BranchDelaySlot bd) {
4013  int size = 0;
4014
4015  if (cond == cc_always) {
4016    size += 1;
4017  } else {
4018    size += 3;
4019  }
4020
4021  if (bd == PROTECT && kArchVariant != kMips64r6) size += 1;
4022
4023  return size * kInstrSize;
4024}
4025
4026
4027// Note: To call gcc-compiled C code on mips, you must call thru t9.
4028void MacroAssembler::Call(Register target,
4029                          Condition cond,
4030                          Register rs,
4031                          const Operand& rt,
4032                          BranchDelaySlot bd) {
4033#ifdef DEBUG
4034  int size = IsPrevInstrCompactBranch() ? kInstrSize : 0;
4035#endif
4036
4037  BlockTrampolinePoolScope block_trampoline_pool(this);
4038  Label start;
4039  bind(&start);
4040  if (kArchVariant == kMips64r6 && bd == PROTECT) {
4041    if (cond == cc_always) {
4042      jialc(target, 0);
4043    } else {
4044      BRANCH_ARGS_CHECK(cond, rs, rt);
4045      Branch(2, NegateCondition(cond), rs, rt);
4046      jialc(target, 0);
4047    }
4048  } else {
4049    if (cond == cc_always) {
4050      jalr(target);
4051    } else {
4052      BRANCH_ARGS_CHECK(cond, rs, rt);
4053      Branch(2, NegateCondition(cond), rs, rt);
4054      jalr(target);
4055    }
4056    // Emit a nop in the branch delay slot if required.
4057    if (bd == PROTECT) nop();
4058  }
4059
4060#ifdef DEBUG
4061  CHECK_EQ(size + CallSize(target, cond, rs, rt, bd),
4062           SizeOfCodeGeneratedSince(&start));
4063#endif
4064}
4065
4066
4067int MacroAssembler::CallSize(Address target,
4068                             RelocInfo::Mode rmode,
4069                             Condition cond,
4070                             Register rs,
4071                             const Operand& rt,
4072                             BranchDelaySlot bd) {
4073  int size = CallSize(t9, cond, rs, rt, bd);
4074  return size + 4 * kInstrSize;
4075}
4076
4077
4078void MacroAssembler::Call(Address target,
4079                          RelocInfo::Mode rmode,
4080                          Condition cond,
4081                          Register rs,
4082                          const Operand& rt,
4083                          BranchDelaySlot bd) {
4084  BlockTrampolinePoolScope block_trampoline_pool(this);
4085  Label start;
4086  bind(&start);
4087  int64_t target_int = reinterpret_cast<int64_t>(target);
4088  li(t9, Operand(target_int, rmode), ADDRESS_LOAD);
4089  Call(t9, cond, rs, rt, bd);
4090  DCHECK_EQ(CallSize(target, rmode, cond, rs, rt, bd),
4091            SizeOfCodeGeneratedSince(&start));
4092}
4093
4094
4095int MacroAssembler::CallSize(Handle<Code> code,
4096                             RelocInfo::Mode rmode,
4097                             TypeFeedbackId ast_id,
4098                             Condition cond,
4099                             Register rs,
4100                             const Operand& rt,
4101                             BranchDelaySlot bd) {
4102  AllowDeferredHandleDereference using_raw_address;
4103  return CallSize(reinterpret_cast<Address>(code.location()),
4104      rmode, cond, rs, rt, bd);
4105}
4106
4107
4108void MacroAssembler::Call(Handle<Code> code,
4109                          RelocInfo::Mode rmode,
4110                          TypeFeedbackId ast_id,
4111                          Condition cond,
4112                          Register rs,
4113                          const Operand& rt,
4114                          BranchDelaySlot bd) {
4115  BlockTrampolinePoolScope block_trampoline_pool(this);
4116  Label start;
4117  bind(&start);
4118  DCHECK(RelocInfo::IsCodeTarget(rmode));
4119  if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
4120    SetRecordedAstId(ast_id);
4121    rmode = RelocInfo::CODE_TARGET_WITH_ID;
4122  }
4123  AllowDeferredHandleDereference embedding_raw_address;
4124  Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd);
4125  DCHECK_EQ(CallSize(code, rmode, ast_id, cond, rs, rt, bd),
4126            SizeOfCodeGeneratedSince(&start));
4127}
4128
4129
4130void MacroAssembler::Ret(Condition cond,
4131                         Register rs,
4132                         const Operand& rt,
4133                         BranchDelaySlot bd) {
4134  Jump(ra, cond, rs, rt, bd);
4135}
4136
4137
4138void MacroAssembler::BranchLong(Label* L, BranchDelaySlot bdslot) {
4139  if (kArchVariant == kMips64r6 && bdslot == PROTECT &&
4140      (!L->is_bound() || is_near_r6(L))) {
4141    BranchShortHelperR6(0, L);
4142  } else {
4143    EmitForbiddenSlotInstruction();
4144    BlockTrampolinePoolScope block_trampoline_pool(this);
4145    {
4146      BlockGrowBufferScope block_buf_growth(this);
4147      // Buffer growth (and relocation) must be blocked for internal references
4148      // until associated instructions are emitted and available to be patched.
4149      RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
4150      j(L);
4151    }
4152    // Emit a nop in the branch delay slot if required.
4153    if (bdslot == PROTECT) nop();
4154  }
4155}
4156
4157
4158void MacroAssembler::BranchAndLinkLong(Label* L, BranchDelaySlot bdslot) {
4159  if (kArchVariant == kMips64r6 && bdslot == PROTECT &&
4160      (!L->is_bound() || is_near_r6(L))) {
4161    BranchAndLinkShortHelperR6(0, L);
4162  } else {
4163    EmitForbiddenSlotInstruction();
4164    BlockTrampolinePoolScope block_trampoline_pool(this);
4165    {
4166      BlockGrowBufferScope block_buf_growth(this);
4167      // Buffer growth (and relocation) must be blocked for internal references
4168      // until associated instructions are emitted and available to be patched.
4169      RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
4170      jal(L);
4171    }
4172    // Emit a nop in the branch delay slot if required.
4173    if (bdslot == PROTECT) nop();
4174  }
4175}
4176
4177
4178void MacroAssembler::DropAndRet(int drop) {
4179  DCHECK(is_int16(drop * kPointerSize));
4180  Ret(USE_DELAY_SLOT);
4181  daddiu(sp, sp, drop * kPointerSize);
4182}
4183
4184void MacroAssembler::DropAndRet(int drop,
4185                                Condition cond,
4186                                Register r1,
4187                                const Operand& r2) {
4188  // Both Drop and Ret need to be conditional.
4189  Label skip;
4190  if (cond != cc_always) {
4191    Branch(&skip, NegateCondition(cond), r1, r2);
4192  }
4193
4194  Drop(drop);
4195  Ret();
4196
4197  if (cond != cc_always) {
4198    bind(&skip);
4199  }
4200}
4201
4202
4203void MacroAssembler::Drop(int count,
4204                          Condition cond,
4205                          Register reg,
4206                          const Operand& op) {
4207  if (count <= 0) {
4208    return;
4209  }
4210
4211  Label skip;
4212
4213  if (cond != al) {
4214     Branch(&skip, NegateCondition(cond), reg, op);
4215  }
4216
4217  Daddu(sp, sp, Operand(count * kPointerSize));
4218
4219  if (cond != al) {
4220    bind(&skip);
4221  }
4222}
4223
4224
4225
4226void MacroAssembler::Swap(Register reg1,
4227                          Register reg2,
4228                          Register scratch) {
4229  if (scratch.is(no_reg)) {
4230    Xor(reg1, reg1, Operand(reg2));
4231    Xor(reg2, reg2, Operand(reg1));
4232    Xor(reg1, reg1, Operand(reg2));
4233  } else {
4234    mov(scratch, reg1);
4235    mov(reg1, reg2);
4236    mov(reg2, scratch);
4237  }
4238}
4239
4240
4241void MacroAssembler::Call(Label* target) {
4242  BranchAndLink(target);
4243}
4244
4245
4246void MacroAssembler::Push(Handle<Object> handle) {
4247  li(at, Operand(handle));
4248  push(at);
4249}
4250
4251
4252void MacroAssembler::PushRegisterAsTwoSmis(Register src, Register scratch) {
4253  DCHECK(!src.is(scratch));
4254  mov(scratch, src);
4255  dsrl32(src, src, 0);
4256  dsll32(src, src, 0);
4257  push(src);
4258  dsll32(scratch, scratch, 0);
4259  push(scratch);
4260}
4261
4262
4263void MacroAssembler::PopRegisterAsTwoSmis(Register dst, Register scratch) {
4264  DCHECK(!dst.is(scratch));
4265  pop(scratch);
4266  dsrl32(scratch, scratch, 0);
4267  pop(dst);
4268  dsrl32(dst, dst, 0);
4269  dsll32(dst, dst, 0);
4270  or_(dst, dst, scratch);
4271}
4272
4273
4274void MacroAssembler::DebugBreak() {
4275  PrepareCEntryArgs(0);
4276  PrepareCEntryFunction(
4277      ExternalReference(Runtime::kHandleDebuggerStatement, isolate()));
4278  CEntryStub ces(isolate(), 1);
4279  DCHECK(AllowThisStubCall(&ces));
4280  Call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
4281}
4282
4283
4284// ---------------------------------------------------------------------------
4285// Exception handling.
4286
4287void MacroAssembler::PushStackHandler() {
4288  // Adjust this code if not the case.
4289  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
4290  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
4291
4292  // Link the current handler as the next handler.
4293  li(a6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
4294  ld(a5, MemOperand(a6));
4295  push(a5);
4296
4297  // Set this new handler as the current one.
4298  sd(sp, MemOperand(a6));
4299}
4300
4301
4302void MacroAssembler::PopStackHandler() {
4303  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
4304  pop(a1);
4305  Daddu(sp, sp, Operand(static_cast<int64_t>(StackHandlerConstants::kSize -
4306                                             kPointerSize)));
4307  li(at, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
4308  sd(a1, MemOperand(at));
4309}
4310
4311
4312void MacroAssembler::Allocate(int object_size,
4313                              Register result,
4314                              Register scratch1,
4315                              Register scratch2,
4316                              Label* gc_required,
4317                              AllocationFlags flags) {
4318  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
4319  if (!FLAG_inline_new) {
4320    if (emit_debug_code()) {
4321      // Trash the registers to simulate an allocation failure.
4322      li(result, 0x7091);
4323      li(scratch1, 0x7191);
4324      li(scratch2, 0x7291);
4325    }
4326    jmp(gc_required);
4327    return;
4328  }
4329
4330  DCHECK(!AreAliased(result, scratch1, scratch2, t9, at));
4331
4332  // Make object size into bytes.
4333  if ((flags & SIZE_IN_WORDS) != 0) {
4334    object_size *= kPointerSize;
4335  }
4336  DCHECK(0 == (object_size & kObjectAlignmentMask));
4337
4338  // Check relative positions of allocation top and limit addresses.
4339  // ARM adds additional checks to make sure the ldm instruction can be
4340  // used. On MIPS we don't have ldm so we don't need additional checks either.
4341  ExternalReference allocation_top =
4342      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4343  ExternalReference allocation_limit =
4344      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
4345
4346  intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
4347  intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
4348  DCHECK((limit - top) == kPointerSize);
4349
4350  // Set up allocation top address and allocation limit registers.
4351  Register top_address = scratch1;
4352  // This code stores a temporary value in t9.
4353  Register alloc_limit = t9;
4354  Register result_end = scratch2;
4355  li(top_address, Operand(allocation_top));
4356
4357  if ((flags & RESULT_CONTAINS_TOP) == 0) {
4358    // Load allocation top into result and allocation limit into alloc_limit.
4359    ld(result, MemOperand(top_address));
4360    ld(alloc_limit, MemOperand(top_address, kPointerSize));
4361  } else {
4362    if (emit_debug_code()) {
4363      // Assert that result actually contains top on entry.
4364      ld(alloc_limit, MemOperand(top_address));
4365      Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit));
4366    }
4367    // Load allocation limit. Result already contains allocation top.
4368    ld(alloc_limit, MemOperand(top_address, static_cast<int32_t>(limit - top)));
4369  }
4370
4371  // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have
4372  // the same alignment on ARM64.
4373  STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
4374
4375  if (emit_debug_code()) {
4376    And(at, result, Operand(kDoubleAlignmentMask));
4377    Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg));
4378  }
4379
4380  // Calculate new top and bail out if new space is exhausted. Use result
4381  // to calculate the new top.
4382  Daddu(result_end, result, Operand(object_size));
4383  Branch(gc_required, Ugreater, result_end, Operand(alloc_limit));
4384
4385  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
4386    // The top pointer is not updated for allocation folding dominators.
4387    sd(result_end, MemOperand(top_address));
4388  }
4389
4390  // Tag object.
4391  Daddu(result, result, Operand(kHeapObjectTag));
4392}
4393
4394
4395void MacroAssembler::Allocate(Register object_size, Register result,
4396                              Register result_end, Register scratch,
4397                              Label* gc_required, AllocationFlags flags) {
4398  if (!FLAG_inline_new) {
4399    if (emit_debug_code()) {
4400      // Trash the registers to simulate an allocation failure.
4401      li(result, 0x7091);
4402      li(scratch, 0x7191);
4403      li(result_end, 0x7291);
4404    }
4405    jmp(gc_required);
4406    return;
4407  }
4408
4409  // |object_size| and |result_end| may overlap, other registers must not.
4410  DCHECK(!AreAliased(object_size, result, scratch, t9, at));
4411  DCHECK(!AreAliased(result_end, result, scratch, t9, at));
4412
4413  // Check relative positions of allocation top and limit addresses.
4414  // ARM adds additional checks to make sure the ldm instruction can be
4415  // used. On MIPS we don't have ldm so we don't need additional checks either.
4416  ExternalReference allocation_top =
4417      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4418  ExternalReference allocation_limit =
4419      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
4420  intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
4421  intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
4422  DCHECK((limit - top) == kPointerSize);
4423
4424  // Set up allocation top address and object size registers.
4425  Register top_address = scratch;
4426  // This code stores a temporary value in t9.
4427  Register alloc_limit = t9;
4428  li(top_address, Operand(allocation_top));
4429
4430  if ((flags & RESULT_CONTAINS_TOP) == 0) {
4431    // Load allocation top into result and allocation limit into alloc_limit.
4432    ld(result, MemOperand(top_address));
4433    ld(alloc_limit, MemOperand(top_address, kPointerSize));
4434  } else {
4435    if (emit_debug_code()) {
4436      // Assert that result actually contains top on entry.
4437      ld(alloc_limit, MemOperand(top_address));
4438      Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit));
4439    }
4440    // Load allocation limit. Result already contains allocation top.
4441    ld(alloc_limit, MemOperand(top_address, static_cast<int32_t>(limit - top)));
4442  }
4443
4444  // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have
4445  // the same alignment on ARM64.
4446  STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
4447
4448  if (emit_debug_code()) {
4449    And(at, result, Operand(kDoubleAlignmentMask));
4450    Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg));
4451  }
4452
4453  // Calculate new top and bail out if new space is exhausted. Use result
4454  // to calculate the new top. Object size may be in words so a shift is
4455  // required to get the number of bytes.
4456  if ((flags & SIZE_IN_WORDS) != 0) {
4457    Dlsa(result_end, result, object_size, kPointerSizeLog2);
4458  } else {
4459    Daddu(result_end, result, Operand(object_size));
4460  }
4461
4462  Branch(gc_required, Ugreater, result_end, Operand(alloc_limit));
4463
4464  // Update allocation top. result temporarily holds the new top.
4465  if (emit_debug_code()) {
4466    And(at, result_end, Operand(kObjectAlignmentMask));
4467    Check(eq, kUnalignedAllocationInNewSpace, at, Operand(zero_reg));
4468  }
4469
4470  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
4471    // The top pointer is not updated for allocation folding dominators.
4472    sd(result_end, MemOperand(top_address));
4473  }
4474
4475  // Tag object if.
4476  Daddu(result, result, Operand(kHeapObjectTag));
4477}
4478
4479void MacroAssembler::FastAllocate(int object_size, Register result,
4480                                  Register scratch1, Register scratch2,
4481                                  AllocationFlags flags) {
4482  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
4483  DCHECK(!AreAliased(result, scratch1, scratch2, at));
4484
4485  // Make object size into bytes.
4486  if ((flags & SIZE_IN_WORDS) != 0) {
4487    object_size *= kPointerSize;
4488  }
4489  DCHECK(0 == (object_size & kObjectAlignmentMask));
4490
4491  ExternalReference allocation_top =
4492      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4493
4494  Register top_address = scratch1;
4495  Register result_end = scratch2;
4496  li(top_address, Operand(allocation_top));
4497  ld(result, MemOperand(top_address));
4498
4499  // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have
4500  // the same alignment on MIPS64.
4501  STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
4502
4503  if (emit_debug_code()) {
4504    And(at, result, Operand(kDoubleAlignmentMask));
4505    Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg));
4506  }
4507
4508  // Calculate new top and write it back.
4509  Daddu(result_end, result, Operand(object_size));
4510  sd(result_end, MemOperand(top_address));
4511
4512  Daddu(result, result, Operand(kHeapObjectTag));
4513}
4514
4515void MacroAssembler::FastAllocate(Register object_size, Register result,
4516                                  Register result_end, Register scratch,
4517                                  AllocationFlags flags) {
4518  // |object_size| and |result_end| may overlap, other registers must not.
4519  DCHECK(!AreAliased(object_size, result, scratch, at));
4520  DCHECK(!AreAliased(result_end, result, scratch, at));
4521
4522  ExternalReference allocation_top =
4523      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4524
4525  // Set up allocation top address and object size registers.
4526  Register top_address = scratch;
4527  li(top_address, Operand(allocation_top));
4528  ld(result, MemOperand(top_address));
4529
4530  // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have
4531  // the same alignment on MIPS64.
4532  STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
4533
4534  if (emit_debug_code()) {
4535    And(at, result, Operand(kDoubleAlignmentMask));
4536    Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg));
4537  }
4538
4539  // Calculate new top and write it back
4540  if ((flags & SIZE_IN_WORDS) != 0) {
4541    Dlsa(result_end, result, object_size, kPointerSizeLog2);
4542  } else {
4543    Daddu(result_end, result, Operand(object_size));
4544  }
4545
4546  // Update allocation top. result temporarily holds the new top.
4547  if (emit_debug_code()) {
4548    And(at, result_end, Operand(kObjectAlignmentMask));
4549    Check(eq, kUnalignedAllocationInNewSpace, at, Operand(zero_reg));
4550  }
4551
4552  Daddu(result, result, Operand(kHeapObjectTag));
4553}
4554
4555void MacroAssembler::AllocateTwoByteString(Register result,
4556                                           Register length,
4557                                           Register scratch1,
4558                                           Register scratch2,
4559                                           Register scratch3,
4560                                           Label* gc_required) {
4561  // Calculate the number of bytes needed for the characters in the string while
4562  // observing object alignment.
4563  DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
4564  dsll(scratch1, length, 1);  // Length in bytes, not chars.
4565  daddiu(scratch1, scratch1,
4566       kObjectAlignmentMask + SeqTwoByteString::kHeaderSize);
4567  And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
4568
4569  // Allocate two-byte string in new space.
4570  Allocate(scratch1, result, scratch2, scratch3, gc_required,
4571           NO_ALLOCATION_FLAGS);
4572
4573  // Set the map, length and hash field.
4574  InitializeNewString(result,
4575                      length,
4576                      Heap::kStringMapRootIndex,
4577                      scratch1,
4578                      scratch2);
4579}
4580
4581
4582void MacroAssembler::AllocateOneByteString(Register result, Register length,
4583                                           Register scratch1, Register scratch2,
4584                                           Register scratch3,
4585                                           Label* gc_required) {
4586  // Calculate the number of bytes needed for the characters in the string
4587  // while observing object alignment.
4588  DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
4589  DCHECK(kCharSize == 1);
4590  daddiu(scratch1, length,
4591      kObjectAlignmentMask + SeqOneByteString::kHeaderSize);
4592  And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
4593
4594  // Allocate one-byte string in new space.
4595  Allocate(scratch1, result, scratch2, scratch3, gc_required,
4596           NO_ALLOCATION_FLAGS);
4597
4598  // Set the map, length and hash field.
4599  InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
4600                      scratch1, scratch2);
4601}
4602
4603
4604void MacroAssembler::AllocateTwoByteConsString(Register result,
4605                                               Register length,
4606                                               Register scratch1,
4607                                               Register scratch2,
4608                                               Label* gc_required) {
4609  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
4610           NO_ALLOCATION_FLAGS);
4611  InitializeNewString(result,
4612                      length,
4613                      Heap::kConsStringMapRootIndex,
4614                      scratch1,
4615                      scratch2);
4616}
4617
4618
4619void MacroAssembler::AllocateOneByteConsString(Register result, Register length,
4620                                               Register scratch1,
4621                                               Register scratch2,
4622                                               Label* gc_required) {
4623  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
4624           NO_ALLOCATION_FLAGS);
4625
4626  InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
4627                      scratch1, scratch2);
4628}
4629
4630
4631void MacroAssembler::AllocateTwoByteSlicedString(Register result,
4632                                                 Register length,
4633                                                 Register scratch1,
4634                                                 Register scratch2,
4635                                                 Label* gc_required) {
4636  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
4637           NO_ALLOCATION_FLAGS);
4638
4639  InitializeNewString(result,
4640                      length,
4641                      Heap::kSlicedStringMapRootIndex,
4642                      scratch1,
4643                      scratch2);
4644}
4645
4646
4647void MacroAssembler::AllocateOneByteSlicedString(Register result,
4648                                                 Register length,
4649                                                 Register scratch1,
4650                                                 Register scratch2,
4651                                                 Label* gc_required) {
4652  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
4653           NO_ALLOCATION_FLAGS);
4654
4655  InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
4656                      scratch1, scratch2);
4657}
4658
4659
4660void MacroAssembler::JumpIfNotUniqueNameInstanceType(Register reg,
4661                                                     Label* not_unique_name) {
4662  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
4663  Label succeed;
4664  And(at, reg, Operand(kIsNotStringMask | kIsNotInternalizedMask));
4665  Branch(&succeed, eq, at, Operand(zero_reg));
4666  Branch(not_unique_name, ne, reg, Operand(SYMBOL_TYPE));
4667
4668  bind(&succeed);
4669}
4670
4671
4672// Allocates a heap number or jumps to the label if the young space is full and
4673// a scavenge is needed.
4674void MacroAssembler::AllocateHeapNumber(Register result,
4675                                        Register scratch1,
4676                                        Register scratch2,
4677                                        Register heap_number_map,
4678                                        Label* need_gc,
4679                                        MutableMode mode) {
4680  // Allocate an object in the heap for the heap number and tag it as a heap
4681  // object.
4682  Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc,
4683           NO_ALLOCATION_FLAGS);
4684
4685  Heap::RootListIndex map_index = mode == MUTABLE
4686      ? Heap::kMutableHeapNumberMapRootIndex
4687      : Heap::kHeapNumberMapRootIndex;
4688  AssertIsRoot(heap_number_map, map_index);
4689
4690  // Store heap number map in the allocated object.
4691  sd(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
4692}
4693
4694
4695void MacroAssembler::AllocateHeapNumberWithValue(Register result,
4696                                                 FPURegister value,
4697                                                 Register scratch1,
4698                                                 Register scratch2,
4699                                                 Label* gc_required) {
4700  LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
4701  AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required);
4702  sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset));
4703}
4704
4705
4706void MacroAssembler::AllocateJSValue(Register result, Register constructor,
4707                                     Register value, Register scratch1,
4708                                     Register scratch2, Label* gc_required) {
4709  DCHECK(!result.is(constructor));
4710  DCHECK(!result.is(scratch1));
4711  DCHECK(!result.is(scratch2));
4712  DCHECK(!result.is(value));
4713
4714  // Allocate JSValue in new space.
4715  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
4716           NO_ALLOCATION_FLAGS);
4717
4718  // Initialize the JSValue.
4719  LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
4720  sd(scratch1, FieldMemOperand(result, HeapObject::kMapOffset));
4721  LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
4722  sd(scratch1, FieldMemOperand(result, JSObject::kPropertiesOffset));
4723  sd(scratch1, FieldMemOperand(result, JSObject::kElementsOffset));
4724  sd(value, FieldMemOperand(result, JSValue::kValueOffset));
4725  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
4726}
4727
4728
4729void MacroAssembler::CopyBytes(Register src,
4730                               Register dst,
4731                               Register length,
4732                               Register scratch) {
4733  Label align_loop_1, word_loop, byte_loop, byte_loop_1, done;
4734
4735  // Align src before copying in word size chunks.
4736  Branch(&byte_loop, le, length, Operand(kPointerSize));
4737  bind(&align_loop_1);
4738  And(scratch, src, kPointerSize - 1);
4739  Branch(&word_loop, eq, scratch, Operand(zero_reg));
4740  lbu(scratch, MemOperand(src));
4741  Daddu(src, src, 1);
4742  sb(scratch, MemOperand(dst));
4743  Daddu(dst, dst, 1);
4744  Dsubu(length, length, Operand(1));
4745  Branch(&align_loop_1, ne, length, Operand(zero_reg));
4746
4747  // Copy bytes in word size chunks.
4748  bind(&word_loop);
4749  if (emit_debug_code()) {
4750    And(scratch, src, kPointerSize - 1);
4751    Assert(eq, kExpectingAlignmentForCopyBytes,
4752        scratch, Operand(zero_reg));
4753  }
4754  Branch(&byte_loop, lt, length, Operand(kPointerSize));
4755  ld(scratch, MemOperand(src));
4756  Daddu(src, src, kPointerSize);
4757
4758  // TODO(kalmard) check if this can be optimized to use sw in most cases.
4759  // Can't use unaligned access - copy byte by byte.
4760  if (kArchEndian == kLittle) {
4761    sb(scratch, MemOperand(dst, 0));
4762    dsrl(scratch, scratch, 8);
4763    sb(scratch, MemOperand(dst, 1));
4764    dsrl(scratch, scratch, 8);
4765    sb(scratch, MemOperand(dst, 2));
4766    dsrl(scratch, scratch, 8);
4767    sb(scratch, MemOperand(dst, 3));
4768    dsrl(scratch, scratch, 8);
4769    sb(scratch, MemOperand(dst, 4));
4770    dsrl(scratch, scratch, 8);
4771    sb(scratch, MemOperand(dst, 5));
4772    dsrl(scratch, scratch, 8);
4773    sb(scratch, MemOperand(dst, 6));
4774    dsrl(scratch, scratch, 8);
4775    sb(scratch, MemOperand(dst, 7));
4776  } else {
4777    sb(scratch, MemOperand(dst, 7));
4778    dsrl(scratch, scratch, 8);
4779    sb(scratch, MemOperand(dst, 6));
4780    dsrl(scratch, scratch, 8);
4781    sb(scratch, MemOperand(dst, 5));
4782    dsrl(scratch, scratch, 8);
4783    sb(scratch, MemOperand(dst, 4));
4784    dsrl(scratch, scratch, 8);
4785    sb(scratch, MemOperand(dst, 3));
4786    dsrl(scratch, scratch, 8);
4787    sb(scratch, MemOperand(dst, 2));
4788    dsrl(scratch, scratch, 8);
4789    sb(scratch, MemOperand(dst, 1));
4790    dsrl(scratch, scratch, 8);
4791    sb(scratch, MemOperand(dst, 0));
4792  }
4793  Daddu(dst, dst, 8);
4794
4795  Dsubu(length, length, Operand(kPointerSize));
4796  Branch(&word_loop);
4797
4798  // Copy the last bytes if any left.
4799  bind(&byte_loop);
4800  Branch(&done, eq, length, Operand(zero_reg));
4801  bind(&byte_loop_1);
4802  lbu(scratch, MemOperand(src));
4803  Daddu(src, src, 1);
4804  sb(scratch, MemOperand(dst));
4805  Daddu(dst, dst, 1);
4806  Dsubu(length, length, Operand(1));
4807  Branch(&byte_loop_1, ne, length, Operand(zero_reg));
4808  bind(&done);
4809}
4810
4811
4812void MacroAssembler::InitializeFieldsWithFiller(Register current_address,
4813                                                Register end_address,
4814                                                Register filler) {
4815  Label loop, entry;
4816  Branch(&entry);
4817  bind(&loop);
4818  sd(filler, MemOperand(current_address));
4819  Daddu(current_address, current_address, kPointerSize);
4820  bind(&entry);
4821  Branch(&loop, ult, current_address, Operand(end_address));
4822}
4823
4824
4825void MacroAssembler::CheckFastElements(Register map,
4826                                       Register scratch,
4827                                       Label* fail) {
4828  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
4829  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
4830  STATIC_ASSERT(FAST_ELEMENTS == 2);
4831  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
4832  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
4833  Branch(fail, hi, scratch,
4834         Operand(Map::kMaximumBitField2FastHoleyElementValue));
4835}
4836
4837
4838void MacroAssembler::CheckFastObjectElements(Register map,
4839                                             Register scratch,
4840                                             Label* fail) {
4841  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
4842  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
4843  STATIC_ASSERT(FAST_ELEMENTS == 2);
4844  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
4845  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
4846  Branch(fail, ls, scratch,
4847         Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
4848  Branch(fail, hi, scratch,
4849         Operand(Map::kMaximumBitField2FastHoleyElementValue));
4850}
4851
4852
4853void MacroAssembler::CheckFastSmiElements(Register map,
4854                                          Register scratch,
4855                                          Label* fail) {
4856  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
4857  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
4858  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
4859  Branch(fail, hi, scratch,
4860         Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
4861}
4862
4863
4864void MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
4865                                                 Register key_reg,
4866                                                 Register elements_reg,
4867                                                 Register scratch1,
4868                                                 Register scratch2,
4869                                                 Label* fail,
4870                                                 int elements_offset) {
4871  DCHECK(!AreAliased(value_reg, key_reg, elements_reg, scratch1, scratch2));
4872  Label smi_value, done;
4873
4874  // Handle smi values specially.
4875  JumpIfSmi(value_reg, &smi_value);
4876
4877  // Ensure that the object is a heap number.
4878  CheckMap(value_reg,
4879           scratch1,
4880           Heap::kHeapNumberMapRootIndex,
4881           fail,
4882           DONT_DO_SMI_CHECK);
4883
4884  // Double value, turn potential sNaN into qNan.
4885  DoubleRegister double_result = f0;
4886  DoubleRegister double_scratch = f2;
4887
4888  ldc1(double_result, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
4889  Branch(USE_DELAY_SLOT, &done);  // Canonicalization is one instruction.
4890  FPUCanonicalizeNaN(double_result, double_result);
4891
4892  bind(&smi_value);
4893  // Untag and transfer.
4894  dsrl32(scratch1, value_reg, 0);
4895  mtc1(scratch1, double_scratch);
4896  cvt_d_w(double_result, double_scratch);
4897
4898  bind(&done);
4899  Daddu(scratch1, elements_reg,
4900      Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag -
4901              elements_offset));
4902  dsra(scratch2, key_reg, 32 - kDoubleSizeLog2);
4903  Daddu(scratch1, scratch1, scratch2);
4904  // scratch1 is now effective address of the double element.
4905  sdc1(double_result, MemOperand(scratch1, 0));
4906}
4907
4908void MacroAssembler::SubNanPreservePayloadAndSign_s(FPURegister fd,
4909                                                    FPURegister fs,
4910                                                    FPURegister ft) {
4911  FloatRegister dest = fd.is(fs) || fd.is(ft) ? kLithiumScratchDouble : fd;
4912  Label check_nan, save_payload, done;
4913  Register scratch1 = t8;
4914  Register scratch2 = t9;
4915
4916  sub_s(dest, fs, ft);
4917  // Check if the result of subtraction is NaN.
4918  BranchF32(nullptr, &check_nan, eq, fs, ft);
4919  Branch(USE_DELAY_SLOT, &done);
4920  dest.is(fd) ? nop() : mov_s(fd, dest);
4921
4922  bind(&check_nan);
4923  // Check if first operand is a NaN.
4924  mfc1(scratch1, fs);
4925  BranchF32(nullptr, &save_payload, eq, fs, fs);
4926  // Second operand must be a NaN.
4927  mfc1(scratch1, ft);
4928
4929  bind(&save_payload);
4930  // Reserve payload.
4931  And(scratch1, scratch1,
4932      Operand(kSingleSignMask | ((1 << kSingleNaNShift) - 1)));
4933  mfc1(scratch2, dest);
4934  And(scratch2, scratch2, Operand(kSingleNaNMask));
4935  Or(scratch2, scratch2, scratch1);
4936  mtc1(scratch2, fd);
4937
4938  bind(&done);
4939}
4940
4941void MacroAssembler::SubNanPreservePayloadAndSign_d(FPURegister fd,
4942                                                    FPURegister fs,
4943                                                    FPURegister ft) {
4944  FloatRegister dest = fd.is(fs) || fd.is(ft) ? kLithiumScratchDouble : fd;
4945  Label check_nan, save_payload, done;
4946  Register scratch1 = t8;
4947  Register scratch2 = t9;
4948
4949  sub_d(dest, fs, ft);
4950  // Check if the result of subtraction is NaN.
4951  BranchF64(nullptr, &check_nan, eq, fs, ft);
4952  Branch(USE_DELAY_SLOT, &done);
4953  dest.is(fd) ? nop() : mov_d(fd, dest);
4954
4955  bind(&check_nan);
4956  // Check if first operand is a NaN.
4957  dmfc1(scratch1, fs);
4958  BranchF64(nullptr, &save_payload, eq, fs, fs);
4959  // Second operand must be a NaN.
4960  dmfc1(scratch1, ft);
4961
4962  bind(&save_payload);
4963  // Reserve payload.
4964  li(at, Operand(kDoubleSignMask | (1L << kDoubleNaNShift)));
4965  Dsubu(at, at, Operand(1));
4966  And(scratch1, scratch1, at);
4967  dmfc1(scratch2, dest);
4968  And(scratch2, scratch2, Operand(kDoubleNaNMask));
4969  Or(scratch2, scratch2, scratch1);
4970  dmtc1(scratch2, fd);
4971
4972  bind(&done);
4973}
4974
4975void MacroAssembler::CompareMapAndBranch(Register obj,
4976                                         Register scratch,
4977                                         Handle<Map> map,
4978                                         Label* early_success,
4979                                         Condition cond,
4980                                         Label* branch_to) {
4981  ld(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
4982  CompareMapAndBranch(scratch, map, early_success, cond, branch_to);
4983}
4984
4985
4986void MacroAssembler::CompareMapAndBranch(Register obj_map,
4987                                         Handle<Map> map,
4988                                         Label* early_success,
4989                                         Condition cond,
4990                                         Label* branch_to) {
4991  Branch(branch_to, cond, obj_map, Operand(map));
4992}
4993
4994
4995void MacroAssembler::CheckMap(Register obj,
4996                              Register scratch,
4997                              Handle<Map> map,
4998                              Label* fail,
4999                              SmiCheckType smi_check_type) {
5000  if (smi_check_type == DO_SMI_CHECK) {
5001    JumpIfSmi(obj, fail);
5002  }
5003  Label success;
5004  CompareMapAndBranch(obj, scratch, map, &success, ne, fail);
5005  bind(&success);
5006}
5007
5008
5009void MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
5010                                     Register scratch2, Handle<WeakCell> cell,
5011                                     Handle<Code> success,
5012                                     SmiCheckType smi_check_type) {
5013  Label fail;
5014  if (smi_check_type == DO_SMI_CHECK) {
5015    JumpIfSmi(obj, &fail);
5016  }
5017  ld(scratch1, FieldMemOperand(obj, HeapObject::kMapOffset));
5018  GetWeakValue(scratch2, cell);
5019  Jump(success, RelocInfo::CODE_TARGET, eq, scratch1, Operand(scratch2));
5020  bind(&fail);
5021}
5022
5023
5024void MacroAssembler::CheckMap(Register obj,
5025                              Register scratch,
5026                              Heap::RootListIndex index,
5027                              Label* fail,
5028                              SmiCheckType smi_check_type) {
5029  if (smi_check_type == DO_SMI_CHECK) {
5030    JumpIfSmi(obj, fail);
5031  }
5032  ld(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
5033  LoadRoot(at, index);
5034  Branch(fail, ne, scratch, Operand(at));
5035}
5036
5037
5038void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
5039  li(value, Operand(cell));
5040  ld(value, FieldMemOperand(value, WeakCell::kValueOffset));
5041}
5042
5043void MacroAssembler::FPUCanonicalizeNaN(const DoubleRegister dst,
5044                                        const DoubleRegister src) {
5045  sub_d(dst, src, kDoubleRegZero);
5046}
5047
5048void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
5049                                   Label* miss) {
5050  GetWeakValue(value, cell);
5051  JumpIfSmi(value, miss);
5052}
5053
5054
5055void MacroAssembler::MovFromFloatResult(const DoubleRegister dst) {
5056  if (IsMipsSoftFloatABI) {
5057    if (kArchEndian == kLittle) {
5058      Move(dst, v0, v1);
5059    } else {
5060      Move(dst, v1, v0);
5061    }
5062  } else {
5063    Move(dst, f0);  // Reg f0 is o32 ABI FP return value.
5064  }
5065}
5066
5067
5068void MacroAssembler::MovFromFloatParameter(const DoubleRegister dst) {
5069  if (IsMipsSoftFloatABI) {
5070    if (kArchEndian == kLittle) {
5071      Move(dst, a0, a1);
5072    } else {
5073      Move(dst, a1, a0);
5074    }
5075  } else {
5076    Move(dst, f12);  // Reg f12 is n64 ABI FP first argument value.
5077  }
5078}
5079
5080
5081void MacroAssembler::MovToFloatParameter(DoubleRegister src) {
5082  if (!IsMipsSoftFloatABI) {
5083    Move(f12, src);
5084  } else {
5085    if (kArchEndian == kLittle) {
5086      Move(a0, a1, src);
5087    } else {
5088      Move(a1, a0, src);
5089    }
5090  }
5091}
5092
5093
5094void MacroAssembler::MovToFloatResult(DoubleRegister src) {
5095  if (!IsMipsSoftFloatABI) {
5096    Move(f0, src);
5097  } else {
5098    if (kArchEndian == kLittle) {
5099      Move(v0, v1, src);
5100    } else {
5101      Move(v1, v0, src);
5102    }
5103  }
5104}
5105
5106
5107void MacroAssembler::MovToFloatParameters(DoubleRegister src1,
5108                                          DoubleRegister src2) {
5109  if (!IsMipsSoftFloatABI) {
5110    const DoubleRegister fparg2 = f13;
5111    if (src2.is(f12)) {
5112      DCHECK(!src1.is(fparg2));
5113      Move(fparg2, src2);
5114      Move(f12, src1);
5115    } else {
5116      Move(f12, src1);
5117      Move(fparg2, src2);
5118    }
5119  } else {
5120    if (kArchEndian == kLittle) {
5121      Move(a0, a1, src1);
5122      Move(a2, a3, src2);
5123    } else {
5124      Move(a1, a0, src1);
5125      Move(a3, a2, src2);
5126    }
5127  }
5128}
5129
5130
5131// -----------------------------------------------------------------------------
5132// JavaScript invokes.
5133
5134void MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
5135                                        Register caller_args_count_reg,
5136                                        Register scratch0, Register scratch1) {
5137#if DEBUG
5138  if (callee_args_count.is_reg()) {
5139    DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
5140                       scratch1));
5141  } else {
5142    DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
5143  }
5144#endif
5145
5146  // Calculate the end of destination area where we will put the arguments
5147  // after we drop current frame. We add kPointerSize to count the receiver
5148  // argument which is not included into formal parameters count.
5149  Register dst_reg = scratch0;
5150  Dlsa(dst_reg, fp, caller_args_count_reg, kPointerSizeLog2);
5151  Daddu(dst_reg, dst_reg,
5152        Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize));
5153
5154  Register src_reg = caller_args_count_reg;
5155  // Calculate the end of source area. +kPointerSize is for the receiver.
5156  if (callee_args_count.is_reg()) {
5157    Dlsa(src_reg, sp, callee_args_count.reg(), kPointerSizeLog2);
5158    Daddu(src_reg, src_reg, Operand(kPointerSize));
5159  } else {
5160    Daddu(src_reg, sp,
5161          Operand((callee_args_count.immediate() + 1) * kPointerSize));
5162  }
5163
5164  if (FLAG_debug_code) {
5165    Check(lo, kStackAccessBelowStackPointer, src_reg, Operand(dst_reg));
5166  }
5167
5168  // Restore caller's frame pointer and return address now as they will be
5169  // overwritten by the copying loop.
5170  ld(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
5171  ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
5172
5173  // Now copy callee arguments to the caller frame going backwards to avoid
5174  // callee arguments corruption (source and destination areas could overlap).
5175
5176  // Both src_reg and dst_reg are pointing to the word after the one to copy,
5177  // so they must be pre-decremented in the loop.
5178  Register tmp_reg = scratch1;
5179  Label loop, entry;
5180  Branch(&entry);
5181  bind(&loop);
5182  Dsubu(src_reg, src_reg, Operand(kPointerSize));
5183  Dsubu(dst_reg, dst_reg, Operand(kPointerSize));
5184  ld(tmp_reg, MemOperand(src_reg));
5185  sd(tmp_reg, MemOperand(dst_reg));
5186  bind(&entry);
5187  Branch(&loop, ne, sp, Operand(src_reg));
5188
5189  // Leave current frame.
5190  mov(sp, dst_reg);
5191}
5192
5193void MacroAssembler::InvokePrologue(const ParameterCount& expected,
5194                                    const ParameterCount& actual,
5195                                    Label* done,
5196                                    bool* definitely_mismatches,
5197                                    InvokeFlag flag,
5198                                    const CallWrapper& call_wrapper) {
5199  bool definitely_matches = false;
5200  *definitely_mismatches = false;
5201  Label regular_invoke;
5202
5203  // Check whether the expected and actual arguments count match. If not,
5204  // setup registers according to contract with ArgumentsAdaptorTrampoline:
5205  //  a0: actual arguments count
5206  //  a1: function (passed through to callee)
5207  //  a2: expected arguments count
5208
5209  // The code below is made a lot easier because the calling code already sets
5210  // up actual and expected registers according to the contract if values are
5211  // passed in registers.
5212  DCHECK(actual.is_immediate() || actual.reg().is(a0));
5213  DCHECK(expected.is_immediate() || expected.reg().is(a2));
5214
5215  if (expected.is_immediate()) {
5216    DCHECK(actual.is_immediate());
5217    li(a0, Operand(actual.immediate()));
5218    if (expected.immediate() == actual.immediate()) {
5219      definitely_matches = true;
5220    } else {
5221      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
5222      if (expected.immediate() == sentinel) {
5223        // Don't worry about adapting arguments for builtins that
5224        // don't want that done. Skip adaption code by making it look
5225        // like we have a match between expected and actual number of
5226        // arguments.
5227        definitely_matches = true;
5228      } else {
5229        *definitely_mismatches = true;
5230        li(a2, Operand(expected.immediate()));
5231      }
5232    }
5233  } else if (actual.is_immediate()) {
5234    li(a0, Operand(actual.immediate()));
5235    Branch(&regular_invoke, eq, expected.reg(), Operand(a0));
5236  } else {
5237    Branch(&regular_invoke, eq, expected.reg(), Operand(actual.reg()));
5238  }
5239
5240  if (!definitely_matches) {
5241    Handle<Code> adaptor =
5242        isolate()->builtins()->ArgumentsAdaptorTrampoline();
5243    if (flag == CALL_FUNCTION) {
5244      call_wrapper.BeforeCall(CallSize(adaptor));
5245      Call(adaptor);
5246      call_wrapper.AfterCall();
5247      if (!*definitely_mismatches) {
5248        Branch(done);
5249      }
5250    } else {
5251      Jump(adaptor, RelocInfo::CODE_TARGET);
5252    }
5253    bind(&regular_invoke);
5254  }
5255}
5256
5257
5258void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target,
5259                                             const ParameterCount& expected,
5260                                             const ParameterCount& actual) {
5261  Label skip_flooding;
5262  ExternalReference last_step_action =
5263      ExternalReference::debug_last_step_action_address(isolate());
5264  STATIC_ASSERT(StepFrame > StepIn);
5265  li(t0, Operand(last_step_action));
5266  lb(t0, MemOperand(t0));
5267  Branch(&skip_flooding, lt, t0, Operand(StepIn));
5268  {
5269    FrameScope frame(this,
5270                     has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
5271    if (expected.is_reg()) {
5272      SmiTag(expected.reg());
5273      Push(expected.reg());
5274    }
5275    if (actual.is_reg()) {
5276      SmiTag(actual.reg());
5277      Push(actual.reg());
5278    }
5279    if (new_target.is_valid()) {
5280      Push(new_target);
5281    }
5282    Push(fun);
5283    Push(fun);
5284    CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
5285    Pop(fun);
5286    if (new_target.is_valid()) {
5287      Pop(new_target);
5288    }
5289    if (actual.is_reg()) {
5290      Pop(actual.reg());
5291      SmiUntag(actual.reg());
5292    }
5293    if (expected.is_reg()) {
5294      Pop(expected.reg());
5295      SmiUntag(expected.reg());
5296    }
5297  }
5298  bind(&skip_flooding);
5299}
5300
5301
5302void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
5303                                        const ParameterCount& expected,
5304                                        const ParameterCount& actual,
5305                                        InvokeFlag flag,
5306                                        const CallWrapper& call_wrapper) {
5307  // You can't call a function without a valid frame.
5308  DCHECK(flag == JUMP_FUNCTION || has_frame());
5309  DCHECK(function.is(a1));
5310  DCHECK_IMPLIES(new_target.is_valid(), new_target.is(a3));
5311
5312  if (call_wrapper.NeedsDebugStepCheck()) {
5313    FloodFunctionIfStepping(function, new_target, expected, actual);
5314  }
5315
5316  // Clear the new.target register if not given.
5317  if (!new_target.is_valid()) {
5318    LoadRoot(a3, Heap::kUndefinedValueRootIndex);
5319  }
5320
5321  Label done;
5322  bool definitely_mismatches = false;
5323  InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
5324                 call_wrapper);
5325  if (!definitely_mismatches) {
5326    // We call indirectly through the code field in the function to
5327    // allow recompilation to take effect without changing any of the
5328    // call sites.
5329    Register code = t0;
5330    ld(code, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
5331    if (flag == CALL_FUNCTION) {
5332      call_wrapper.BeforeCall(CallSize(code));
5333      Call(code);
5334      call_wrapper.AfterCall();
5335    } else {
5336      DCHECK(flag == JUMP_FUNCTION);
5337      Jump(code);
5338    }
5339    // Continue here if InvokePrologue does handle the invocation due to
5340    // mismatched parameter counts.
5341    bind(&done);
5342  }
5343}
5344
5345
5346void MacroAssembler::InvokeFunction(Register function,
5347                                    Register new_target,
5348                                    const ParameterCount& actual,
5349                                    InvokeFlag flag,
5350                                    const CallWrapper& call_wrapper) {
5351  // You can't call a function without a valid frame.
5352  DCHECK(flag == JUMP_FUNCTION || has_frame());
5353
5354  // Contract with called JS functions requires that function is passed in a1.
5355  DCHECK(function.is(a1));
5356  Register expected_reg = a2;
5357  Register temp_reg = t0;
5358  ld(temp_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
5359  ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
5360  // The argument count is stored as int32_t on 64-bit platforms.
5361  // TODO(plind): Smi on 32-bit platforms.
5362  lw(expected_reg,
5363     FieldMemOperand(temp_reg,
5364                     SharedFunctionInfo::kFormalParameterCountOffset));
5365  ParameterCount expected(expected_reg);
5366  InvokeFunctionCode(a1, new_target, expected, actual, flag, call_wrapper);
5367}
5368
5369
5370void MacroAssembler::InvokeFunction(Register function,
5371                                    const ParameterCount& expected,
5372                                    const ParameterCount& actual,
5373                                    InvokeFlag flag,
5374                                    const CallWrapper& call_wrapper) {
5375  // You can't call a function without a valid frame.
5376  DCHECK(flag == JUMP_FUNCTION || has_frame());
5377
5378  // Contract with called JS functions requires that function is passed in a1.
5379  DCHECK(function.is(a1));
5380
5381  // Get the function and setup the context.
5382  ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
5383
5384  InvokeFunctionCode(a1, no_reg, expected, actual, flag, call_wrapper);
5385}
5386
5387
5388void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
5389                                    const ParameterCount& expected,
5390                                    const ParameterCount& actual,
5391                                    InvokeFlag flag,
5392                                    const CallWrapper& call_wrapper) {
5393  li(a1, function);
5394  InvokeFunction(a1, expected, actual, flag, call_wrapper);
5395}
5396
5397
5398void MacroAssembler::IsObjectJSStringType(Register object,
5399                                          Register scratch,
5400                                          Label* fail) {
5401  DCHECK(kNotStringTag != 0);
5402
5403  ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
5404  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
5405  And(scratch, scratch, Operand(kIsNotStringMask));
5406  Branch(fail, ne, scratch, Operand(zero_reg));
5407}
5408
5409
5410void MacroAssembler::IsObjectNameType(Register object,
5411                                      Register scratch,
5412                                      Label* fail) {
5413  ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
5414  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
5415  Branch(fail, hi, scratch, Operand(LAST_NAME_TYPE));
5416}
5417
5418
5419// ---------------------------------------------------------------------------
5420// Support functions.
5421
5422
5423void MacroAssembler::GetMapConstructor(Register result, Register map,
5424                                       Register temp, Register temp2) {
5425  Label done, loop;
5426  ld(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
5427  bind(&loop);
5428  JumpIfSmi(result, &done);
5429  GetObjectType(result, temp, temp2);
5430  Branch(&done, ne, temp2, Operand(MAP_TYPE));
5431  ld(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
5432  Branch(&loop);
5433  bind(&done);
5434}
5435
5436
5437void MacroAssembler::TryGetFunctionPrototype(Register function, Register result,
5438                                             Register scratch, Label* miss) {
5439  // Get the prototype or initial map from the function.
5440  ld(result,
5441     FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
5442
5443  // If the prototype or initial map is the hole, don't return it and
5444  // simply miss the cache instead. This will allow us to allocate a
5445  // prototype object on-demand in the runtime system.
5446  LoadRoot(t8, Heap::kTheHoleValueRootIndex);
5447  Branch(miss, eq, result, Operand(t8));
5448
5449  // If the function does not have an initial map, we're done.
5450  Label done;
5451  GetObjectType(result, scratch, scratch);
5452  Branch(&done, ne, scratch, Operand(MAP_TYPE));
5453
5454  // Get the prototype from the initial map.
5455  ld(result, FieldMemOperand(result, Map::kPrototypeOffset));
5456
5457  // All done.
5458  bind(&done);
5459}
5460
5461
5462void MacroAssembler::GetObjectType(Register object,
5463                                   Register map,
5464                                   Register type_reg) {
5465  ld(map, FieldMemOperand(object, HeapObject::kMapOffset));
5466  lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
5467}
5468
5469
5470// -----------------------------------------------------------------------------
5471// Runtime calls.
5472
5473void MacroAssembler::CallStub(CodeStub* stub,
5474                              TypeFeedbackId ast_id,
5475                              Condition cond,
5476                              Register r1,
5477                              const Operand& r2,
5478                              BranchDelaySlot bd) {
5479  DCHECK(AllowThisStubCall(stub));  // Stub calls are not allowed in some stubs.
5480  Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id,
5481       cond, r1, r2, bd);
5482}
5483
5484
5485void MacroAssembler::TailCallStub(CodeStub* stub,
5486                                  Condition cond,
5487                                  Register r1,
5488                                  const Operand& r2,
5489                                  BranchDelaySlot bd) {
5490  Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2, bd);
5491}
5492
5493
5494bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
5495  return has_frame_ || !stub->SometimesSetsUpAFrame();
5496}
5497
5498
5499void MacroAssembler::IndexFromHash(Register hash, Register index) {
5500  // If the hash field contains an array index pick it out. The assert checks
5501  // that the constants for the maximum number of digits for an array index
5502  // cached in the hash field and the number of bits reserved for it does not
5503  // conflict.
5504  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
5505         (1 << String::kArrayIndexValueBits));
5506  DecodeFieldToSmi<String::ArrayIndexValueBits>(index, hash);
5507}
5508
5509
5510void MacroAssembler::ObjectToDoubleFPURegister(Register object,
5511                                               FPURegister result,
5512                                               Register scratch1,
5513                                               Register scratch2,
5514                                               Register heap_number_map,
5515                                               Label* not_number,
5516                                               ObjectToDoubleFlags flags) {
5517  Label done;
5518  if ((flags & OBJECT_NOT_SMI) == 0) {
5519    Label not_smi;
5520    JumpIfNotSmi(object, &not_smi);
5521    // Remove smi tag and convert to double.
5522    // dsra(scratch1, object, kSmiTagSize);
5523    dsra32(scratch1, object, 0);
5524    mtc1(scratch1, result);
5525    cvt_d_w(result, result);
5526    Branch(&done);
5527    bind(&not_smi);
5528  }
5529  // Check for heap number and load double value from it.
5530  ld(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
5531  Branch(not_number, ne, scratch1, Operand(heap_number_map));
5532
5533  if ((flags & AVOID_NANS_AND_INFINITIES) != 0) {
5534    // If exponent is all ones the number is either a NaN or +/-Infinity.
5535    Register exponent = scratch1;
5536    Register mask_reg = scratch2;
5537    lwu(exponent, FieldMemOperand(object, HeapNumber::kExponentOffset));
5538    li(mask_reg, HeapNumber::kExponentMask);
5539
5540    And(exponent, exponent, mask_reg);
5541    Branch(not_number, eq, exponent, Operand(mask_reg));
5542  }
5543  ldc1(result, FieldMemOperand(object, HeapNumber::kValueOffset));
5544  bind(&done);
5545}
5546
5547
5548void MacroAssembler::SmiToDoubleFPURegister(Register smi,
5549                                            FPURegister value,
5550                                            Register scratch1) {
5551  dsra32(scratch1, smi, 0);
5552  mtc1(scratch1, value);
5553  cvt_d_w(value, value);
5554}
5555
5556static inline void BranchOvfHelper(MacroAssembler* masm, Register overflow_dst,
5557                                   Label* overflow_label,
5558                                   Label* no_overflow_label) {
5559  DCHECK(overflow_label || no_overflow_label);
5560  if (!overflow_label) {
5561    DCHECK(no_overflow_label);
5562    masm->Branch(no_overflow_label, ge, overflow_dst, Operand(zero_reg));
5563  } else {
5564    masm->Branch(overflow_label, lt, overflow_dst, Operand(zero_reg));
5565    if (no_overflow_label) masm->Branch(no_overflow_label);
5566  }
5567}
5568
5569void MacroAssembler::AddBranchOvf(Register dst, Register left,
5570                                  const Operand& right, Label* overflow_label,
5571                                  Label* no_overflow_label, Register scratch) {
5572  if (right.is_reg()) {
5573    AddBranchOvf(dst, left, right.rm(), overflow_label, no_overflow_label,
5574                 scratch);
5575  } else {
5576    if (kArchVariant == kMips64r6) {
5577      Register right_reg = t9;
5578      DCHECK(!left.is(right_reg));
5579      li(right_reg, Operand(right));
5580      AddBranchOvf(dst, left, right_reg, overflow_label, no_overflow_label);
5581    } else {
5582      Register overflow_dst = t9;
5583      DCHECK(!dst.is(scratch));
5584      DCHECK(!dst.is(overflow_dst));
5585      DCHECK(!scratch.is(overflow_dst));
5586      DCHECK(!left.is(overflow_dst));
5587      if (dst.is(left)) {
5588        mov(scratch, left);  // Preserve left.
5589        // Left is overwritten.
5590        Addu(dst, left, static_cast<int32_t>(right.immediate()));
5591        xor_(scratch, dst, scratch);  // Original left.
5592        // Load right since xori takes uint16 as immediate.
5593        Addu(overflow_dst, zero_reg, right);
5594        xor_(overflow_dst, dst, overflow_dst);
5595        and_(overflow_dst, overflow_dst, scratch);
5596      } else {
5597        Addu(dst, left, static_cast<int32_t>(right.immediate()));
5598        xor_(overflow_dst, dst, left);
5599        // Load right since xori takes uint16 as immediate.
5600        Addu(scratch, zero_reg, right);
5601        xor_(scratch, dst, scratch);
5602        and_(overflow_dst, scratch, overflow_dst);
5603      }
5604      BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5605    }
5606  }
5607}
5608
5609void MacroAssembler::AddBranchOvf(Register dst, Register left, Register right,
5610                                  Label* overflow_label,
5611                                  Label* no_overflow_label, Register scratch) {
5612  if (kArchVariant == kMips64r6) {
5613    if (!overflow_label) {
5614      DCHECK(no_overflow_label);
5615      DCHECK(!dst.is(scratch));
5616      Register left_reg = left.is(dst) ? scratch : left;
5617      Register right_reg = right.is(dst) ? t9 : right;
5618      DCHECK(!dst.is(left_reg));
5619      DCHECK(!dst.is(right_reg));
5620      Move(left_reg, left);
5621      Move(right_reg, right);
5622      addu(dst, left, right);
5623      bnvc(left_reg, right_reg, no_overflow_label);
5624    } else {
5625      bovc(left, right, overflow_label);
5626      addu(dst, left, right);
5627      if (no_overflow_label) bc(no_overflow_label);
5628    }
5629  } else {
5630    Register overflow_dst = t9;
5631    DCHECK(!dst.is(scratch));
5632    DCHECK(!dst.is(overflow_dst));
5633    DCHECK(!scratch.is(overflow_dst));
5634    DCHECK(!left.is(overflow_dst));
5635    DCHECK(!right.is(overflow_dst));
5636    DCHECK(!left.is(scratch));
5637    DCHECK(!right.is(scratch));
5638
5639    if (left.is(right) && dst.is(left)) {
5640      mov(overflow_dst, right);
5641      right = overflow_dst;
5642    }
5643
5644    if (dst.is(left)) {
5645      mov(scratch, left);           // Preserve left.
5646      addu(dst, left, right);       // Left is overwritten.
5647      xor_(scratch, dst, scratch);  // Original left.
5648      xor_(overflow_dst, dst, right);
5649      and_(overflow_dst, overflow_dst, scratch);
5650    } else if (dst.is(right)) {
5651      mov(scratch, right);          // Preserve right.
5652      addu(dst, left, right);       // Right is overwritten.
5653      xor_(scratch, dst, scratch);  // Original right.
5654      xor_(overflow_dst, dst, left);
5655      and_(overflow_dst, overflow_dst, scratch);
5656    } else {
5657      addu(dst, left, right);
5658      xor_(overflow_dst, dst, left);
5659      xor_(scratch, dst, right);
5660      and_(overflow_dst, scratch, overflow_dst);
5661    }
5662    BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5663  }
5664}
5665
5666void MacroAssembler::SubBranchOvf(Register dst, Register left,
5667                                  const Operand& right, Label* overflow_label,
5668                                  Label* no_overflow_label, Register scratch) {
5669  DCHECK(overflow_label || no_overflow_label);
5670  if (right.is_reg()) {
5671    SubBranchOvf(dst, left, right.rm(), overflow_label, no_overflow_label,
5672                 scratch);
5673  } else {
5674    Register overflow_dst = t9;
5675    DCHECK(!dst.is(scratch));
5676    DCHECK(!dst.is(overflow_dst));
5677    DCHECK(!scratch.is(overflow_dst));
5678    DCHECK(!left.is(overflow_dst));
5679    DCHECK(!left.is(scratch));
5680    if (dst.is(left)) {
5681      mov(scratch, left);  // Preserve left.
5682      // Left is overwritten.
5683      Subu(dst, left, static_cast<int32_t>(right.immediate()));
5684      // Load right since xori takes uint16 as immediate.
5685      Addu(overflow_dst, zero_reg, right);
5686      xor_(overflow_dst, scratch, overflow_dst);  // scratch is original left.
5687      xor_(scratch, dst, scratch);                // scratch is original left.
5688      and_(overflow_dst, scratch, overflow_dst);
5689    } else {
5690      Subu(dst, left, right);
5691      xor_(overflow_dst, dst, left);
5692      // Load right since xori takes uint16 as immediate.
5693      Addu(scratch, zero_reg, right);
5694      xor_(scratch, left, scratch);
5695      and_(overflow_dst, scratch, overflow_dst);
5696    }
5697    BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5698  }
5699}
5700
5701void MacroAssembler::SubBranchOvf(Register dst, Register left, Register right,
5702                                  Label* overflow_label,
5703                                  Label* no_overflow_label, Register scratch) {
5704  DCHECK(overflow_label || no_overflow_label);
5705  Register overflow_dst = t9;
5706  DCHECK(!dst.is(scratch));
5707  DCHECK(!dst.is(overflow_dst));
5708  DCHECK(!scratch.is(overflow_dst));
5709  DCHECK(!overflow_dst.is(left));
5710  DCHECK(!overflow_dst.is(right));
5711  DCHECK(!scratch.is(left));
5712  DCHECK(!scratch.is(right));
5713
5714  // This happens with some crankshaft code. Since Subu works fine if
5715  // left == right, let's not make that restriction here.
5716  if (left.is(right)) {
5717    mov(dst, zero_reg);
5718    if (no_overflow_label) {
5719      Branch(no_overflow_label);
5720    }
5721  }
5722
5723  if (dst.is(left)) {
5724    mov(scratch, left);  // Preserve left.
5725    subu(dst, left, right);            // Left is overwritten.
5726    xor_(overflow_dst, dst, scratch);  // scratch is original left.
5727    xor_(scratch, scratch, right);     // scratch is original left.
5728    and_(overflow_dst, scratch, overflow_dst);
5729  } else if (dst.is(right)) {
5730    mov(scratch, right);  // Preserve right.
5731    subu(dst, left, right);  // Right is overwritten.
5732    xor_(overflow_dst, dst, left);
5733    xor_(scratch, left, scratch);  // Original right.
5734    and_(overflow_dst, scratch, overflow_dst);
5735  } else {
5736    subu(dst, left, right);
5737    xor_(overflow_dst, dst, left);
5738    xor_(scratch, left, right);
5739    and_(overflow_dst, scratch, overflow_dst);
5740  }
5741  BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5742}
5743
5744void MacroAssembler::DaddBranchOvf(Register dst, Register left,
5745                                   const Operand& right, Label* overflow_label,
5746                                   Label* no_overflow_label, Register scratch) {
5747  if (right.is_reg()) {
5748    DaddBranchOvf(dst, left, right.rm(), overflow_label, no_overflow_label,
5749                  scratch);
5750  } else {
5751    Register overflow_dst = t9;
5752    DCHECK(!dst.is(scratch));
5753    DCHECK(!dst.is(overflow_dst));
5754    DCHECK(!scratch.is(overflow_dst));
5755    DCHECK(!left.is(overflow_dst));
5756    li(overflow_dst, right);  // Load right.
5757    if (dst.is(left)) {
5758      mov(scratch, left);              // Preserve left.
5759      Daddu(dst, left, overflow_dst);  // Left is overwritten.
5760      xor_(scratch, dst, scratch);     // Original left.
5761      xor_(overflow_dst, dst, overflow_dst);
5762      and_(overflow_dst, overflow_dst, scratch);
5763    } else {
5764      Daddu(dst, left, overflow_dst);
5765      xor_(scratch, dst, overflow_dst);
5766      xor_(overflow_dst, dst, left);
5767      and_(overflow_dst, scratch, overflow_dst);
5768    }
5769    BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5770  }
5771}
5772
5773
5774void MacroAssembler::DaddBranchOvf(Register dst, Register left, Register right,
5775                                   Label* overflow_label,
5776                                   Label* no_overflow_label, Register scratch) {
5777  Register overflow_dst = t9;
5778  DCHECK(!dst.is(scratch));
5779  DCHECK(!dst.is(overflow_dst));
5780  DCHECK(!scratch.is(overflow_dst));
5781  DCHECK(!left.is(overflow_dst));
5782  DCHECK(!right.is(overflow_dst));
5783  DCHECK(!left.is(scratch));
5784  DCHECK(!right.is(scratch));
5785
5786  if (left.is(right) && dst.is(left)) {
5787    mov(overflow_dst, right);
5788    right = overflow_dst;
5789  }
5790
5791  if (dst.is(left)) {
5792    mov(scratch, left);           // Preserve left.
5793    daddu(dst, left, right);      // Left is overwritten.
5794    xor_(scratch, dst, scratch);  // Original left.
5795    xor_(overflow_dst, dst, right);
5796    and_(overflow_dst, overflow_dst, scratch);
5797  } else if (dst.is(right)) {
5798    mov(scratch, right);          // Preserve right.
5799    daddu(dst, left, right);      // Right is overwritten.
5800    xor_(scratch, dst, scratch);  // Original right.
5801    xor_(overflow_dst, dst, left);
5802    and_(overflow_dst, overflow_dst, scratch);
5803  } else {
5804    daddu(dst, left, right);
5805    xor_(overflow_dst, dst, left);
5806    xor_(scratch, dst, right);
5807    and_(overflow_dst, scratch, overflow_dst);
5808  }
5809  BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5810}
5811
5812
5813void MacroAssembler::DsubBranchOvf(Register dst, Register left,
5814                                   const Operand& right, Label* overflow_label,
5815                                   Label* no_overflow_label, Register scratch) {
5816  DCHECK(overflow_label || no_overflow_label);
5817  if (right.is_reg()) {
5818    DsubBranchOvf(dst, left, right.rm(), overflow_label, no_overflow_label,
5819                  scratch);
5820  } else {
5821    Register overflow_dst = t9;
5822    DCHECK(!dst.is(scratch));
5823    DCHECK(!dst.is(overflow_dst));
5824    DCHECK(!scratch.is(overflow_dst));
5825    DCHECK(!left.is(overflow_dst));
5826    DCHECK(!left.is(scratch));
5827    li(overflow_dst, right);  // Load right.
5828    if (dst.is(left)) {
5829      mov(scratch, left);                         // Preserve left.
5830      Dsubu(dst, left, overflow_dst);             // Left is overwritten.
5831      xor_(overflow_dst, scratch, overflow_dst);  // scratch is original left.
5832      xor_(scratch, dst, scratch);                // scratch is original left.
5833      and_(overflow_dst, scratch, overflow_dst);
5834    } else {
5835      Dsubu(dst, left, overflow_dst);
5836      xor_(scratch, left, overflow_dst);
5837      xor_(overflow_dst, dst, left);
5838      and_(overflow_dst, scratch, overflow_dst);
5839    }
5840    BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5841  }
5842}
5843
5844
5845void MacroAssembler::DsubBranchOvf(Register dst, Register left, Register right,
5846                                   Label* overflow_label,
5847                                   Label* no_overflow_label, Register scratch) {
5848  DCHECK(overflow_label || no_overflow_label);
5849  Register overflow_dst = t9;
5850  DCHECK(!dst.is(scratch));
5851  DCHECK(!dst.is(overflow_dst));
5852  DCHECK(!scratch.is(overflow_dst));
5853  DCHECK(!overflow_dst.is(left));
5854  DCHECK(!overflow_dst.is(right));
5855  DCHECK(!scratch.is(left));
5856  DCHECK(!scratch.is(right));
5857
5858  // This happens with some crankshaft code. Since Subu works fine if
5859  // left == right, let's not make that restriction here.
5860  if (left.is(right)) {
5861    mov(dst, zero_reg);
5862    if (no_overflow_label) {
5863      Branch(no_overflow_label);
5864    }
5865  }
5866
5867  if (dst.is(left)) {
5868    mov(scratch, left);                // Preserve left.
5869    dsubu(dst, left, right);           // Left is overwritten.
5870    xor_(overflow_dst, dst, scratch);  // scratch is original left.
5871    xor_(scratch, scratch, right);     // scratch is original left.
5872    and_(overflow_dst, scratch, overflow_dst);
5873  } else if (dst.is(right)) {
5874    mov(scratch, right);      // Preserve right.
5875    dsubu(dst, left, right);  // Right is overwritten.
5876    xor_(overflow_dst, dst, left);
5877    xor_(scratch, left, scratch);  // Original right.
5878    and_(overflow_dst, scratch, overflow_dst);
5879  } else {
5880    dsubu(dst, left, right);
5881    xor_(overflow_dst, dst, left);
5882    xor_(scratch, left, right);
5883    and_(overflow_dst, scratch, overflow_dst);
5884  }
5885  BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5886}
5887
5888
5889void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
5890                                 SaveFPRegsMode save_doubles,
5891                                 BranchDelaySlot bd) {
5892  // All parameters are on the stack. v0 has the return value after call.
5893
5894  // If the expected number of arguments of the runtime function is
5895  // constant, we check that the actual number of arguments match the
5896  // expectation.
5897  CHECK(f->nargs < 0 || f->nargs == num_arguments);
5898
5899  // TODO(1236192): Most runtime routines don't need the number of
5900  // arguments passed in because it is constant. At some point we
5901  // should remove this need and make the runtime routine entry code
5902  // smarter.
5903  PrepareCEntryArgs(num_arguments);
5904  PrepareCEntryFunction(ExternalReference(f, isolate()));
5905  CEntryStub stub(isolate(), 1, save_doubles);
5906  CallStub(&stub, TypeFeedbackId::None(), al, zero_reg, Operand(zero_reg), bd);
5907}
5908
5909
5910void MacroAssembler::CallExternalReference(const ExternalReference& ext,
5911                                           int num_arguments,
5912                                           BranchDelaySlot bd) {
5913  PrepareCEntryArgs(num_arguments);
5914  PrepareCEntryFunction(ext);
5915
5916  CEntryStub stub(isolate(), 1);
5917  CallStub(&stub, TypeFeedbackId::None(), al, zero_reg, Operand(zero_reg), bd);
5918}
5919
5920
5921void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
5922  const Runtime::Function* function = Runtime::FunctionForId(fid);
5923  DCHECK_EQ(1, function->result_size);
5924  if (function->nargs >= 0) {
5925    PrepareCEntryArgs(function->nargs);
5926  }
5927  JumpToExternalReference(ExternalReference(fid, isolate()));
5928}
5929
5930
5931void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
5932                                             BranchDelaySlot bd) {
5933  PrepareCEntryFunction(builtin);
5934  CEntryStub stub(isolate(), 1);
5935  Jump(stub.GetCode(),
5936       RelocInfo::CODE_TARGET,
5937       al,
5938       zero_reg,
5939       Operand(zero_reg),
5940       bd);
5941}
5942
5943
5944void MacroAssembler::SetCounter(StatsCounter* counter, int value,
5945                                Register scratch1, Register scratch2) {
5946  if (FLAG_native_code_counters && counter->Enabled()) {
5947    li(scratch1, Operand(value));
5948    li(scratch2, Operand(ExternalReference(counter)));
5949    sd(scratch1, MemOperand(scratch2));
5950  }
5951}
5952
5953
5954void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
5955                                      Register scratch1, Register scratch2) {
5956  DCHECK(value > 0);
5957  if (FLAG_native_code_counters && counter->Enabled()) {
5958    li(scratch2, Operand(ExternalReference(counter)));
5959    ld(scratch1, MemOperand(scratch2));
5960    Daddu(scratch1, scratch1, Operand(value));
5961    sd(scratch1, MemOperand(scratch2));
5962  }
5963}
5964
5965
5966void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
5967                                      Register scratch1, Register scratch2) {
5968  DCHECK(value > 0);
5969  if (FLAG_native_code_counters && counter->Enabled()) {
5970    li(scratch2, Operand(ExternalReference(counter)));
5971    ld(scratch1, MemOperand(scratch2));
5972    Dsubu(scratch1, scratch1, Operand(value));
5973    sd(scratch1, MemOperand(scratch2));
5974  }
5975}
5976
5977
5978// -----------------------------------------------------------------------------
5979// Debugging.
5980
5981void MacroAssembler::Assert(Condition cc, BailoutReason reason,
5982                            Register rs, Operand rt) {
5983  if (emit_debug_code())
5984    Check(cc, reason, rs, rt);
5985}
5986
5987
5988void MacroAssembler::AssertFastElements(Register elements) {
5989  if (emit_debug_code()) {
5990    DCHECK(!elements.is(at));
5991    Label ok;
5992    push(elements);
5993    ld(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
5994    LoadRoot(at, Heap::kFixedArrayMapRootIndex);
5995    Branch(&ok, eq, elements, Operand(at));
5996    LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex);
5997    Branch(&ok, eq, elements, Operand(at));
5998    LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);
5999    Branch(&ok, eq, elements, Operand(at));
6000    Abort(kJSObjectWithFastElementsMapHasSlowElements);
6001    bind(&ok);
6002    pop(elements);
6003  }
6004}
6005
6006
6007void MacroAssembler::Check(Condition cc, BailoutReason reason,
6008                           Register rs, Operand rt) {
6009  Label L;
6010  Branch(&L, cc, rs, rt);
6011  Abort(reason);
6012  // Will not return here.
6013  bind(&L);
6014}
6015
6016
6017void MacroAssembler::Abort(BailoutReason reason) {
6018  Label abort_start;
6019  bind(&abort_start);
6020#ifdef DEBUG
6021  const char* msg = GetBailoutReason(reason);
6022  if (msg != NULL) {
6023    RecordComment("Abort message: ");
6024    RecordComment(msg);
6025  }
6026
6027  if (FLAG_trap_on_abort) {
6028    stop(msg);
6029    return;
6030  }
6031#endif
6032
6033  li(a0, Operand(Smi::FromInt(reason)));
6034  push(a0);
6035  // Disable stub call restrictions to always allow calls to abort.
6036  if (!has_frame_) {
6037    // We don't actually want to generate a pile of code for this, so just
6038    // claim there is a stack frame, without generating one.
6039    FrameScope scope(this, StackFrame::NONE);
6040    CallRuntime(Runtime::kAbort);
6041  } else {
6042    CallRuntime(Runtime::kAbort);
6043  }
6044  // Will not return here.
6045  if (is_trampoline_pool_blocked()) {
6046    // If the calling code cares about the exact number of
6047    // instructions generated, we insert padding here to keep the size
6048    // of the Abort macro constant.
6049    // Currently in debug mode with debug_code enabled the number of
6050    // generated instructions is 10, so we use this as a maximum value.
6051    static const int kExpectedAbortInstructions = 10;
6052    int abort_instructions = InstructionsGeneratedSince(&abort_start);
6053    DCHECK(abort_instructions <= kExpectedAbortInstructions);
6054    while (abort_instructions++ < kExpectedAbortInstructions) {
6055      nop();
6056    }
6057  }
6058}
6059
6060
6061void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
6062  if (context_chain_length > 0) {
6063    // Move up the chain of contexts to the context containing the slot.
6064    ld(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
6065    for (int i = 1; i < context_chain_length; i++) {
6066      ld(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
6067    }
6068  } else {
6069    // Slot is in the current function context.  Move it into the
6070    // destination register in case we store into it (the write barrier
6071    // cannot be allowed to destroy the context in esi).
6072    Move(dst, cp);
6073  }
6074}
6075
6076
6077void MacroAssembler::LoadTransitionedArrayMapConditional(
6078    ElementsKind expected_kind,
6079    ElementsKind transitioned_kind,
6080    Register map_in_out,
6081    Register scratch,
6082    Label* no_map_match) {
6083  DCHECK(IsFastElementsKind(expected_kind));
6084  DCHECK(IsFastElementsKind(transitioned_kind));
6085
6086  // Check that the function's map is the same as the expected cached map.
6087  ld(scratch, NativeContextMemOperand());
6088  ld(at, ContextMemOperand(scratch, Context::ArrayMapIndex(expected_kind)));
6089  Branch(no_map_match, ne, map_in_out, Operand(at));
6090
6091  // Use the transitioned cached map.
6092  ld(map_in_out,
6093     ContextMemOperand(scratch, Context::ArrayMapIndex(transitioned_kind)));
6094}
6095
6096
6097void MacroAssembler::LoadNativeContextSlot(int index, Register dst) {
6098  ld(dst, NativeContextMemOperand());
6099  ld(dst, ContextMemOperand(dst, index));
6100}
6101
6102
6103void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
6104                                                  Register map,
6105                                                  Register scratch) {
6106  // Load the initial map. The global functions all have initial maps.
6107  ld(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
6108  if (emit_debug_code()) {
6109    Label ok, fail;
6110    CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
6111    Branch(&ok);
6112    bind(&fail);
6113    Abort(kGlobalFunctionsMustHaveInitialMap);
6114    bind(&ok);
6115  }
6116}
6117
6118void MacroAssembler::StubPrologue(StackFrame::Type type) {
6119  li(at, Operand(Smi::FromInt(type)));
6120  PushCommonFrame(at);
6121}
6122
6123
6124void MacroAssembler::Prologue(bool code_pre_aging) {
6125  PredictableCodeSizeScope predictible_code_size_scope(
6126      this, kNoCodeAgeSequenceLength);
6127  // The following three instructions must remain together and unmodified
6128  // for code aging to work properly.
6129  if (code_pre_aging) {
6130    // Pre-age the code.
6131    Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
6132    nop(Assembler::CODE_AGE_MARKER_NOP);
6133    // Load the stub address to t9 and call it,
6134    // GetCodeAgeAndParity() extracts the stub address from this instruction.
6135    li(t9,
6136       Operand(reinterpret_cast<uint64_t>(stub->instruction_start())),
6137       ADDRESS_LOAD);
6138    nop();  // Prevent jalr to jal optimization.
6139    jalr(t9, a0);
6140    nop();  // Branch delay slot nop.
6141    nop();  // Pad the empty space.
6142  } else {
6143    PushStandardFrame(a1);
6144    nop(Assembler::CODE_AGE_SEQUENCE_NOP);
6145    nop(Assembler::CODE_AGE_SEQUENCE_NOP);
6146    nop(Assembler::CODE_AGE_SEQUENCE_NOP);
6147  }
6148}
6149
6150void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
6151  ld(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
6152  ld(vector, FieldMemOperand(vector, JSFunction::kLiteralsOffset));
6153  ld(vector, FieldMemOperand(vector, LiteralsArray::kFeedbackVectorOffset));
6154}
6155
6156
6157void MacroAssembler::EnterFrame(StackFrame::Type type,
6158                                bool load_constant_pool_pointer_reg) {
6159  // Out-of-line constant pool not implemented on mips64.
6160  UNREACHABLE();
6161}
6162
6163
6164void MacroAssembler::EnterFrame(StackFrame::Type type) {
6165  int stack_offset, fp_offset;
6166  if (type == StackFrame::INTERNAL) {
6167    stack_offset = -4 * kPointerSize;
6168    fp_offset = 2 * kPointerSize;
6169  } else {
6170    stack_offset = -3 * kPointerSize;
6171    fp_offset = 1 * kPointerSize;
6172  }
6173  daddiu(sp, sp, stack_offset);
6174  stack_offset = -stack_offset - kPointerSize;
6175  sd(ra, MemOperand(sp, stack_offset));
6176  stack_offset -= kPointerSize;
6177  sd(fp, MemOperand(sp, stack_offset));
6178  stack_offset -= kPointerSize;
6179  li(t9, Operand(Smi::FromInt(type)));
6180  sd(t9, MemOperand(sp, stack_offset));
6181  if (type == StackFrame::INTERNAL) {
6182    DCHECK_EQ(stack_offset, kPointerSize);
6183    li(t9, Operand(CodeObject()));
6184    sd(t9, MemOperand(sp, 0));
6185  } else {
6186    DCHECK_EQ(stack_offset, 0);
6187  }
6188  // Adjust FP to point to saved FP.
6189  Daddu(fp, sp, Operand(fp_offset));
6190}
6191
6192
6193void MacroAssembler::LeaveFrame(StackFrame::Type type) {
6194  daddiu(sp, fp, 2 * kPointerSize);
6195  ld(ra, MemOperand(fp, 1 * kPointerSize));
6196  ld(fp, MemOperand(fp, 0 * kPointerSize));
6197}
6198
6199void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
6200  // Set up the frame structure on the stack.
6201  STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement);
6202  STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset);
6203  STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset);
6204
6205  // This is how the stack will look:
6206  // fp + 2 (==kCallerSPDisplacement) - old stack's end
6207  // [fp + 1 (==kCallerPCOffset)] - saved old ra
6208  // [fp + 0 (==kCallerFPOffset)] - saved old fp
6209  // [fp - 1 StackFrame::EXIT Smi
6210  // [fp - 2 (==kSPOffset)] - sp of the called function
6211  // [fp - 3 (==kCodeOffset)] - CodeObject
6212  // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the
6213  //   new stack (will contain saved ra)
6214
6215  // Save registers and reserve room for saved entry sp and code object.
6216  daddiu(sp, sp, -2 * kPointerSize - ExitFrameConstants::kFixedFrameSizeFromFp);
6217  sd(ra, MemOperand(sp, 4 * kPointerSize));
6218  sd(fp, MemOperand(sp, 3 * kPointerSize));
6219  li(at, Operand(Smi::FromInt(StackFrame::EXIT)));
6220  sd(at, MemOperand(sp, 2 * kPointerSize));
6221  // Set up new frame pointer.
6222  daddiu(fp, sp, ExitFrameConstants::kFixedFrameSizeFromFp);
6223
6224  if (emit_debug_code()) {
6225    sd(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset));
6226  }
6227
6228  // Accessed from ExitFrame::code_slot.
6229  li(t8, Operand(CodeObject()), CONSTANT_SIZE);
6230  sd(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
6231
6232  // Save the frame pointer and the context in top.
6233  li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
6234  sd(fp, MemOperand(t8));
6235  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
6236  sd(cp, MemOperand(t8));
6237
6238  const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
6239  if (save_doubles) {
6240    // The stack is already aligned to 0 modulo 8 for stores with sdc1.
6241    int kNumOfSavedRegisters = FPURegister::kMaxNumRegisters / 2;
6242    int space = kNumOfSavedRegisters * kDoubleSize;
6243    Dsubu(sp, sp, Operand(space));
6244    // Remember: we only need to save every 2nd double FPU value.
6245    for (int i = 0; i < kNumOfSavedRegisters; i++) {
6246      FPURegister reg = FPURegister::from_code(2 * i);
6247      sdc1(reg, MemOperand(sp, i * kDoubleSize));
6248    }
6249  }
6250
6251  // Reserve place for the return address, stack space and an optional slot
6252  // (used by the DirectCEntryStub to hold the return value if a struct is
6253  // returned) and align the frame preparing for calling the runtime function.
6254  DCHECK(stack_space >= 0);
6255  Dsubu(sp, sp, Operand((stack_space + 2) * kPointerSize));
6256  if (frame_alignment > 0) {
6257    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
6258    And(sp, sp, Operand(-frame_alignment));  // Align stack.
6259  }
6260
6261  // Set the exit frame sp value to point just before the return address
6262  // location.
6263  daddiu(at, sp, kPointerSize);
6264  sd(at, MemOperand(fp, ExitFrameConstants::kSPOffset));
6265}
6266
6267
6268void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
6269                                    bool restore_context, bool do_return,
6270                                    bool argument_count_is_length) {
6271  // Optionally restore all double registers.
6272  if (save_doubles) {
6273    // Remember: we only need to restore every 2nd double FPU value.
6274    int kNumOfSavedRegisters = FPURegister::kMaxNumRegisters / 2;
6275    Dsubu(t8, fp, Operand(ExitFrameConstants::kFixedFrameSizeFromFp +
6276                          kNumOfSavedRegisters * kDoubleSize));
6277    for (int i = 0; i < kNumOfSavedRegisters; i++) {
6278      FPURegister reg = FPURegister::from_code(2 * i);
6279      ldc1(reg, MemOperand(t8, i  * kDoubleSize));
6280    }
6281  }
6282
6283  // Clear top frame.
6284  li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
6285  sd(zero_reg, MemOperand(t8));
6286
6287  // Restore current context from top and clear it in debug mode.
6288  if (restore_context) {
6289    li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
6290    ld(cp, MemOperand(t8));
6291  }
6292#ifdef DEBUG
6293  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
6294  sd(a3, MemOperand(t8));
6295#endif
6296
6297  // Pop the arguments, restore registers, and return.
6298  mov(sp, fp);  // Respect ABI stack constraint.
6299  ld(fp, MemOperand(sp, ExitFrameConstants::kCallerFPOffset));
6300  ld(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset));
6301
6302  if (argument_count.is_valid()) {
6303    if (argument_count_is_length) {
6304      daddu(sp, sp, argument_count);
6305    } else {
6306      Dlsa(sp, sp, argument_count, kPointerSizeLog2, t8);
6307    }
6308  }
6309
6310  if (do_return) {
6311    Ret(USE_DELAY_SLOT);
6312    // If returning, the instruction in the delay slot will be the addiu below.
6313  }
6314  daddiu(sp, sp, 2 * kPointerSize);
6315}
6316
6317
6318void MacroAssembler::InitializeNewString(Register string,
6319                                         Register length,
6320                                         Heap::RootListIndex map_index,
6321                                         Register scratch1,
6322                                         Register scratch2) {
6323  // dsll(scratch1, length, kSmiTagSize);
6324  dsll32(scratch1, length, 0);
6325  LoadRoot(scratch2, map_index);
6326  sd(scratch1, FieldMemOperand(string, String::kLengthOffset));
6327  li(scratch1, Operand(String::kEmptyHashField));
6328  sd(scratch2, FieldMemOperand(string, HeapObject::kMapOffset));
6329  sw(scratch1, FieldMemOperand(string, String::kHashFieldOffset));
6330}
6331
6332
6333int MacroAssembler::ActivationFrameAlignment() {
6334#if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64
6335  // Running on the real platform. Use the alignment as mandated by the local
6336  // environment.
6337  // Note: This will break if we ever start generating snapshots on one Mips
6338  // platform for another Mips platform with a different alignment.
6339  return base::OS::ActivationFrameAlignment();
6340#else  // V8_HOST_ARCH_MIPS
6341  // If we are using the simulator then we should always align to the expected
6342  // alignment. As the simulator is used to generate snapshots we do not know
6343  // if the target platform will need alignment, so this is controlled from a
6344  // flag.
6345  return FLAG_sim_stack_alignment;
6346#endif  // V8_HOST_ARCH_MIPS
6347}
6348
6349
6350void MacroAssembler::AssertStackIsAligned() {
6351  if (emit_debug_code()) {
6352      const int frame_alignment = ActivationFrameAlignment();
6353      const int frame_alignment_mask = frame_alignment - 1;
6354
6355      if (frame_alignment > kPointerSize) {
6356        Label alignment_as_expected;
6357        DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
6358        andi(at, sp, frame_alignment_mask);
6359        Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
6360        // Don't use Check here, as it will call Runtime_Abort re-entering here.
6361        stop("Unexpected stack alignment");
6362        bind(&alignment_as_expected);
6363      }
6364    }
6365}
6366
6367
6368void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
6369    Register reg,
6370    Register scratch,
6371    Label* not_power_of_two_or_zero) {
6372  Dsubu(scratch, reg, Operand(1));
6373  Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt,
6374         scratch, Operand(zero_reg));
6375  and_(at, scratch, reg);  // In the delay slot.
6376  Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg));
6377}
6378
6379
6380void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) {
6381  DCHECK(!reg.is(overflow));
6382  mov(overflow, reg);  // Save original value.
6383  SmiTag(reg);
6384  xor_(overflow, overflow, reg);  // Overflow if (value ^ 2 * value) < 0.
6385}
6386
6387
6388void MacroAssembler::SmiTagCheckOverflow(Register dst,
6389                                         Register src,
6390                                         Register overflow) {
6391  if (dst.is(src)) {
6392    // Fall back to slower case.
6393    SmiTagCheckOverflow(dst, overflow);
6394  } else {
6395    DCHECK(!dst.is(src));
6396    DCHECK(!dst.is(overflow));
6397    DCHECK(!src.is(overflow));
6398    SmiTag(dst, src);
6399    xor_(overflow, dst, src);  // Overflow if (value ^ 2 * value) < 0.
6400  }
6401}
6402
6403
6404void MacroAssembler::SmiLoadUntag(Register dst, MemOperand src) {
6405  if (SmiValuesAre32Bits()) {
6406    lw(dst, UntagSmiMemOperand(src.rm(), src.offset()));
6407  } else {
6408    lw(dst, src);
6409    SmiUntag(dst);
6410  }
6411}
6412
6413
6414void MacroAssembler::SmiLoadScale(Register dst, MemOperand src, int scale) {
6415  if (SmiValuesAre32Bits()) {
6416    // TODO(plind): not clear if lw or ld faster here, need micro-benchmark.
6417    lw(dst, UntagSmiMemOperand(src.rm(), src.offset()));
6418    dsll(dst, dst, scale);
6419  } else {
6420    lw(dst, src);
6421    DCHECK(scale >= kSmiTagSize);
6422    sll(dst, dst, scale - kSmiTagSize);
6423  }
6424}
6425
6426
6427// Returns 2 values: the Smi and a scaled version of the int within the Smi.
6428void MacroAssembler::SmiLoadWithScale(Register d_smi,
6429                                      Register d_scaled,
6430                                      MemOperand src,
6431                                      int scale) {
6432  if (SmiValuesAre32Bits()) {
6433    ld(d_smi, src);
6434    dsra(d_scaled, d_smi, kSmiShift - scale);
6435  } else {
6436    lw(d_smi, src);
6437    DCHECK(scale >= kSmiTagSize);
6438    sll(d_scaled, d_smi, scale - kSmiTagSize);
6439  }
6440}
6441
6442
6443// Returns 2 values: the untagged Smi (int32) and scaled version of that int.
6444void MacroAssembler::SmiLoadUntagWithScale(Register d_int,
6445                                           Register d_scaled,
6446                                           MemOperand src,
6447                                           int scale) {
6448  if (SmiValuesAre32Bits()) {
6449    lw(d_int, UntagSmiMemOperand(src.rm(), src.offset()));
6450    dsll(d_scaled, d_int, scale);
6451  } else {
6452    lw(d_int, src);
6453    // Need both the int and the scaled in, so use two instructions.
6454    SmiUntag(d_int);
6455    sll(d_scaled, d_int, scale);
6456  }
6457}
6458
6459
6460void MacroAssembler::UntagAndJumpIfSmi(Register dst,
6461                                       Register src,
6462                                       Label* smi_case) {
6463  // DCHECK(!dst.is(src));
6464  JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT);
6465  SmiUntag(dst, src);
6466}
6467
6468
6469void MacroAssembler::UntagAndJumpIfNotSmi(Register dst,
6470                                          Register src,
6471                                          Label* non_smi_case) {
6472  // DCHECK(!dst.is(src));
6473  JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT);
6474  SmiUntag(dst, src);
6475}
6476
6477void MacroAssembler::JumpIfSmi(Register value,
6478                               Label* smi_label,
6479                               Register scratch,
6480                               BranchDelaySlot bd) {
6481  DCHECK_EQ(0, kSmiTag);
6482  andi(scratch, value, kSmiTagMask);
6483  Branch(bd, smi_label, eq, scratch, Operand(zero_reg));
6484}
6485
6486void MacroAssembler::JumpIfNotSmi(Register value,
6487                                  Label* not_smi_label,
6488                                  Register scratch,
6489                                  BranchDelaySlot bd) {
6490  DCHECK_EQ(0, kSmiTag);
6491  andi(scratch, value, kSmiTagMask);
6492  Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg));
6493}
6494
6495
6496void MacroAssembler::JumpIfNotBothSmi(Register reg1,
6497                                      Register reg2,
6498                                      Label* on_not_both_smi) {
6499  STATIC_ASSERT(kSmiTag == 0);
6500  // TODO(plind): Find some better to fix this assert issue.
6501#if defined(__APPLE__)
6502  DCHECK_EQ(1, kSmiTagMask);
6503#else
6504  DCHECK_EQ((int64_t)1, kSmiTagMask);
6505#endif
6506  or_(at, reg1, reg2);
6507  JumpIfNotSmi(at, on_not_both_smi);
6508}
6509
6510
6511void MacroAssembler::JumpIfEitherSmi(Register reg1,
6512                                     Register reg2,
6513                                     Label* on_either_smi) {
6514  STATIC_ASSERT(kSmiTag == 0);
6515  // TODO(plind): Find some better to fix this assert issue.
6516#if defined(__APPLE__)
6517  DCHECK_EQ(1, kSmiTagMask);
6518#else
6519  DCHECK_EQ((int64_t)1, kSmiTagMask);
6520#endif
6521  // Both Smi tags must be 1 (not Smi).
6522  and_(at, reg1, reg2);
6523  JumpIfSmi(at, on_either_smi);
6524}
6525
6526void MacroAssembler::AssertNotNumber(Register object) {
6527  if (emit_debug_code()) {
6528    STATIC_ASSERT(kSmiTag == 0);
6529    andi(at, object, kSmiTagMask);
6530    Check(ne, kOperandIsANumber, at, Operand(zero_reg));
6531    GetObjectType(object, t8, t8);
6532    Check(ne, kOperandIsNotANumber, t8, Operand(HEAP_NUMBER_TYPE));
6533  }
6534}
6535
6536void MacroAssembler::AssertNotSmi(Register object) {
6537  if (emit_debug_code()) {
6538    STATIC_ASSERT(kSmiTag == 0);
6539    andi(at, object, kSmiTagMask);
6540    Check(ne, kOperandIsASmi, at, Operand(zero_reg));
6541  }
6542}
6543
6544
6545void MacroAssembler::AssertSmi(Register object) {
6546  if (emit_debug_code()) {
6547    STATIC_ASSERT(kSmiTag == 0);
6548    andi(at, object, kSmiTagMask);
6549    Check(eq, kOperandIsASmi, at, Operand(zero_reg));
6550  }
6551}
6552
6553
6554void MacroAssembler::AssertString(Register object) {
6555  if (emit_debug_code()) {
6556    STATIC_ASSERT(kSmiTag == 0);
6557    SmiTst(object, t8);
6558    Check(ne, kOperandIsASmiAndNotAString, t8, Operand(zero_reg));
6559    GetObjectType(object, t8, t8);
6560    Check(lo, kOperandIsNotAString, t8, Operand(FIRST_NONSTRING_TYPE));
6561  }
6562}
6563
6564
6565void MacroAssembler::AssertName(Register object) {
6566  if (emit_debug_code()) {
6567    STATIC_ASSERT(kSmiTag == 0);
6568    SmiTst(object, t8);
6569    Check(ne, kOperandIsASmiAndNotAName, t8, Operand(zero_reg));
6570    GetObjectType(object, t8, t8);
6571    Check(le, kOperandIsNotAName, t8, Operand(LAST_NAME_TYPE));
6572  }
6573}
6574
6575
6576void MacroAssembler::AssertFunction(Register object) {
6577  if (emit_debug_code()) {
6578    STATIC_ASSERT(kSmiTag == 0);
6579    SmiTst(object, t8);
6580    Check(ne, kOperandIsASmiAndNotAFunction, t8, Operand(zero_reg));
6581    GetObjectType(object, t8, t8);
6582    Check(eq, kOperandIsNotAFunction, t8, Operand(JS_FUNCTION_TYPE));
6583  }
6584}
6585
6586
6587void MacroAssembler::AssertBoundFunction(Register object) {
6588  if (emit_debug_code()) {
6589    STATIC_ASSERT(kSmiTag == 0);
6590    SmiTst(object, t8);
6591    Check(ne, kOperandIsASmiAndNotABoundFunction, t8, Operand(zero_reg));
6592    GetObjectType(object, t8, t8);
6593    Check(eq, kOperandIsNotABoundFunction, t8, Operand(JS_BOUND_FUNCTION_TYPE));
6594  }
6595}
6596
6597void MacroAssembler::AssertGeneratorObject(Register object) {
6598  if (emit_debug_code()) {
6599    STATIC_ASSERT(kSmiTag == 0);
6600    SmiTst(object, t8);
6601    Check(ne, kOperandIsASmiAndNotAGeneratorObject, t8, Operand(zero_reg));
6602    GetObjectType(object, t8, t8);
6603    Check(eq, kOperandIsNotAGeneratorObject, t8,
6604          Operand(JS_GENERATOR_OBJECT_TYPE));
6605  }
6606}
6607
6608void MacroAssembler::AssertReceiver(Register object) {
6609  if (emit_debug_code()) {
6610    STATIC_ASSERT(kSmiTag == 0);
6611    SmiTst(object, t8);
6612    Check(ne, kOperandIsASmiAndNotAReceiver, t8, Operand(zero_reg));
6613    GetObjectType(object, t8, t8);
6614    Check(ge, kOperandIsNotAReceiver, t8, Operand(FIRST_JS_RECEIVER_TYPE));
6615  }
6616}
6617
6618
6619void MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
6620                                                     Register scratch) {
6621  if (emit_debug_code()) {
6622    Label done_checking;
6623    AssertNotSmi(object);
6624    LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
6625    Branch(&done_checking, eq, object, Operand(scratch));
6626    ld(t8, FieldMemOperand(object, HeapObject::kMapOffset));
6627    LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex);
6628    Assert(eq, kExpectedUndefinedOrCell, t8, Operand(scratch));
6629    bind(&done_checking);
6630  }
6631}
6632
6633
6634void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
6635  if (emit_debug_code()) {
6636    DCHECK(!reg.is(at));
6637    LoadRoot(at, index);
6638    Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at));
6639  }
6640}
6641
6642
6643void MacroAssembler::JumpIfNotHeapNumber(Register object,
6644                                         Register heap_number_map,
6645                                         Register scratch,
6646                                         Label* on_not_heap_number) {
6647  ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
6648  AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
6649  Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map));
6650}
6651
6652
6653void MacroAssembler::JumpIfNonSmisNotBothSequentialOneByteStrings(
6654    Register first, Register second, Register scratch1, Register scratch2,
6655    Label* failure) {
6656  // Test that both first and second are sequential one-byte strings.
6657  // Assume that they are non-smis.
6658  ld(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
6659  ld(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
6660  lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
6661  lbu(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
6662
6663  JumpIfBothInstanceTypesAreNotSequentialOneByte(scratch1, scratch2, scratch1,
6664                                                 scratch2, failure);
6665}
6666
6667
6668void MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register first,
6669                                                           Register second,
6670                                                           Register scratch1,
6671                                                           Register scratch2,
6672                                                           Label* failure) {
6673  // Check that neither is a smi.
6674  STATIC_ASSERT(kSmiTag == 0);
6675  And(scratch1, first, Operand(second));
6676  JumpIfSmi(scratch1, failure);
6677  JumpIfNonSmisNotBothSequentialOneByteStrings(first, second, scratch1,
6678                                               scratch2, failure);
6679}
6680
6681
6682void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
6683    Register first, Register second, Register scratch1, Register scratch2,
6684    Label* failure) {
6685  const int kFlatOneByteStringMask =
6686      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
6687  const int kFlatOneByteStringTag =
6688      kStringTag | kOneByteStringTag | kSeqStringTag;
6689  DCHECK(kFlatOneByteStringTag <= 0xffff);  // Ensure this fits 16-bit immed.
6690  andi(scratch1, first, kFlatOneByteStringMask);
6691  Branch(failure, ne, scratch1, Operand(kFlatOneByteStringTag));
6692  andi(scratch2, second, kFlatOneByteStringMask);
6693  Branch(failure, ne, scratch2, Operand(kFlatOneByteStringTag));
6694}
6695
6696
6697void MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(Register type,
6698                                                              Register scratch,
6699                                                              Label* failure) {
6700  const int kFlatOneByteStringMask =
6701      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
6702  const int kFlatOneByteStringTag =
6703      kStringTag | kOneByteStringTag | kSeqStringTag;
6704  And(scratch, type, Operand(kFlatOneByteStringMask));
6705  Branch(failure, ne, scratch, Operand(kFlatOneByteStringTag));
6706}
6707
6708static const int kRegisterPassedArguments = 8;
6709
6710int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
6711                                              int num_double_arguments) {
6712  int stack_passed_words = 0;
6713  num_reg_arguments += 2 * num_double_arguments;
6714
6715  // O32: Up to four simple arguments are passed in registers a0..a3.
6716  // N64: Up to eight simple arguments are passed in registers a0..a7.
6717  if (num_reg_arguments > kRegisterPassedArguments) {
6718    stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
6719  }
6720  stack_passed_words += kCArgSlotCount;
6721  return stack_passed_words;
6722}
6723
6724
6725void MacroAssembler::EmitSeqStringSetCharCheck(Register string,
6726                                               Register index,
6727                                               Register value,
6728                                               Register scratch,
6729                                               uint32_t encoding_mask) {
6730  Label is_object;
6731  SmiTst(string, at);
6732  Check(ne, kNonObject, at, Operand(zero_reg));
6733
6734  ld(at, FieldMemOperand(string, HeapObject::kMapOffset));
6735  lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
6736
6737  andi(at, at, kStringRepresentationMask | kStringEncodingMask);
6738  li(scratch, Operand(encoding_mask));
6739  Check(eq, kUnexpectedStringType, at, Operand(scratch));
6740
6741  // TODO(plind): requires Smi size check code for mips32.
6742
6743  ld(at, FieldMemOperand(string, String::kLengthOffset));
6744  Check(lt, kIndexIsTooLarge, index, Operand(at));
6745
6746  DCHECK(Smi::FromInt(0) == 0);
6747  Check(ge, kIndexIsNegative, index, Operand(zero_reg));
6748}
6749
6750
6751void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
6752                                          int num_double_arguments,
6753                                          Register scratch) {
6754  int frame_alignment = ActivationFrameAlignment();
6755
6756  // n64: Up to eight simple arguments in a0..a3, a4..a7, No argument slots.
6757  // O32: Up to four simple arguments are passed in registers a0..a3.
6758  // Those four arguments must have reserved argument slots on the stack for
6759  // mips, even though those argument slots are not normally used.
6760  // Both ABIs: Remaining arguments are pushed on the stack, above (higher
6761  // address than) the (O32) argument slots. (arg slot calculation handled by
6762  // CalculateStackPassedWords()).
6763  int stack_passed_arguments = CalculateStackPassedWords(
6764      num_reg_arguments, num_double_arguments);
6765  if (frame_alignment > kPointerSize) {
6766    // Make stack end at alignment and make room for num_arguments - 4 words
6767    // and the original value of sp.
6768    mov(scratch, sp);
6769    Dsubu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
6770    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
6771    And(sp, sp, Operand(-frame_alignment));
6772    sd(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
6773  } else {
6774    Dsubu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
6775  }
6776}
6777
6778
6779void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
6780                                          Register scratch) {
6781  PrepareCallCFunction(num_reg_arguments, 0, scratch);
6782}
6783
6784
6785void MacroAssembler::CallCFunction(ExternalReference function,
6786                                   int num_reg_arguments,
6787                                   int num_double_arguments) {
6788  li(t8, Operand(function));
6789  CallCFunctionHelper(t8, num_reg_arguments, num_double_arguments);
6790}
6791
6792
6793void MacroAssembler::CallCFunction(Register function,
6794                                   int num_reg_arguments,
6795                                   int num_double_arguments) {
6796  CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
6797}
6798
6799
6800void MacroAssembler::CallCFunction(ExternalReference function,
6801                                   int num_arguments) {
6802  CallCFunction(function, num_arguments, 0);
6803}
6804
6805
6806void MacroAssembler::CallCFunction(Register function,
6807                                   int num_arguments) {
6808  CallCFunction(function, num_arguments, 0);
6809}
6810
6811
6812void MacroAssembler::CallCFunctionHelper(Register function,
6813                                         int num_reg_arguments,
6814                                         int num_double_arguments) {
6815  DCHECK(has_frame());
6816  // Make sure that the stack is aligned before calling a C function unless
6817  // running in the simulator. The simulator has its own alignment check which
6818  // provides more information.
6819  // The argument stots are presumed to have been set up by
6820  // PrepareCallCFunction. The C function must be called via t9, for mips ABI.
6821
6822#if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64
6823  if (emit_debug_code()) {
6824    int frame_alignment = base::OS::ActivationFrameAlignment();
6825    int frame_alignment_mask = frame_alignment - 1;
6826    if (frame_alignment > kPointerSize) {
6827      DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
6828      Label alignment_as_expected;
6829      And(at, sp, Operand(frame_alignment_mask));
6830      Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
6831      // Don't use Check here, as it will call Runtime_Abort possibly
6832      // re-entering here.
6833      stop("Unexpected alignment in CallCFunction");
6834      bind(&alignment_as_expected);
6835    }
6836  }
6837#endif  // V8_HOST_ARCH_MIPS
6838
6839  // Just call directly. The function called cannot cause a GC, or
6840  // allow preemption, so the return address in the link register
6841  // stays correct.
6842
6843  if (!function.is(t9)) {
6844    mov(t9, function);
6845    function = t9;
6846  }
6847
6848  Call(function);
6849
6850  int stack_passed_arguments = CalculateStackPassedWords(
6851      num_reg_arguments, num_double_arguments);
6852
6853  if (base::OS::ActivationFrameAlignment() > kPointerSize) {
6854    ld(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
6855  } else {
6856    Daddu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
6857  }
6858}
6859
6860
6861#undef BRANCH_ARGS_CHECK
6862
6863
6864void MacroAssembler::CheckPageFlag(
6865    Register object,
6866    Register scratch,
6867    int mask,
6868    Condition cc,
6869    Label* condition_met) {
6870  And(scratch, object, Operand(~Page::kPageAlignmentMask));
6871  ld(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
6872  And(scratch, scratch, Operand(mask));
6873  Branch(condition_met, cc, scratch, Operand(zero_reg));
6874}
6875
6876
6877void MacroAssembler::JumpIfBlack(Register object,
6878                                 Register scratch0,
6879                                 Register scratch1,
6880                                 Label* on_black) {
6881  HasColor(object, scratch0, scratch1, on_black, 1, 1);  // kBlackBitPattern.
6882  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
6883}
6884
6885
6886void MacroAssembler::HasColor(Register object,
6887                              Register bitmap_scratch,
6888                              Register mask_scratch,
6889                              Label* has_color,
6890                              int first_bit,
6891                              int second_bit) {
6892  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t8));
6893  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t9));
6894
6895  GetMarkBits(object, bitmap_scratch, mask_scratch);
6896
6897  Label other_color;
6898  // Note that we are using two 4-byte aligned loads.
6899  LoadWordPair(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
6900  And(t8, t9, Operand(mask_scratch));
6901  Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg));
6902  // Shift left 1 by adding.
6903  Daddu(mask_scratch, mask_scratch, Operand(mask_scratch));
6904  And(t8, t9, Operand(mask_scratch));
6905  Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg));
6906
6907  bind(&other_color);
6908}
6909
6910
6911void MacroAssembler::GetMarkBits(Register addr_reg,
6912                                 Register bitmap_reg,
6913                                 Register mask_reg) {
6914  DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
6915  // addr_reg is divided into fields:
6916  // |63        page base        20|19    high      8|7   shift   3|2  0|
6917  // 'high' gives the index of the cell holding color bits for the object.
6918  // 'shift' gives the offset in the cell for this object's color.
6919  And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask));
6920  Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2);
6921  const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
6922  Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits);
6923  Dlsa(bitmap_reg, bitmap_reg, t8, Bitmap::kBytesPerCellLog2);
6924  li(t8, Operand(1));
6925  dsllv(mask_reg, t8, mask_reg);
6926}
6927
6928
6929void MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
6930                                 Register mask_scratch, Register load_scratch,
6931                                 Label* value_is_white) {
6932  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, t8));
6933  GetMarkBits(value, bitmap_scratch, mask_scratch);
6934
6935  // If the value is black or grey we don't need to do anything.
6936  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
6937  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
6938  DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
6939  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
6940
6941  // Since both black and grey have a 1 in the first position and white does
6942  // not have a 1 there we only need to check one bit.
6943  // Note that we are using a 4-byte aligned 8-byte load.
6944  if (emit_debug_code()) {
6945    LoadWordPair(load_scratch,
6946                 MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
6947  } else {
6948    lwu(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
6949  }
6950  And(t8, mask_scratch, load_scratch);
6951  Branch(value_is_white, eq, t8, Operand(zero_reg));
6952}
6953
6954
6955void MacroAssembler::LoadInstanceDescriptors(Register map,
6956                                             Register descriptors) {
6957  ld(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
6958}
6959
6960
6961void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
6962  lwu(dst, FieldMemOperand(map, Map::kBitField3Offset));
6963  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
6964}
6965
6966
6967void MacroAssembler::EnumLength(Register dst, Register map) {
6968  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
6969  lwu(dst, FieldMemOperand(map, Map::kBitField3Offset));
6970  And(dst, dst, Operand(Map::EnumLengthBits::kMask));
6971  SmiTag(dst);
6972}
6973
6974
6975void MacroAssembler::LoadAccessor(Register dst, Register holder,
6976                                  int accessor_index,
6977                                  AccessorComponent accessor) {
6978  ld(dst, FieldMemOperand(holder, HeapObject::kMapOffset));
6979  LoadInstanceDescriptors(dst, dst);
6980  ld(dst,
6981     FieldMemOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
6982  int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
6983                                           : AccessorPair::kSetterOffset;
6984  ld(dst, FieldMemOperand(dst, offset));
6985}
6986
6987
6988void MacroAssembler::CheckEnumCache(Label* call_runtime) {
6989  Register null_value = a5;
6990  Register  empty_fixed_array_value = a6;
6991  LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
6992  Label next, start;
6993  mov(a2, a0);
6994
6995  // Check if the enum length field is properly initialized, indicating that
6996  // there is an enum cache.
6997  ld(a1, FieldMemOperand(a2, HeapObject::kMapOffset));
6998
6999  EnumLength(a3, a1);
7000  Branch(
7001      call_runtime, eq, a3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel)));
7002
7003  LoadRoot(null_value, Heap::kNullValueRootIndex);
7004  jmp(&start);
7005
7006  bind(&next);
7007  ld(a1, FieldMemOperand(a2, HeapObject::kMapOffset));
7008
7009  // For all objects but the receiver, check that the cache is empty.
7010  EnumLength(a3, a1);
7011  Branch(call_runtime, ne, a3, Operand(Smi::FromInt(0)));
7012
7013  bind(&start);
7014
7015  // Check that there are no elements. Register a2 contains the current JS
7016  // object we've reached through the prototype chain.
7017  Label no_elements;
7018  ld(a2, FieldMemOperand(a2, JSObject::kElementsOffset));
7019  Branch(&no_elements, eq, a2, Operand(empty_fixed_array_value));
7020
7021  // Second chance, the object may be using the empty slow element dictionary.
7022  LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex);
7023  Branch(call_runtime, ne, a2, Operand(at));
7024
7025  bind(&no_elements);
7026  ld(a2, FieldMemOperand(a1, Map::kPrototypeOffset));
7027  Branch(&next, ne, a2, Operand(null_value));
7028}
7029
7030
7031void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
7032  DCHECK(!output_reg.is(input_reg));
7033  Label done;
7034  li(output_reg, Operand(255));
7035  // Normal branch: nop in delay slot.
7036  Branch(&done, gt, input_reg, Operand(output_reg));
7037  // Use delay slot in this branch.
7038  Branch(USE_DELAY_SLOT, &done, lt, input_reg, Operand(zero_reg));
7039  mov(output_reg, zero_reg);  // In delay slot.
7040  mov(output_reg, input_reg);  // Value is in range 0..255.
7041  bind(&done);
7042}
7043
7044
7045void MacroAssembler::ClampDoubleToUint8(Register result_reg,
7046                                        DoubleRegister input_reg,
7047                                        DoubleRegister temp_double_reg) {
7048  Label above_zero;
7049  Label done;
7050  Label in_bounds;
7051
7052  Move(temp_double_reg, 0.0);
7053  BranchF(&above_zero, NULL, gt, input_reg, temp_double_reg);
7054
7055  // Double value is less than zero, NaN or Inf, return 0.
7056  mov(result_reg, zero_reg);
7057  Branch(&done);
7058
7059  // Double value is >= 255, return 255.
7060  bind(&above_zero);
7061  Move(temp_double_reg, 255.0);
7062  BranchF(&in_bounds, NULL, le, input_reg, temp_double_reg);
7063  li(result_reg, Operand(255));
7064  Branch(&done);
7065
7066  // In 0-255 range, round and truncate.
7067  bind(&in_bounds);
7068  cvt_w_d(temp_double_reg, input_reg);
7069  mfc1(result_reg, temp_double_reg);
7070  bind(&done);
7071}
7072
7073void MacroAssembler::TestJSArrayForAllocationMemento(Register receiver_reg,
7074                                                     Register scratch_reg,
7075                                                     Label* no_memento_found) {
7076  Label map_check;
7077  Label top_check;
7078  ExternalReference new_space_allocation_top_adr =
7079      ExternalReference::new_space_allocation_top_address(isolate());
7080  const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
7081  const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
7082
7083  // Bail out if the object is not in new space.
7084  JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
7085  // If the object is in new space, we need to check whether it is on the same
7086  // page as the current top.
7087  Daddu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
7088  li(at, Operand(new_space_allocation_top_adr));
7089  ld(at, MemOperand(at));
7090  Xor(scratch_reg, scratch_reg, Operand(at));
7091  And(scratch_reg, scratch_reg, Operand(~Page::kPageAlignmentMask));
7092  Branch(&top_check, eq, scratch_reg, Operand(zero_reg));
7093  // The object is on a different page than allocation top. Bail out if the
7094  // object sits on the page boundary as no memento can follow and we cannot
7095  // touch the memory following it.
7096  Daddu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
7097  Xor(scratch_reg, scratch_reg, Operand(receiver_reg));
7098  And(scratch_reg, scratch_reg, Operand(~Page::kPageAlignmentMask));
7099  Branch(no_memento_found, ne, scratch_reg, Operand(zero_reg));
7100  // Continue with the actual map check.
7101  jmp(&map_check);
7102  // If top is on the same page as the current object, we need to check whether
7103  // we are below top.
7104  bind(&top_check);
7105  Daddu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
7106  li(at, Operand(new_space_allocation_top_adr));
7107  ld(at, MemOperand(at));
7108  Branch(no_memento_found, gt, scratch_reg, Operand(at));
7109  // Memento map check.
7110  bind(&map_check);
7111  ld(scratch_reg, MemOperand(receiver_reg, kMementoMapOffset));
7112  Branch(no_memento_found, ne, scratch_reg,
7113         Operand(isolate()->factory()->allocation_memento_map()));
7114}
7115
7116
7117Register GetRegisterThatIsNotOneOf(Register reg1,
7118                                   Register reg2,
7119                                   Register reg3,
7120                                   Register reg4,
7121                                   Register reg5,
7122                                   Register reg6) {
7123  RegList regs = 0;
7124  if (reg1.is_valid()) regs |= reg1.bit();
7125  if (reg2.is_valid()) regs |= reg2.bit();
7126  if (reg3.is_valid()) regs |= reg3.bit();
7127  if (reg4.is_valid()) regs |= reg4.bit();
7128  if (reg5.is_valid()) regs |= reg5.bit();
7129  if (reg6.is_valid()) regs |= reg6.bit();
7130
7131  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
7132  for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
7133    int code = config->GetAllocatableGeneralCode(i);
7134    Register candidate = Register::from_code(code);
7135    if (regs & candidate.bit()) continue;
7136    return candidate;
7137  }
7138  UNREACHABLE();
7139  return no_reg;
7140}
7141
7142
7143void MacroAssembler::JumpIfDictionaryInPrototypeChain(
7144    Register object,
7145    Register scratch0,
7146    Register scratch1,
7147    Label* found) {
7148  DCHECK(!scratch1.is(scratch0));
7149  Factory* factory = isolate()->factory();
7150  Register current = scratch0;
7151  Label loop_again, end;
7152
7153  // Scratch contained elements pointer.
7154  Move(current, object);
7155  ld(current, FieldMemOperand(current, HeapObject::kMapOffset));
7156  ld(current, FieldMemOperand(current, Map::kPrototypeOffset));
7157  Branch(&end, eq, current, Operand(factory->null_value()));
7158
7159  // Loop based on the map going up the prototype chain.
7160  bind(&loop_again);
7161  ld(current, FieldMemOperand(current, HeapObject::kMapOffset));
7162  lbu(scratch1, FieldMemOperand(current, Map::kInstanceTypeOffset));
7163  STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
7164  STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
7165  Branch(found, lo, scratch1, Operand(JS_OBJECT_TYPE));
7166  lb(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
7167  DecodeField<Map::ElementsKindBits>(scratch1);
7168  Branch(found, eq, scratch1, Operand(DICTIONARY_ELEMENTS));
7169  ld(current, FieldMemOperand(current, Map::kPrototypeOffset));
7170  Branch(&loop_again, ne, current, Operand(factory->null_value()));
7171
7172  bind(&end);
7173}
7174
7175
7176bool AreAliased(Register reg1, Register reg2, Register reg3, Register reg4,
7177                Register reg5, Register reg6, Register reg7, Register reg8,
7178                Register reg9, Register reg10) {
7179  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() + reg3.is_valid() +
7180                        reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
7181                        reg7.is_valid() + reg8.is_valid() + reg9.is_valid() +
7182                        reg10.is_valid();
7183
7184  RegList regs = 0;
7185  if (reg1.is_valid()) regs |= reg1.bit();
7186  if (reg2.is_valid()) regs |= reg2.bit();
7187  if (reg3.is_valid()) regs |= reg3.bit();
7188  if (reg4.is_valid()) regs |= reg4.bit();
7189  if (reg5.is_valid()) regs |= reg5.bit();
7190  if (reg6.is_valid()) regs |= reg6.bit();
7191  if (reg7.is_valid()) regs |= reg7.bit();
7192  if (reg8.is_valid()) regs |= reg8.bit();
7193  if (reg9.is_valid()) regs |= reg9.bit();
7194  if (reg10.is_valid()) regs |= reg10.bit();
7195  int n_of_non_aliasing_regs = NumRegs(regs);
7196
7197  return n_of_valid_regs != n_of_non_aliasing_regs;
7198}
7199
7200
7201CodePatcher::CodePatcher(Isolate* isolate, byte* address, int instructions,
7202                         FlushICache flush_cache)
7203    : address_(address),
7204      size_(instructions * Assembler::kInstrSize),
7205      masm_(isolate, address, size_ + Assembler::kGap, CodeObjectRequired::kNo),
7206      flush_cache_(flush_cache) {
7207  // Create a new macro assembler pointing to the address of the code to patch.
7208  // The size is adjusted with kGap on order for the assembler to generate size
7209  // bytes of instructions without failing with buffer size constraints.
7210  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
7211}
7212
7213
7214CodePatcher::~CodePatcher() {
7215  // Indicate that code has changed.
7216  if (flush_cache_ == FLUSH) {
7217    Assembler::FlushICache(masm_.isolate(), address_, size_);
7218  }
7219  // Check that the code was patched as expected.
7220  DCHECK(masm_.pc_ == address_ + size_);
7221  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
7222}
7223
7224
7225void CodePatcher::Emit(Instr instr) {
7226  masm()->emit(instr);
7227}
7228
7229
7230void CodePatcher::Emit(Address addr) {
7231  // masm()->emit(reinterpret_cast<Instr>(addr));
7232}
7233
7234
7235void CodePatcher::ChangeBranchCondition(Instr current_instr,
7236                                        uint32_t new_opcode) {
7237  current_instr = (current_instr & ~kOpcodeMask) | new_opcode;
7238  masm_.emit(current_instr);
7239}
7240
7241
7242void MacroAssembler::TruncatingDiv(Register result,
7243                                   Register dividend,
7244                                   int32_t divisor) {
7245  DCHECK(!dividend.is(result));
7246  DCHECK(!dividend.is(at));
7247  DCHECK(!result.is(at));
7248  base::MagicNumbersForDivision<uint32_t> mag =
7249  base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
7250  li(at, Operand(static_cast<int32_t>(mag.multiplier)));
7251  Mulh(result, dividend, Operand(at));
7252  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
7253  if (divisor > 0 && neg) {
7254    Addu(result, result, Operand(dividend));
7255  }
7256  if (divisor < 0 && !neg && mag.multiplier > 0) {
7257    Subu(result, result, Operand(dividend));
7258  }
7259  if (mag.shift > 0) sra(result, result, mag.shift);
7260  srl(at, dividend, 31);
7261  Addu(result, result, Operand(at));
7262}
7263
7264
7265}  // namespace internal
7266}  // namespace v8
7267
7268#endif  // V8_TARGET_ARCH_MIPS64
7269