13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
43100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include <limits.h>  // For LONG_MIN, LONG_MAX.
63100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_MIPS
8f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/division-by-constant.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/mips/macro-assembler-mips.h"
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/register-configuration.h"
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h"
173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 {
193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal {
203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               CodeObjectRequired create_code_object)
23257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    : Assembler(arg_isolate, buffer, size),
243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      generating_stub_(false),
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      has_frame_(false),
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      has_double_zero_reg_set_(false) {
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (create_code_object == CodeObjectRequired::kYes) {
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    code_object_ =
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<Object>::New(isolate()->heap()->undefined_value(), isolate());
30257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Load(Register dst,
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const MemOperand& src,
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Representation r) {
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8()) {
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lb(dst, src);
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger8()) {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lbu(dst, src);
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16()) {
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lh(dst, src);
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger16()) {
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lhu(dst, src);
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lw(dst, src);
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Store(Register src,
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           const MemOperand& dst,
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Representation r) {
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8() || r.IsUInteger8()) {
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sb(src, dst);
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16() || r.IsUInteger16()) {
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sh(src, dst);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (r.IsHeapObject()) {
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertNotSmi(src);
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (r.IsSmi()) {
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertSmi(src);
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sw(src, dst);
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::LoadRoot(Register destination,
703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Heap::RootListIndex index) {
716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(destination, MemOperand(s6, index << kPointerSizeLog2));
723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::LoadRoot(Register destination,
763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Heap::RootListIndex index,
773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Condition cond,
783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Register src1, const Operand& src2) {
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(2, NegateCondition(cond), src1, src2);
806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(destination, MemOperand(s6, index << kPointerSizeLog2));
813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::StoreRoot(Register source,
8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Heap::RootListIndex index) {
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(source, MemOperand(s6, index << kPointerSizeLog2));
8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::StoreRoot(Register source,
9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Heap::RootListIndex index,
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Condition cond,
9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register src1, const Operand& src2) {
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(2, NegateCondition(cond), src1, src2);
9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(source, MemOperand(s6, index << kPointerSizeLog2));
9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PushCommonFrame(Register marker_reg) {
1013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (marker_reg.is_valid()) {
1023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(ra, fp, marker_reg);
1033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Addu(fp, sp, Operand(kPointerSize));
1043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
1053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(ra, fp);
1063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(fp, sp);
1073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
1093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PopCommonFrame(Register marker_reg) {
1113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (marker_reg.is_valid()) {
1123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Pop(ra, fp, marker_reg);
1133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
1143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Pop(ra, fp);
1153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
1173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PushStandardFrame(Register function_reg) {
1193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int offset = -StandardFrameConstants::kContextOffset;
1203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (function_reg.is_valid()) {
1213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(ra, fp, cp, function_reg);
1223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    offset += kPointerSize;
1233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
1243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(ra, fp, cp);
1253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Addu(fp, sp, Operand(offset));
1273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Push and pop all registers that can hold pointers.
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::PushSafepointRegisters() {
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Safepoints expect a block of kNumSafepointRegisters values on the
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // stack, so adjust the stack for unsaved registers.
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(num_unsaved >= 0);
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (num_unsaved > 0) {
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Subu(sp, sp, Operand(num_unsaved * kPointerSize));
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  MultiPush(kSafepointSavedRegisters);
139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::PopSafepointRegisters() {
143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  MultiPop(kSafepointSavedRegisters);
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (num_unsaved > 0) {
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Addu(sp, sp, Operand(num_unsaved * kPointerSize));
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(src, SafepointRegisterSlot(dst));
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(dst, SafepointRegisterSlot(src));
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The registers are pushed starting with the highest encoding,
163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // which means that lowest encodings are closest to the stack pointer.
164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return kSafepointRegisterStackIndexMap[reg_code];
165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochMemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochMemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNIMPLEMENTED_MIPS();
175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // General purpose registers are pushed last on the stack.
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int doubles_size = DoubleRegister::kMaxNumRegisters * kDoubleSize;
177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return MemOperand(sp, doubles_size + register_offset);
179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
18244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::InNewSpace(Register object,
18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Register scratch,
18444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Condition cc,
18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Label* branch) {
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == eq || cc == ne);
187f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CheckPageFlag(object, scratch, MemoryChunk::kIsInNewSpaceMask, cc, branch);
18844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Clobbers object, dst, value, and ra, if (ra_status == kRAHasBeenSaved)
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// The register 'object' contains a heap object pointer.  The heap object
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// tag is shifted away.
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField(
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset,
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register dst,
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RAStatus ra_status,
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RememberedSetAction remembered_set_action,
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(value, dst, t8, object));
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First, check if a write barrier is even needed. The tests below
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
20785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  Label done;
20844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Although the object register is tagged, the offset is relative to the start
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(offset, kPointerSize));
217592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(dst, object, Operand(offset - kHeapObjectTag));
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    And(t8, dst, Operand((1 << kPointerSizeLog2) - 1));
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&ok, eq, t8, Operand(zero_reg));
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    stop("Unaligned cell in write barrier");
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWrite(object,
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              dst,
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              value,
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              ra_status,
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              save_fp,
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              remembered_set_action,
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK,
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              pointers_to_here_check_for_value);
23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
23644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
23744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
23944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // turned on to provoke errors.
240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(value, Operand(bit_cast<int32_t>(kZapValue + 4)));
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(dst, Operand(bit_cast<int32_t>(kZapValue + 8)));
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Clobbers object, dst, map, and ra, if (ra_status == kRAHasBeenSaved)
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteForMap(Register object,
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register map,
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register dst,
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       RAStatus ra_status,
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       SaveFPRegsMode fp_mode) {
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(at));
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lw(dst, FieldMemOperand(map, HeapObject::kMapOffset));
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(eq,
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kWrongAddressOrValuePassedToRecordWrite,
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          dst,
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Operand(isolate()->factory()->meta_map()));
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_incremental_marking) {
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lw(at, FieldMemOperand(object, HeapObject::kMapOffset));
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(eq,
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kWrongAddressOrValuePassedToRecordWrite,
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          map,
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Operand(at));
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // A single check of the map's pages interesting flag suffices, since it is
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // only set during incremental collection, and then it's also guaranteed that
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the from object's page's interesting flag is also set.  This optimization
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // relies on the fact that maps can never be in new space.
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckPageFlag(map,
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                map,  // Used as scratch.
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                MemoryChunk::kPointersToHereAreInterestingMask,
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                eq,
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                &done);
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Addu(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag));
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    And(at, dst, Operand((1 << kPointerSizeLog2) - 1));
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Branch(&ok, eq, at, Operand(zero_reg));
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stop("Unaligned cell in write barrier");
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record the actual write.
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (ra_status == kRAHasNotBeenSaved) {
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    push(ra);
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (ra_status == kRAHasNotBeenSaved) {
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pop(ra);
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, at, dst);
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(dst, Operand(bit_cast<int32_t>(kZapValue + 12)));
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(map, Operand(bit_cast<int32_t>(kZapValue + 16)));
31744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
31844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
31944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
32044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Clobbers object, address, value, and ra, if (ra_status == kRAHasBeenSaved)
322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// The register 'object' contains a heap object pointer.  The heap object
32344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// tag is shifted away.
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWrite(
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register address,
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RAStatus ra_status,
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode fp_mode,
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, address, value, t8));
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, address, value, t9));
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(at, MemOperand(address));
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Assert(
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value));
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
341c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (remembered_set_action == OMIT_REMEMBERED_SET &&
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !FLAG_incremental_marking) {
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // First, check if a write barrier is even needed. The tests below
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // catch stores of smis and stores into the young generation.
34944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done;
35044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(0, kSmiTag);
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckPageFlag(value,
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  value,  // Used as scratch.
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  MemoryChunk::kPointersToHereAreInterestingMask,
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  eq,
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &done);
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(object,
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                eq,
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done);
36844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
36944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Record the actual write.
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (ra_status == kRAHasNotBeenSaved) {
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(ra);
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub);
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (ra_status == kRAHasNotBeenSaved) {
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    pop(ra);
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, at,
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   value);
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
38844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // turned on to provoke errors.
389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(address, Operand(bit_cast<int32_t>(kZapValue + 12)));
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(value, Operand(bit_cast<int32_t>(kZapValue + 16)));
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
395109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::RecordWriteCodeEntryField(Register js_function,
396109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register code_entry,
397109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register scratch) {
398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int offset = JSFunction::kCodeEntryOffset;
399109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Since a code entry (value) is always in old space, we don't need to update
401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // remembered set. If incremental marking is off, there is nothing for us to
402109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // do.
403109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!FLAG_incremental_marking) return;
404109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(js_function.is(a1));
406109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(code_entry.is(t0));
407109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(scratch.is(t1));
408109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  AssertNotSmi(js_function);
409109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
410109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
411109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Addu(scratch, js_function, Operand(offset - kHeapObjectTag));
412109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    lw(at, MemOperand(scratch));
413109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Assert(eq, kWrongAddressOrValuePassedToRecordWrite, at,
414109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch           Operand(code_entry));
415109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
416109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
417109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // First, check if a write barrier is even needed. The tests below
418109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // catch stores of Smis and stores into young gen.
419109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label done;
420109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
421109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(code_entry, scratch,
422109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersToHereAreInterestingMask, eq, &done);
423109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(js_function, scratch,
424109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask, eq, &done);
425109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
426109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const Register dst = scratch;
427109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Addu(dst, js_function, Operand(offset - kHeapObjectTag));
428109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
429109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save caller-saved registers. js_function and code_entry are in the
430109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // caller-saved register list.
431109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(kJSCallerSaved & js_function.bit());
432109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(kJSCallerSaved & code_entry.bit());
433109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  MultiPush(kJSCallerSaved | ra.bit());
434109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int argument_count = 3;
436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PrepareCallCFunction(argument_count, 0, code_entry);
438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(a0, js_function);
440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mov(a1, dst);
441109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  li(a2, Operand(ExternalReference::isolate_address(isolate())));
442109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
443109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  {
444109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    AllowExternalCallThatCantCauseGC scope(this);
445109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallCFunction(
446109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        ExternalReference::incremental_marking_record_write_code_entry_function(
447109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            isolate()),
448109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        argument_count);
449109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
450109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
451109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore caller-saved registers.
452109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  MultiPop(kJSCallerSaved | ra.bit());
453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
454109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&done);
455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register address,
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch,
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         SaveFPRegsMode fp_mode,
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         RememberedSetFinalAction and_then) {
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfNotInNewSpace(object, scratch, &ok);
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    stop("Remembered set pointer is in new space");
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load store buffer top.
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference store_buffer =
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference::store_buffer_top(isolate());
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(store_buffer));
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, MemOperand(t8));
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store pointer to buffer and increment buffer top.
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(address, MemOperand(scratch));
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(scratch, scratch, kPointerSize);
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Write back new top of buffer.
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(scratch, MemOperand(t8));
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call stub on end of buffer.
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for end of buffer.
4813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  And(t8, scratch, Operand(StoreBuffer::kStoreBufferMask));
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kFallThroughAtEnd) {
4833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Branch(&done, ne, t8, Operand(zero_reg));
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kReturnAtEnd);
4863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Ret(ne, t8, Operand(zero_reg));
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(ra);
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub store_buffer_overflow(isolate(), fp_mode);
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&store_buffer_overflow);
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(ra);
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Ret();
49544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
49644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
49744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
49844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
49944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// -----------------------------------------------------------------------------
500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Allocation support.
50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Compute the hash code from the untagged key.  This must be kept in sync with
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code-stub-hydrogen.cc
506c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register reg0, Register scratch) {
507c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // First of all we assign the hash seed to scratch.
508c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  LoadRoot(scratch, Heap::kHashSeedRootIndex);
509c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  SmiUntag(scratch);
510c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
511c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Xor original key with a seed.
512c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xor_(reg0, reg0, scratch);
513c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
514c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Compute the hash code from the untagged key.  This must be kept in sync
515c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // with ComputeIntegerHash in utils.h.
516c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  //
517c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = ~hash + (hash << 15);
518c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  nor(scratch, reg0, zero_reg);
519109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Lsa(reg0, scratch, reg0, 15);
520c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
521c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 12);
522c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  srl(at, reg0, 12);
523c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xor_(reg0, reg0, at);
524c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
525c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash + (hash << 2);
526109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Lsa(reg0, reg0, reg0, 2);
527c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
528c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 4);
529c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  srl(at, reg0, 4);
530c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xor_(reg0, reg0, at);
531c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
532c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash * 2057;
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sll(scratch, reg0, 11);
534109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Lsa(reg0, reg0, reg0, 3);
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addu(reg0, reg0, scratch);
536c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
537c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 16);
538c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  srl(at, reg0, 16);
539c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xor_(reg0, reg0, at);
540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  And(reg0, reg0, Operand(0x3fffffff));
541c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
542c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
5433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ---------------------------------------------------------------------------
544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Instruction macros.
5453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
54644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) {
5473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    addu(rd, rs, rt.rm());
5493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
55044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      addiu(rd, rs, rt.imm32_);
5523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
5533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!rs.is(at));
5553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
55644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      addu(rd, rs, at);
5573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
5583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
5593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
56244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) {
5633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
56444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    subu(rd, rs, rt.rm());
5653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
56644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
56744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      addiu(rd, rs, -rt.imm32_);  // No subiu instr, use addiu(x, y, -imm).
5683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
5693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!rs.is(at));
5713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
57244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      subu(rd, rs, at);
5733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
5743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
5753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) {
5793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsMipsArchVariant(kLoongson)) {
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mult(rs, rt.rm());
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mflo(rd);
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mul(rd, rs, rt.rm());
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
5873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rs.is(at));
5893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsMipsArchVariant(kLoongson)) {
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mult(rs, at);
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mflo(rd);
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mul(rd, rs, at);
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
5973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Mul(Register rd_hi, Register rd_lo,
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register rs, const Operand& rt) {
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (rt.is_reg()) {
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!IsMipsArchVariant(kMips32r6)) {
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mult(rs, rt.rm());
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mflo(rd_lo);
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mfhi(rd_hi);
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (rd_lo.is(rs)) {
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!rd_hi.is(rs));
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!rd_hi.is(rt.rm()) && !rd_lo.is(rt.rm()));
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        muh(rd_hi, rs, rt.rm());
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mul(rd_lo, rs, rt.rm());
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!rd_hi.is(rt.rm()) && !rd_lo.is(rt.rm()));
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mul(rd_lo, rs, rt.rm());
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        muh(rd_hi, rs, rt.rm());
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // li handles the relocation.
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rs.is(at));
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(at, rt);
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!IsMipsArchVariant(kMips32r6)) {
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mult(rs, at);
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mflo(rd_lo);
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mfhi(rd_hi);
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (rd_lo.is(rs)) {
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!rd_hi.is(rs));
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!rd_hi.is(at) && !rd_lo.is(at));
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        muh(rd_hi, rs, at);
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mul(rd_lo, rs, at);
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!rd_hi.is(at) && !rd_lo.is(at));
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mul(rd_lo, rs, at);
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        muh(rd_hi, rs, at);
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::Mulu(Register rd_hi, Register rd_lo, Register rs,
6433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                          const Operand& rt) {
6443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register reg;
6453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (rt.is_reg()) {
6463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    reg = rt.rm();
6473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
6483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!rs.is(at));
6493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    reg = at;
6503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    li(reg, rt);
6513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
6523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
6533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (!IsMipsArchVariant(kMips32r6)) {
6543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    multu(rs, reg);
6553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mflo(rd_lo);
6563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mfhi(rd_hi);
6573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
6583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (rd_lo.is(rs)) {
6593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      DCHECK(!rd_hi.is(rs));
6603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      DCHECK(!rd_hi.is(reg) && !rd_lo.is(reg));
6613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      muhu(rd_hi, rs, reg);
6623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      mulu(rd_lo, rs, reg);
6633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
6643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      DCHECK(!rd_hi.is(reg) && !rd_lo.is(reg));
6653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      mulu(rd_lo, rs, reg);
6663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      muhu(rd_hi, rs, reg);
6673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
6683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
6693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Mulh(Register rd, Register rs, const Operand& rt) {
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (rt.is_reg()) {
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!IsMipsArchVariant(kMips32r6)) {
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mult(rs, rt.rm());
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mfhi(rd);
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      muh(rd, rs, rt.rm());
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // li handles the relocation.
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rs.is(at));
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(at, rt);
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!IsMipsArchVariant(kMips32r6)) {
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mult(rs, at);
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mfhi(rd);
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      muh(rd, rs, at);
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Mult(Register rs, const Operand& rt) {
6943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
6953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    mult(rs, rt.rm());
6963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
6973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rs.is(at));
6993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
7003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    mult(rs, at);
7013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
7023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
7033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Mulhu(Register rd, Register rs, const Operand& rt) {
706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (rt.is_reg()) {
707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!IsMipsArchVariant(kMips32r6)) {
708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      multu(rs, rt.rm());
709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mfhi(rd);
710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      muhu(rd, rs, rt.rm());
712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // li handles the relocation.
715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!rs.is(at));
716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    li(at, rt);
717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!IsMipsArchVariant(kMips32r6)) {
718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      multu(rs, at);
719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mfhi(rd);
720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
721958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      muhu(rd, rs, at);
722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Multu(Register rs, const Operand& rt) {
7283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
7293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    multu(rs, rt.rm());
7303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
7313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rs.is(at));
7333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
7343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    multu(rs, at);
7353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
7363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
7373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Div(Register rs, const Operand& rt) {
7403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
7413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    div(rs, rt.rm());
7423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
7433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rs.is(at));
7453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
7463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    div(rs, at);
7473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
7483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
7493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Div(Register rem, Register res,
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register rs, const Operand& rt) {
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (rt.is_reg()) {
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!IsMipsArchVariant(kMips32r6)) {
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      div(rs, rt.rm());
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mflo(res);
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mfhi(rem);
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      div(res, rs, rt.rm());
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mod(rem, rs, rt.rm());
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // li handles the relocation.
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rs.is(at));
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(at, rt);
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!IsMipsArchVariant(kMips32r6)) {
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      div(rs, at);
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mflo(res);
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mfhi(rem);
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      div(res, rs, at);
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mod(rem, rs, at);
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Div(Register res, Register rs, const Operand& rt) {
779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (rt.is_reg()) {
780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!IsMipsArchVariant(kMips32r6)) {
781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      div(rs, rt.rm());
782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mflo(res);
783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      div(res, rs, rt.rm());
785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // li handles the relocation.
788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!rs.is(at));
789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    li(at, rt);
790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!IsMipsArchVariant(kMips32r6)) {
791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      div(rs, at);
792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mflo(res);
793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      div(res, rs, at);
795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Mod(Register rd, Register rs, const Operand& rt) {
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (rt.is_reg()) {
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!IsMipsArchVariant(kMips32r6)) {
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      div(rs, rt.rm());
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mfhi(rd);
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mod(rd, rs, rt.rm());
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // li handles the relocation.
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rs.is(at));
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(at, rt);
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!IsMipsArchVariant(kMips32r6)) {
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      div(rs, at);
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mfhi(rd);
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mod(rd, rs, at);
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Modu(Register rd, Register rs, const Operand& rt) {
823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (rt.is_reg()) {
824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!IsMipsArchVariant(kMips32r6)) {
825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      divu(rs, rt.rm());
826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mfhi(rd);
827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      modu(rd, rs, rt.rm());
829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // li handles the relocation.
832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!rs.is(at));
833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    li(at, rt);
834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!IsMipsArchVariant(kMips32r6)) {
835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      divu(rs, at);
836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mfhi(rd);
837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      modu(rd, rs, at);
839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
840958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
842958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
843958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
8443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Divu(Register rs, const Operand& rt) {
8453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
8463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    divu(rs, rt.rm());
8473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
8483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rs.is(at));
8503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
8513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    divu(rs, at);
8523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
8533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
8543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
856958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Divu(Register res, Register rs, const Operand& rt) {
857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (rt.is_reg()) {
858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!IsMipsArchVariant(kMips32r6)) {
859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      divu(rs, rt.rm());
860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mflo(res);
861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      divu(res, rs, rt.rm());
863958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
864958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
865958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // li handles the relocation.
866958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!rs.is(at));
867958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    li(at, rt);
868958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!IsMipsArchVariant(kMips32r6)) {
869958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      divu(rs, at);
870958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mflo(res);
871958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
872958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      divu(res, rs, at);
873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
875958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
876958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
877958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
8783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::And(Register rd, Register rs, const Operand& rt) {
8793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
8803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    and_(rd, rs, rt.rm());
8813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
88244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
8833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      andi(rd, rs, rt.imm32_);
8843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
8853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!rs.is(at));
8873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
8883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      and_(rd, rs, at);
8893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
8903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
8913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
8923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Or(Register rd, Register rs, const Operand& rt) {
8953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
8963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    or_(rd, rs, rt.rm());
8973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
8993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ori(rd, rs, rt.imm32_);
9003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
9013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!rs.is(at));
9033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
9043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      or_(rd, rs, at);
9053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) {
9113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
9123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    xor_(rd, rs, rt.rm());
9133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
91444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
9153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      xori(rd, rs, rt.imm32_);
9163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
9173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!rs.is(at));
9193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
9203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      xor_(rd, rs, at);
9213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
9223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Nor(Register rd, Register rs, const Operand& rt) {
9273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
9283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    nor(rd, rs, rt.rm());
9293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
9303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rs.is(at));
9323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
9333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    nor(rd, rs, at);
9343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::Neg(Register rs, const Operand& rt) {
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rt.is_reg());
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!at.is(rs));
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!at.is(rt.rm()));
942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  li(at, -1);
943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  xor_(rs, rt.rm(), at);
944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
9473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) {
9483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
9493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    slt(rd, rs, rt.rm());
9503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
95144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
9523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slti(rd, rs, rt.imm32_);
9533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
9543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!rs.is(at));
9563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
9573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slt(rd, rs, at);
9583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
9593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) {
9643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
9653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    sltu(rd, rs, rt.rm());
9663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
967f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    const uint32_t int16_min = std::numeric_limits<int16_t>::min();
968f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (is_uint15(rt.imm32_) && !MustUseReg(rt.rmode_)) {
969f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Imm range is: [0, 32767].
9703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltiu(rd, rs, rt.imm32_);
971f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else if (is_uint15(rt.imm32_ - int16_min) && !MustUseReg(rt.rmode_)) {
972f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Imm range is: [max_unsigned-32767,max_unsigned].
973f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      sltiu(rd, rs, static_cast<uint16_t>(rt.imm32_));
9743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
9753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!rs.is(at));
9773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
9783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltu(rd, rs, at);
9793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
9803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
98444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) {
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
98644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (rt.is_reg()) {
98744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      rotrv(rd, rs, rt.rm());
98844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
9893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      rotr(rd, rs, rt.imm32_ & 0x1f);
99044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
99144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
99244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (rt.is_reg()) {
99344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      subu(at, zero_reg, rt.rm());
99444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sllv(at, rs, at);
99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      srlv(rd, rs, rt.rm());
99644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      or_(rd, rd, at);
99744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
99844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (rt.imm32_ == 0) {
99944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        srl(rd, rs, 0);
100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else {
10013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        srl(at, rs, rt.imm32_ & 0x1f);
10023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        sll(rd, rs, (0x20 - (rt.imm32_ & 0x1f)) & 0x1f);
100344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        or_(rd, rd, at);
100444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
100544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
100644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Pref(int32_t hint, const MemOperand& rs) {
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson)) {
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lw(zero_reg, rs);
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pref(hint, rs);
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa,
1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         Register scratch) {
10213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(sa >= 1 && sa <= 31);
1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && sa <= 4) {
10233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lsa(rd, rt, rs, sa - 1);
1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register tmp = rd.is(rt) ? scratch : rd;
1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!tmp.is(rt));
1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sll(tmp, rs, sa);
1028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Addu(rd, rt, tmp);
1029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1032f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::Bovc(Register rs, Register rt, Label* L) {
1033f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (is_trampoline_emitted()) {
1034f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Label skip;
1035f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bnvc(rs, rt, &skip);
1036f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    BranchLong(L, PROTECT);
1037f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bind(&skip);
1038f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
1039f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bovc(rs, rt, L);
1040f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1041f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1042f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1043f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::Bnvc(Register rs, Register rt, Label* L) {
1044f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (is_trampoline_emitted()) {
1045f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Label skip;
1046f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bovc(rs, rt, &skip);
1047f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    BranchLong(L, PROTECT);
1048f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bind(&skip);
1049f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
1050f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bnvc(rs, rt, L);
1051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1052f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ------------Pseudo-instructions-------------
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
105613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Word Swap Byte
1057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::ByteSwapSigned(Register dest, Register src,
1058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                    int operand_size) {
105913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(operand_size == 1 || operand_size == 2 || operand_size == 4);
106013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1061c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (operand_size == 2) {
1062c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Seh(src, src);
1063c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else if (operand_size == 1) {
1064c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Seb(src, src);
1065c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1066c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // No need to do any preparation if operand_size is 4
1067c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1068c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
1069f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    wsbh(dest, src);
1070f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    rotr(dest, dest, 16);
107113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) {
107213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Register tmp = t0;
107313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Register tmp2 = t1;
107413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1075f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    andi(tmp2, src, 0xFF);
107613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    sll(tmp2, tmp2, 24);
107713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    or_(tmp, zero_reg, tmp2);
107813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1079f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    andi(tmp2, src, 0xFF00);
108013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    sll(tmp2, tmp2, 8);
108113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    or_(tmp, tmp, tmp2);
108213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1083f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    srl(src, src, 8);
1084f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    andi(tmp2, src, 0xFF00);
108513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    or_(tmp, tmp, tmp2);
108613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1087f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    srl(src, src, 16);
1088f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    andi(tmp2, src, 0xFF);
108913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    or_(tmp, tmp, tmp2);
109013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1091f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    or_(dest, tmp, zero_reg);
109213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
109313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
109413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1095f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::ByteSwapUnsigned(Register dest, Register src,
1096f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                      int operand_size) {
109713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(operand_size == 1 || operand_size == 2);
109813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
109913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
110013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (operand_size == 1) {
1101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      andi(src, src, 0xFF);
110213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
1103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      andi(src, src, 0xFFFF);
110413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
110513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // No need to do any preparation if operand_size is 4
110613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    wsbh(dest, src);
1108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    rotr(dest, dest, 16);
110913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) {
111013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (operand_size == 1) {
1111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      sll(src, src, 24);
111213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
111313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Register tmp = t0;
111413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      andi(tmp, src, 0xFF00);
1116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      sll(src, src, 24);
111713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      sll(tmp, tmp, 8);
1118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      or_(dest, tmp, src);
111913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
112013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
112113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
112213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Ulw(Register rd, const MemOperand& rs) {
1124bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rd.is(at));
1125bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rs.rm().is(at));
1126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    lw(rd, rs);
1128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           IsMipsArchVariant(kLoongson));
1131bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (is_int16(rs.offset() + kMipsLwrOffset) &&
1132bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        is_int16(rs.offset() + kMipsLwlOffset)) {
1133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (!rd.is(rs.rm())) {
1134bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        lwr(rd, MemOperand(rs.rm(), rs.offset() + kMipsLwrOffset));
1135bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        lwl(rd, MemOperand(rs.rm(), rs.offset() + kMipsLwlOffset));
1136bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else {
1137bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        lwr(at, MemOperand(rs.rm(), rs.offset() + kMipsLwrOffset));
1138bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        lwl(at, MemOperand(rs.rm(), rs.offset() + kMipsLwlOffset));
1139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        mov(rd, at);
1140bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
1141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {  // Offset > 16 bits, use multiple instructions to load.
1142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      LoadRegPlusOffsetToAt(rs);
1143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lwr(rd, MemOperand(at, kMipsLwrOffset));
1144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lwl(rd, MemOperand(at, kMipsLwlOffset));
1145bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1146bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Usw(Register rd, const MemOperand& rs) {
1151bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rd.is(at));
1152bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rs.rm().is(at));
1153bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1154bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sw(rd, rs);
1155bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1156bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1157bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           IsMipsArchVariant(kLoongson));
1158bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (is_int16(rs.offset() + kMipsSwrOffset) &&
1159bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        is_int16(rs.offset() + kMipsSwlOffset)) {
1160bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      swr(rd, MemOperand(rs.rm(), rs.offset() + kMipsSwrOffset));
1161bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      swl(rd, MemOperand(rs.rm(), rs.offset() + kMipsSwlOffset));
1162bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
1163bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      LoadRegPlusOffsetToAt(rs);
1164bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      swr(rd, MemOperand(at, kMipsSwrOffset));
1165bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      swl(rd, MemOperand(at, kMipsSwlOffset));
1166bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1167bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1168bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1169bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1170bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::Ulh(Register rd, const MemOperand& rs) {
1171bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rd.is(at));
1172bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rs.rm().is(at));
1173bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1174bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    lh(rd, rs);
1175bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1176bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1177bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           IsMipsArchVariant(kLoongson));
1178bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (is_int16(rs.offset()) && is_int16(rs.offset() + 1)) {
1179bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#if defined(V8_TARGET_LITTLE_ENDIAN)
1180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(at, rs);
1181bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lb(rd, MemOperand(rs.rm(), rs.offset() + 1));
1182bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#elif defined(V8_TARGET_BIG_ENDIAN)
1183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(at, MemOperand(rs.rm(), rs.offset() + 1));
1184bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lb(rd, rs);
1185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#endif
1186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {  // Offset > 16 bits, use multiple instructions to load.
1187bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      LoadRegPlusOffsetToAt(rs);
1188bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#if defined(V8_TARGET_LITTLE_ENDIAN)
1189bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lb(rd, MemOperand(at, 1));
1190bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(at, MemOperand(at, 0));
1191bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#elif defined(V8_TARGET_BIG_ENDIAN)
1192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lb(rd, MemOperand(at, 0));
1193bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(at, MemOperand(at, 1));
1194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#endif
1195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sll(rd, rd, 8);
1197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    or_(rd, rd, at);
1198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1199bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1200bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1201bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::Ulhu(Register rd, const MemOperand& rs) {
1202bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rd.is(at));
1203bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rs.rm().is(at));
1204bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1205bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    lhu(rd, rs);
1206bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1207bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1208bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           IsMipsArchVariant(kLoongson));
1209bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (is_int16(rs.offset()) && is_int16(rs.offset() + 1)) {
1210bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#if defined(V8_TARGET_LITTLE_ENDIAN)
1211bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(at, rs);
1212bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(rd, MemOperand(rs.rm(), rs.offset() + 1));
1213bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#elif defined(V8_TARGET_BIG_ENDIAN)
1214bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(at, MemOperand(rs.rm(), rs.offset() + 1));
1215bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(rd, rs);
1216bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#endif
1217bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {  // Offset > 16 bits, use multiple instructions to load.
1218bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      LoadRegPlusOffsetToAt(rs);
1219bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#if defined(V8_TARGET_LITTLE_ENDIAN)
1220bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(rd, MemOperand(at, 1));
1221bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(at, MemOperand(at, 0));
1222bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#elif defined(V8_TARGET_BIG_ENDIAN)
1223bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(rd, MemOperand(at, 0));
1224bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      lbu(at, MemOperand(at, 1));
1225bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#endif
1226bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1227bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sll(rd, rd, 8);
1228bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    or_(rd, rd, at);
1229bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1230bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1231bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1232bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::Ush(Register rd, const MemOperand& rs, Register scratch) {
1233bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rd.is(at));
1234bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rs.rm().is(at));
1235bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!rs.rm().is(scratch));
1236bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!scratch.is(at));
1237bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1238bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sh(rd, rs);
1239bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1240bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1241bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           IsMipsArchVariant(kLoongson));
1242bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    MemOperand source = rs;
1243bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // If offset > 16 bits, load address to at with offset 0.
1244bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (!is_int16(rs.offset()) || !is_int16(rs.offset() + 1)) {
1245bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      LoadRegPlusOffsetToAt(rs);
1246bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      source = MemOperand(at, 0);
1247bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1248bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1249bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (!scratch.is(rd)) {
1250bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(scratch, rd);
1251bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1252bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1253bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#if defined(V8_TARGET_LITTLE_ENDIAN)
1254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sb(scratch, source);
1255bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    srl(scratch, scratch, 8);
1256bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sb(scratch, MemOperand(source.rm(), source.offset() + 1));
1257bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#elif defined(V8_TARGET_BIG_ENDIAN)
1258bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sb(scratch, MemOperand(source.rm(), source.offset() + 1));
1259bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    srl(scratch, scratch, 8);
1260bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sb(scratch, source);
1261bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#endif
1262bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1263bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1264bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1265bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::Ulwc1(FPURegister fd, const MemOperand& rs,
1266bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           Register scratch) {
1267bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1268bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    lwc1(fd, rs);
1269bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1270bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1271bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           IsMipsArchVariant(kLoongson));
1272bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Ulw(scratch, rs);
1273bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mtc1(scratch, fd);
1274bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1275bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1276bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::Uswc1(FPURegister fd, const MemOperand& rs,
1278bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           Register scratch) {
1279bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1280bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    swc1(fd, rs);
1281bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1282bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1283bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           IsMipsArchVariant(kLoongson));
1284bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mfc1(scratch, fd);
1285bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Usw(scratch, rs);
1286bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1287bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1288bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1289bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::Uldc1(FPURegister fd, const MemOperand& rs,
1290bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           Register scratch) {
1291bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!scratch.is(at));
1292bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1293bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    ldc1(fd, rs);
1294bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1295bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1296bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           IsMipsArchVariant(kLoongson));
1297bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Ulw(scratch, MemOperand(rs.rm(), rs.offset() + Register::kMantissaOffset));
1298bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mtc1(scratch, fd);
1299bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Ulw(scratch, MemOperand(rs.rm(), rs.offset() + Register::kExponentOffset));
1300bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Mthc1(scratch, fd);
1301bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1302bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1303bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1304bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::Usdc1(FPURegister fd, const MemOperand& rs,
1305bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           Register scratch) {
1306bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!scratch.is(at));
1307bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1308bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sdc1(fd, rs);
1309bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1310bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           IsMipsArchVariant(kLoongson));
1312bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    mfc1(scratch, fd);
1313bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Usw(scratch, MemOperand(rs.rm(), rs.offset() + Register::kMantissaOffset));
1314bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Mfhc1(scratch, fd);
1315bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Usw(scratch, MemOperand(rs.rm(), rs.offset() + Register::kExponentOffset));
1316bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) {
1321f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  li(dst, Operand(value), mode);
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
132444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::li(Register rd, Operand j, LiFlags mode) {
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!j.is_reg());
132744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) {
13293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Normal load of an immediate value which does not need Relocation Info.
13303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if (is_int16(j.imm32_)) {
13313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(rd, zero_reg, j.imm32_);
133244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (!(j.imm32_ & kHiMask)) {
13333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ori(rd, zero_reg, j.imm32_);
133444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (!(j.imm32_ & kImm16Mask)) {
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask);
13363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask);
133844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ori(rd, rd, (j.imm32_ & kImm16Mask));
13393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
134144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (MustUseReg(j.rmode_)) {
13423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      RecordRelocInfo(j.rmode_, j.imm32_);
13433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We always need the same number of instructions as we may need to patch
13453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // this code to load another value which may need 2 instructions to load.
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask);
1347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ori(rd, rd, (j.imm32_ & kImm16Mask));
13483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
13493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::MultiPush(RegList regs) {
1353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t num_to_push = NumberOfBitsSet(regs);
1354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = num_to_push * kPointerSize;
13553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Subu(sp, sp, Operand(stack_offset));
13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
13583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if ((regs & (1 << i)) != 0) {
1359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset -= kPointerSize;
1360589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      sw(ToRegister(i), MemOperand(sp, stack_offset));
13613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
13623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
13633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::MultiPushReversed(RegList regs) {
1367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t num_to_push = NumberOfBitsSet(regs);
1368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = num_to_push * kPointerSize;
13693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1370589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Subu(sp, sp, Operand(stack_offset));
13716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int16_t i = 0; i < kNumRegisters; i++) {
13723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if ((regs & (1 << i)) != 0) {
1373589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset -= kPointerSize;
1374589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      sw(ToRegister(i), MemOperand(sp, stack_offset));
13753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
13763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
13773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::MultiPop(RegList regs) {
1381589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = 0;
13823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int16_t i = 0; i < kNumRegisters; i++) {
13843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if ((regs & (1 << i)) != 0) {
1385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      lw(ToRegister(i), MemOperand(sp, stack_offset));
1386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset += kPointerSize;
13873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
13883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
1389589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  addiu(sp, sp, stack_offset);
13903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::MultiPopReversed(RegList regs) {
1394589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = 0;
13953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
13973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if ((regs & (1 << i)) != 0) {
1398589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      lw(ToRegister(i), MemOperand(sp, stack_offset));
1399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset += kPointerSize;
14003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
14013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
1402589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  addiu(sp, sp, stack_offset);
1403589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
1404589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::MultiPushFPU(RegList regs) {
1407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t num_to_push = NumberOfBitsSet(regs);
1408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = num_to_push * kDoubleSize;
1409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Subu(sp, sp, Operand(stack_offset));
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
1412589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if ((regs & (1 << i)) != 0) {
1413589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset -= kDoubleSize;
1414589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1415589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1416589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
1417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
1418589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1419589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1420589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::MultiPushReversedFPU(RegList regs) {
1421589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t num_to_push = NumberOfBitsSet(regs);
1422589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = num_to_push * kDoubleSize;
1423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Subu(sp, sp, Operand(stack_offset));
1425589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (int16_t i = 0; i < kNumRegisters; i++) {
1426589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if ((regs & (1 << i)) != 0) {
1427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset -= kDoubleSize;
1428589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1429589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1430589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
1431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
1432589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1433589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1434589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::MultiPopFPU(RegList regs) {
1435589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = 0;
1436589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1437589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (int16_t i = 0; i < kNumRegisters; i++) {
1438589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if ((regs & (1 << i)) != 0) {
1439589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset += kDoubleSize;
1441589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1442589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
1443589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  addiu(sp, sp, stack_offset);
1444589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
1445589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1446589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1447589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::MultiPopReversedFPU(RegList regs) {
1448589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = 0;
1449589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
1451589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if ((regs & (1 << i)) != 0) {
1452589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
1453589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset += kDoubleSize;
1454589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1455589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
1456589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  addiu(sp, sp, stack_offset);
14573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
14583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::AddPair(Register dst_low, Register dst_high,
1460bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register left_low, Register left_high,
1461bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register right_low, Register right_high) {
1462bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label no_overflow;
1463bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register kScratchReg = s3;
1464bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register kScratchReg2 = s4;
1465bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Add lower word
1466bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(dst_low, left_low, right_low);
1467bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(dst_high, left_high, right_high);
1468bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Check for lower word unsigned overflow
1469bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Sltu(kScratchReg, dst_low, left_low);
1470bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Sltu(kScratchReg2, dst_low, right_low);
1471bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Or(kScratchReg, kScratchReg2, kScratchReg);
1472bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&no_overflow, eq, kScratchReg, Operand(zero_reg));
1473bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Increment higher word if there was overflow
1474bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(dst_high, dst_high, 0x1);
1475bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&no_overflow);
1476bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1477bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1478bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::SubPair(Register dst_low, Register dst_high,
1479bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register left_low, Register left_high,
1480bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register right_low, Register right_high) {
1481bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label no_overflow;
1482bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register kScratchReg = s3;
1483bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Subtract lower word
1484bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Subu(dst_low, left_low, right_low);
1485bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Subu(dst_high, left_high, right_high);
1486bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Check for lower word unsigned underflow
1487bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Sltu(kScratchReg, left_low, right_low);
1488bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&no_overflow, eq, kScratchReg, Operand(zero_reg));
1489bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Decrement higher word if there was underflow
1490bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Subu(dst_high, dst_high, 0x1);
1491bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&no_overflow);
1492bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1493bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1494bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::ShlPair(Register dst_low, Register dst_high,
1495bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register src_low, Register src_high,
1496bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register shift) {
1497bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label less_than_32;
1498bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label zero_shift;
1499bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label word_shift;
1500bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label done;
1501bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register kScratchReg = s3;
1502bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  And(shift, shift, 0x3F);
1503bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(kScratchReg, 0x20);
1504bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&less_than_32, lt, shift, Operand(kScratchReg));
1505bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1506bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&word_shift, eq, shift, Operand(kScratchReg));
1507bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Shift more than 32
1508bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Subu(kScratchReg, shift, kScratchReg);
1509bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_low, zero_reg);
1510bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sllv(dst_high, src_low, kScratchReg);
1511bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&done);
1512bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Word shift
1513bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&word_shift);
1514bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_low, zero_reg);
1515bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_high, src_low);
1516bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&done);
1517bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1518bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&less_than_32);
1519bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Check if zero shift
1520bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&zero_shift, eq, shift, Operand(zero_reg));
1521bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Shift less than 32
1522bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Subu(kScratchReg, kScratchReg, shift);
1523bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sllv(dst_high, src_high, shift);
1524bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sllv(dst_low, src_low, shift);
1525bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  srlv(kScratchReg, src_low, kScratchReg);
1526bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Or(dst_high, dst_high, kScratchReg);
1527bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&done);
1528bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Zero shift
1529bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&zero_shift);
1530bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_low, src_low);
1531bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_high, src_high);
1532bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&done);
1533bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1534bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1535bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::ShlPair(Register dst_low, Register dst_high,
1536bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register src_low, Register src_high,
1537bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             uint32_t shift) {
1538bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register kScratchReg = s3;
1539bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  shift = shift & 0x3F;
1540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (shift < 32) {
1541bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (shift == 0) {
1542bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_low, src_low);
1543bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_high, src_high);
1544bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
1545bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      sll(dst_high, src_high, shift);
1546bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      sll(dst_low, src_low, shift);
1547bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      shift = 32 - shift;
1548bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      srl(kScratchReg, src_low, shift);
1549bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      Or(dst_high, dst_high, kScratchReg);
1550bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1551bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1552bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (shift == 32) {
1553bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_low, zero_reg);
1554bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_high, src_low);
1555bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
1556bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      shift = shift - 32;
1557bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_low, zero_reg);
1558bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      sll(dst_high, src_low, shift);
1559bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1560bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1561bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1562bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1563bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::ShrPair(Register dst_low, Register dst_high,
1564bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register src_low, Register src_high,
1565bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register shift) {
1566bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label less_than_32;
1567bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label zero_shift;
1568bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label word_shift;
1569bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label done;
1570bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register kScratchReg = s3;
1571bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  And(shift, shift, 0x3F);
1572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(kScratchReg, 0x20);
1573bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&less_than_32, lt, shift, Operand(kScratchReg));
1574bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1575bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&word_shift, eq, shift, Operand(kScratchReg));
1576bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Shift more than 32
1577bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Subu(kScratchReg, shift, kScratchReg);
1578bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_high, zero_reg);
1579bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  srlv(dst_low, src_high, kScratchReg);
1580bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&done);
1581bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Word shift
1582bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&word_shift);
1583bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_high, zero_reg);
1584bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_low, src_high);
1585bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&done);
1586bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&less_than_32);
1588bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Check if zero shift
1589bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&zero_shift, eq, shift, Operand(zero_reg));
1590bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Shift less than 32
1591bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Subu(kScratchReg, kScratchReg, shift);
1592bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  srlv(dst_high, src_high, shift);
1593bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  srlv(dst_low, src_low, shift);
1594bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sllv(kScratchReg, src_high, kScratchReg);
1595bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Or(dst_low, dst_low, kScratchReg);
1596bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&done);
1597bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Zero shift
1598bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&zero_shift);
1599bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_low, src_low);
1600bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_high, src_high);
1601bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&done);
1602bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1603bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1604bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::ShrPair(Register dst_low, Register dst_high,
1605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register src_low, Register src_high,
1606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             uint32_t shift) {
1607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register kScratchReg = s3;
1608bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  shift = shift & 0x3F;
1609bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (shift < 32) {
1610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (shift == 0) {
1611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_low, src_low);
1612bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_high, src_high);
1613bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
1614bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      srl(dst_high, src_high, shift);
1615bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      srl(dst_low, src_low, shift);
1616bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      shift = 32 - shift;
1617bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      sll(kScratchReg, src_high, shift);
1618bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      Or(dst_low, dst_low, kScratchReg);
1619bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1620bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1621bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (shift == 32) {
1622bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_high, zero_reg);
1623bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_low, src_high);
1624bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
1625bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      shift = shift - 32;
1626bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_high, zero_reg);
1627bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      srl(dst_low, src_high, shift);
1628bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1629bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1630bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1631bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1632bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::SarPair(Register dst_low, Register dst_high,
1633bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register src_low, Register src_high,
1634bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register shift) {
1635bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label less_than_32;
1636bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label zero_shift;
1637bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label word_shift;
1638bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label done;
1639bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register kScratchReg = s3;
1640bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register kScratchReg2 = s4;
1641bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  And(shift, shift, 0x3F);
1642bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(kScratchReg, 0x20);
1643bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&less_than_32, lt, shift, Operand(kScratchReg));
1644bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1645bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&word_shift, eq, shift, Operand(kScratchReg));
1646bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1647bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Shift more than 32
1648bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(kScratchReg2, 0x1F);
1649bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Subu(kScratchReg, shift, kScratchReg);
1650bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  srav(dst_high, src_high, kScratchReg2);
1651bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  srav(dst_low, src_high, kScratchReg);
1652bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&done);
1653bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Word shift
1654bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&word_shift);
1655bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(kScratchReg2, 0x1F);
1656bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  srav(dst_high, src_high, kScratchReg2);
1657bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_low, src_high);
1658bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&done);
1659bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1660bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&less_than_32);
1661bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Check if zero shift
1662bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&zero_shift, eq, shift, Operand(zero_reg));
1663bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1664bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Shift less than 32
1665bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Subu(kScratchReg, kScratchReg, shift);
1666bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  srav(dst_high, src_high, shift);
1667bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  srlv(dst_low, src_low, shift);
1668bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sllv(kScratchReg, src_high, kScratchReg);
1669bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Or(dst_low, dst_low, kScratchReg);
1670bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Branch(&done);
1671bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Zero shift
1672bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&zero_shift);
1673bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_low, src_low);
1674bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  mov(dst_high, src_high);
1675bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bind(&done);
1676bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1677bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1678bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::SarPair(Register dst_low, Register dst_high,
1679bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             Register src_low, Register src_high,
1680bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                             uint32_t shift) {
1681bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register kScratchReg = s3;
1682bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  shift = shift & 0x3F;
1683bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (shift < 32) {
1684bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (shift == 0) {
1685bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_low, src_low);
1686bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_high, src_high);
1687bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
1688bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      sra(dst_high, src_high, shift);
1689bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      srl(dst_low, src_low, shift);
1690bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      shift = 32 - shift;
1691bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      sll(kScratchReg, src_high, shift);
1692bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      Or(dst_low, dst_low, kScratchReg);
1693bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1694bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
1695bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (shift == 32) {
1696bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      sra(dst_high, src_high, 31);
1697bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      mov(dst_low, src_high);
1698bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
1699bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      shift = shift - 32;
1700bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      sra(dst_high, src_high, 31);
1701bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      sra(dst_low, src_high, shift);
1702bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1703bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1704bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
17053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
170644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Ext(Register rt,
170744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         Register rs,
170844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         uint16_t pos,
170944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         uint16_t size) {
1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(pos < 32);
1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(pos + size < 33);
17123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
171444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ext_(rt, rs, pos, size);
171544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
171644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Move rs to rt and shift it left then right to get the
171744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // desired bitfield on the right side and zeroes on the left.
171869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int shift_left = 32 - (pos + size);
171969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    sll(rt, rs, shift_left);  // Acts as a move if shift_left == 0.
172069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
172169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int shift_right = 32 - size;
172269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (shift_right > 0) {
172369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      srl(rt, rt, shift_right);
172469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
17253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
172644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
17273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
172944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Ins(Register rt,
173044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         Register rs,
173144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         uint16_t pos,
173244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         uint16_t size) {
1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(pos < 32);
1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(pos + size <= 32);
1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(size != 0);
17363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
173844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ins_(rt, rs, pos, size);
173944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rt.is(t8) && !rs.is(t8));
17413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Subu(at, zero_reg, Operand(1));
17423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(at, at, 32 - size);
17433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(t8, rs, at);
17443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sll(t8, t8, pos);
17453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sll(at, at, pos);
17463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nor(at, at, zero_reg);
17473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(at, rt, at);
17483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    or_(rt, t8, at);
174944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
175044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
17513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1752c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid MacroAssembler::Seb(Register rd, Register rt) {
1753c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
1754c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    seb(rd, rt);
1755c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
1756c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson));
1757c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    sll(rd, rt, 24);
1758c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    sra(rd, rd, 24);
1759c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1760c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1761c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1762c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid MacroAssembler::Seh(Register rd, Register rt) {
1763c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
1764c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    seh(rd, rt);
1765c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
1766c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson));
1767c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    sll(rd, rt, 16);
1768c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    sra(rd, rd, 16);
1769c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1770c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1771c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1772f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::Neg_s(FPURegister fd, FPURegister fs) {
1773f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1774f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // r6 neg_s changes the sign for NaN-like operands as well.
1775f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    neg_s(fd, fs);
1776f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
1777f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1778f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch           IsMipsArchVariant(kLoongson));
1779f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Label is_nan, done;
1780f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Register scratch1 = t8;
1781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Register scratch2 = t9;
1782f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    BranchF32(nullptr, &is_nan, eq, fs, fs);
1783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Branch(USE_DELAY_SLOT, &done);
1784f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // For NaN input, neg_s will return the same NaN value,
1785f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // while the sign has to be changed separately.
1786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    neg_s(fd, fs);  // In delay slot.
1787f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bind(&is_nan);
1788f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    mfc1(scratch1, fs);
1789f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    And(scratch2, scratch1, Operand(~kBinary32SignMask));
1790f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    And(scratch1, scratch1, Operand(kBinary32SignMask));
1791f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Xor(scratch1, scratch1, Operand(kBinary32SignMask));
1792f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Or(scratch2, scratch2, scratch1);
1793f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    mtc1(scratch2, fd);
1794f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bind(&done);
1795f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1796f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1797f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1798f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::Neg_d(FPURegister fd, FPURegister fs) {
1799f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
1800f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // r6 neg_d changes the sign for NaN-like operands as well.
1801f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    neg_d(fd, fs);
1802f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
1803f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
1804f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch           IsMipsArchVariant(kLoongson));
1805f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Label is_nan, done;
1806f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Register scratch1 = t8;
1807f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Register scratch2 = t9;
1808f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    BranchF64(nullptr, &is_nan, eq, fs, fs);
1809f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Branch(USE_DELAY_SLOT, &done);
1810f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // For NaN input, neg_d will return the same NaN value,
1811f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // while the sign has to be changed separately.
1812f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    neg_d(fd, fs);  // In delay slot.
1813f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bind(&is_nan);
1814f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Mfhc1(scratch1, fs);
1815f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    And(scratch2, scratch1, Operand(~HeapNumber::kSignMask));
1816f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
1817f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Xor(scratch1, scratch1, Operand(HeapNumber::kSignMask));
1818f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Or(scratch2, scratch2, scratch1);
1819f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Mthc1(scratch2, fd);
1820f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bind(&done);
1821f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
182344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvt_d_uw(FPURegister fd, Register rs,
182569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              FPURegister scratch) {
1826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // In FP64Mode we do convertion from long.
1827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsFp64Mode()) {
1828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mtc1(rs, scratch);
1829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Mthc1(zero_reg, scratch);
1830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvt_d_l(fd, scratch);
1831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Convert rs to a FP value in fd.
1833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!fd.is(scratch));
1834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!rs.is(at));
183544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label msb_clear, conversion_done;
1837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // For a value which is < 2^31, regard it as a signed positve word.
1838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Branch(&msb_clear, ge, rs, Operand(zero_reg), USE_DELAY_SLOT);
1839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mtc1(rs, fd);
184044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    li(at, 0x41F00000);  // FP value: 2^32.
184244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // For unsigned inputs > 2^31, we convert to double as a signed int32,
1844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // then add 2^32 to move it back to unsigned value in range 2^31..2^31-1.
1845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mtc1(zero_reg, scratch);
1846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Mthc1(at, scratch);
184744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvt_d_w(fd, fd);
184944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Branch(USE_DELAY_SLOT, &conversion_done);
1851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    add_d(fd, fd, scratch);
185244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bind(&msb_clear);
1854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvt_d_w(fd, fd);
185544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bind(&conversion_done);
1857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
185844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
185944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
186044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
186169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid MacroAssembler::Trunc_uw_d(FPURegister fd,
186269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                FPURegister fs,
186369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                FPURegister scratch) {
186469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Trunc_uw_d(fs, t8, scratch);
186569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mtc1(t8, fd);
186644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
186744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1868109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Trunc_uw_s(FPURegister fd, FPURegister fs,
1869109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                FPURegister scratch) {
1870109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Trunc_uw_s(fs, t8, scratch);
1871109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mtc1(t8, fd);
1872109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Trunc_w_d(FPURegister fd, FPURegister fs) {
1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson) && fd.is(fs)) {
1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Mfhc1(t8, fs);
18773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    trunc_w_d(fd, fs);
1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Mthc1(t8, fs);
18793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
18803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    trunc_w_d(fd, fs);
18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
18823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Round_w_d(FPURegister fd, FPURegister fs) {
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson) && fd.is(fs)) {
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Mfhc1(t8, fs);
18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    round_w_d(fd, fs);
1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Mthc1(t8, fs);
18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    round_w_d(fd, fs);
18923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
18933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Floor_w_d(FPURegister fd, FPURegister fs) {
1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson) && fd.is(fs)) {
1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Mfhc1(t8, fs);
18993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    floor_w_d(fd, fs);
1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Mthc1(t8, fs);
19013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
19023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    floor_w_d(fd, fs);
19033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) {
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson) && fd.is(fs)) {
1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Mfhc1(t8, fs);
19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ceil_w_d(fd, fs);
1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Mthc1(t8, fs);
19123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
19133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ceil_w_d(fd, fs);
19143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
19153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
191744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
191869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid MacroAssembler::Trunc_uw_d(FPURegister fd,
191969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                Register rs,
192069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                FPURegister scratch) {
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!fd.is(scratch));
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!rs.is(at));
192344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
192469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Load 2^31 into scratch as its float representation.
192569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  li(at, 0x41E00000);
192669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mtc1(zero_reg, scratch);
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Mthc1(at, scratch);
192869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Test if scratch > fd.
192985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // If fd < 2^31 we can convert it normally.
19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label simple_convert;
19313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BranchF(&simple_convert, NULL, lt, fd, scratch);
193244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
193344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // First we subtract 2^31 from fd, then trunc it to rs
193444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // and add 2^31 to rs.
193569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  sub_d(scratch, fd, scratch);
193669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  trunc_w_d(scratch, scratch);
193769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mfc1(rs, scratch);
193869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Or(rs, rs, 1 << 31);
193944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
194044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done;
194144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&done);
194244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Simple conversion.
194344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&simple_convert);
194469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  trunc_w_d(scratch, fd);
194569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mfc1(rs, scratch);
194644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
194744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
194844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
194944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1950109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Trunc_uw_s(FPURegister fd, Register rs,
1951109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                FPURegister scratch) {
1952109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!fd.is(scratch));
1953109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!rs.is(at));
1954109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1955109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Load 2^31 into scratch as its float representation.
1956109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  li(at, 0x4F000000);
1957109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mtc1(at, scratch);
1958109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Test if scratch > fd.
1959109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // If fd < 2^31 we can convert it normally.
1960109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label simple_convert;
1961109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  BranchF32(&simple_convert, NULL, lt, fd, scratch);
1962109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1963109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // First we subtract 2^31 from fd, then trunc it to rs
1964109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // and add 2^31 to rs.
1965109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  sub_s(scratch, fd, scratch);
1966109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  trunc_w_s(scratch, scratch);
1967109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mfc1(rs, scratch);
1968109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Or(rs, rs, 1 << 31);
1969109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1970109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label done;
1971109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Branch(&done);
1972109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Simple conversion.
1973109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&simple_convert);
1974109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  trunc_w_s(scratch, fd);
1975109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  mfc1(rs, scratch);
1976109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1977109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&done);
1978109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
197944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Mthc1(Register rt, FPURegister fs) {
1981109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (IsFp32Mode()) {
1982f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch    mtc1(rt, fs.high());
1983109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
1984109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsFp64Mode() || IsFpxxMode());
1985109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
1986109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    mthc1(rt, fs);
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Mfhc1(Register rt, FPURegister fs) {
1992109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (IsFp32Mode()) {
1993f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch    mfc1(rt, fs.high());
1994109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
1995109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsFp64Mode() || IsFpxxMode());
1996109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
1997109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    mfhc1(rt, fs);
1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchFCommon(SecondaryField sizeField, Label* target,
2003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* nan, Condition cond, FPURegister cmp1,
2004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   FPURegister cmp2, BranchDelaySlot bd) {
2005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
2006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
2007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (cond == al) {
2008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Branch(bd, target);
2009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return;
2010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6)) {
2013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      sizeField = sizeField == D ? L : W;
2014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(nan || target);
2016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check for unordered (NaN) cases.
2017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (nan) {
2018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bool long_branch =
2019f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          nan->is_bound() ? !is_near(nan) : is_trampoline_emitted();
2020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!IsMipsArchVariant(kMips32r6)) {
2021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (long_branch) {
2022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Label skip;
2023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(UN, sizeField, cmp1, cmp2);
2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1f(&skip);
2025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          nop();
2026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          BranchLong(nan, bd);
2027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bind(&skip);
2028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
2029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(UN, sizeField, cmp1, cmp2);
2030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1t(nan);
2031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (bd == PROTECT) {
2032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            nop();
2033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
2034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
2035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
2036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Use kDoubleCompareReg for comparison result. It has to be unavailable
2037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // to lithium register allocator.
2038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(!cmp1.is(kDoubleCompareReg) && !cmp2.is(kDoubleCompareReg));
2039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (long_branch) {
2040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Label skip;
2041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(UN, sizeField, kDoubleCompareReg, cmp1, cmp2);
2042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1eqz(&skip, kDoubleCompareReg);
2043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          nop();
2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          BranchLong(nan, bd);
2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bind(&skip);
2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(UN, sizeField, kDoubleCompareReg, cmp1, cmp2);
2048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1nez(nan, kDoubleCompareReg);
2049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (bd == PROTECT) {
2050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            nop();
2051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
2052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
2053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
2054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (target) {
2057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bool long_branch =
2058f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          target->is_bound() ? !is_near(target) : is_trampoline_emitted();
2059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (long_branch) {
2060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Label skip;
2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Condition neg_cond = NegateFpuCondition(cond);
2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchShortF(sizeField, &skip, neg_cond, cmp1, cmp2, bd);
2063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchLong(target, bd);
2064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bind(&skip);
2065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
2066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchShortF(sizeField, target, cond, cmp1, cmp2, bd);
2067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShortF(SecondaryField sizeField, Label* target,
2073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Condition cc, FPURegister cmp1,
2074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  FPURegister cmp2, BranchDelaySlot bd) {
2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsMipsArchVariant(kMips32r6)) {
2076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (target) {
2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Here NaN cases were either handled by this function or are assumed to
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // have been handled by the caller.
2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (cc) {
2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case lt:
2082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(OLT, sizeField, cmp1, cmp2);
2083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1t(target);
2084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ult:
2086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(ULT, sizeField, cmp1, cmp2);
2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1t(target);
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case gt:
2090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(ULE, sizeField, cmp1, cmp2);
2091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1f(target);
2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ugt:
2094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(OLE, sizeField, cmp1, cmp2);
2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1f(target);
2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case ge:
2098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(ULT, sizeField, cmp1, cmp2);
2099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1f(target);
2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case uge:
2102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(OLT, sizeField, cmp1, cmp2);
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1f(target);
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case le:
2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(OLE, sizeField, cmp1, cmp2);
2107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1t(target);
2108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ule:
2110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(ULE, sizeField, cmp1, cmp2);
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1t(target);
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case eq:
2114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(EQ, sizeField, cmp1, cmp2);
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1t(target);
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case ueq:
2118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(UEQ, sizeField, cmp1, cmp2);
2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1t(target);
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ne:  // Unordered or not equal.
2122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(EQ, sizeField, cmp1, cmp2);
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1f(target);
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ogl:
2126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(UEQ, sizeField, cmp1, cmp2);
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1f(target);
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        default:
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CHECK(0);
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (target) {
2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Here NaN cases were either handled by this function or are assumed to
2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // have been handled by the caller.
2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Unsigned conditions are treated as their signed counterpart.
2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Use kDoubleCompareReg for comparison result, it is
2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // valid in fp64 (FR = 1) mode which is implied for mips32r6.
2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!cmp1.is(kDoubleCompareReg) && !cmp2.is(kDoubleCompareReg));
2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (cc) {
2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case lt:
2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(OLT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1nez(target, kDoubleCompareReg);
2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ult:
2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(ULT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1nez(target, kDoubleCompareReg);
2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case gt:
2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(ULE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1eqz(target, kDoubleCompareReg);
2154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ugt:
2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(OLE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1eqz(target, kDoubleCompareReg);
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case ge:
2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(ULT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1eqz(target, kDoubleCompareReg);
2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case uge:
2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(OLT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1eqz(target, kDoubleCompareReg);
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case le:
2168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(OLE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1nez(target, kDoubleCompareReg);
2170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ule:
2172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(ULE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1nez(target, kDoubleCompareReg);
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case eq:
2176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(EQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1nez(target, kDoubleCompareReg);
2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case ueq:
2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(UEQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1nez(target, kDoubleCompareReg);
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case ne:
2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(EQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1eqz(target, kDoubleCompareReg);
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ogl:
2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(UEQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1eqz(target, kDoubleCompareReg);
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        default:
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CHECK(0);
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
21953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (bd == PROTECT) {
21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nop();
21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::FmoveLow(FPURegister dst, Register src_low) {
2203109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (IsFp32Mode()) {
2204109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    mtc1(src_low, dst);
2205109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
2206109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsFp64Mode() || IsFpxxMode());
2207109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!src_low.is(at));
2209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mfhc1(at, dst);
2210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mtc1(src_low, dst);
2211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mthc1(at, dst);
2212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(FPURegister dst, float imm) {
2217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  li(at, Operand(bit_cast<int32_t>(imm)));
2218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mtc1(at, dst);
2219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
22223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Move(FPURegister dst, double imm) {
2223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int64_t imm_bits = bit_cast<int64_t>(imm);
22243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle special values first.
2225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (imm_bits == bit_cast<int64_t>(0.0) && has_double_zero_reg_set_) {
22263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov_d(dst, kDoubleRegZero);
2227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (imm_bits == bit_cast<int64_t>(-0.0) && has_double_zero_reg_set_) {
2228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Neg_d(dst, kDoubleRegZero);
22293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
22303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t lo, hi;
22313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoubleAsTwoUInt32(imm, &lo, &hi);
22323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Move the low part of the double into the lower of the corresponding FPU
22333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // register of FPU register pair.
22343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (lo != 0) {
22353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      li(at, Operand(lo));
22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mtc1(at, dst);
22373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
22383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mtc1(zero_reg, dst);
22393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
22403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Move the high part of the double into the higher of the corresponding FPU
22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // register of FPU register pair.
22423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (hi != 0) {
22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      li(at, Operand(hi));
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Mthc1(at, dst);
22453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Mthc1(zero_reg, dst);
22473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (dst.is(kDoubleRegZero)) has_double_zero_reg_set_ = true;
22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movz(Register rd, Register rs, Register rt) {
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r6)) {
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, ne, rt, Operand(zero_reg));
22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movz(rd, rs, rt);
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movn(Register rd, Register rs, Register rt) {
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r6)) {
22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, eq, rt, Operand(zero_reg));
22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
22723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movn(rd, rs, rt);
22733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) {
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson)) {
22793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tests an FP condition code and then conditionally move rs to rd.
22803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We do not currently use any FPU cc bit other than bit 0.
2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(cc == 0);
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!(rs.is(t8) || rd.is(t8)));
22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = t8;
22853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For testing purposes we need to fetch content of the FCSR register and
22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // than test its cc (floating point condition code) bit (for cc = 0, it is
22873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 24. bit of the FCSR).
22883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cfc1(scratch, FCSR);
22893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For the MIPS I, II and III architectures, the contents of scratch is
22903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // UNPREDICTABLE for the instruction immediately following CFC1.
22913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nop();
22923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(scratch, scratch, 16);
22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    andi(scratch, scratch, 0x0080);
22943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, eq, scratch, Operand(zero_reg));
22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
22973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movt(rd, rs, cc);
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) {
2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson)) {
23053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tests an FP condition code and then conditionally move rs to rd.
23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We do not currently use any FPU cc bit other than bit 0.
2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(cc == 0);
2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!(rs.is(t8) || rd.is(t8)));
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = t8;
23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For testing purposes we need to fetch content of the FCSR register and
23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // than test its cc (floating point condition code) bit (for cc = 0, it is
23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 24. bit of the FCSR).
23143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cfc1(scratch, FCSR);
23153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For the MIPS I, II and III architectures, the contents of scratch is
23163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // UNPREDICTABLE for the instruction immediately following CFC1.
23173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nop();
23183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(scratch, scratch, 16);
23193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    andi(scratch, scratch, 0x0080);
23203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, ne, scratch, Operand(zero_reg));
23213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
23223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
23233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movf(rd, rs, cc);
23253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#define __ masm->
23293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
23303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochstatic bool ZeroHelper_d(MacroAssembler* masm, MaxMinKind kind, FPURegister dst,
23313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                         FPURegister src1, FPURegister src2, Label* equal) {
23323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (src1.is(src2)) {
23333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Move(dst, src1);
23343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return true;
23353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
23363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
23373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label other, compare_not_equal;
23383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FPURegister left, right;
23393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (kind == MaxMinKind::kMin) {
23403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    left = src1;
23413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    right = src2;
23423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
23433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    left = src2;
23443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    right = src1;
23453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
23463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
23473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ BranchF64(&compare_not_equal, nullptr, ne, src1, src2);
23483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Left and right hand side are equal, check for -0 vs. +0.
23493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ FmoveHigh(t8, src1);
23503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Branch(&other, eq, t8, Operand(0x80000000));
23513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Move_d(dst, right);
23523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Branch(equal);
23533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&other);
23543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Move_d(dst, left);
23553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Branch(equal);
23563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&compare_not_equal);
23573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return false;
23583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
23593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
23603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochstatic bool ZeroHelper_s(MacroAssembler* masm, MaxMinKind kind, FPURegister dst,
23613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                         FPURegister src1, FPURegister src2, Label* equal) {
23623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (src1.is(src2)) {
23633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Move(dst, src1);
23643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return true;
23653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
23663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
23673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label other, compare_not_equal;
23683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FPURegister left, right;
23693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (kind == MaxMinKind::kMin) {
23703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    left = src1;
23713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    right = src2;
23723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
23733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    left = src2;
23743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    right = src1;
23753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
23763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
23773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ BranchF32(&compare_not_equal, nullptr, ne, src1, src2);
23783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Left and right hand side are equal, check for -0 vs. +0.
23793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ FmoveLow(t8, src1);
23803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Branch(&other, eq, t8, Operand(0x80000000));
23813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Move_s(dst, right);
23823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Branch(equal);
23833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&other);
23843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Move_s(dst, left);
23853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Branch(equal);
23863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&compare_not_equal);
23873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return false;
23883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
23893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
23903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#undef __
23913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
23923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::MinNaNCheck_d(FPURegister dst, FPURegister src1,
23933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                   FPURegister src2, Label* nan) {
23943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (nan) {
23953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    BranchF64(nullptr, nan, eq, src1, src2);
23963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
23973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
23983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    min_d(dst, src1, src2);
23993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
24003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Label skip;
24013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (!ZeroHelper_d(this, MaxMinKind::kMin, dst, src1, src2, &skip)) {
24023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (dst.is(src1)) {
24033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF64(&skip, nullptr, le, src1, src2);
24043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_d(dst, src2);
24053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else if (dst.is(src2)) {
24063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF64(&skip, nullptr, ge, src1, src2);
24073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_d(dst, src1);
24083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
24093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Label right;
24103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF64(&right, nullptr, gt, src1, src2);
24113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_d(dst, src1);
24123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Branch(&skip);
24133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        bind(&right);
24143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_d(dst, src2);
24153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
24163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
24173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    bind(&skip);
24183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
24193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
24203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
24213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::MaxNaNCheck_d(FPURegister dst, FPURegister src1,
24223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                   FPURegister src2, Label* nan) {
24233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (nan) {
24243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    BranchF64(nullptr, nan, eq, src1, src2);
24253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
24263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
24273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    max_d(dst, src1, src2);
24283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
24293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Label skip;
24303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (!ZeroHelper_d(this, MaxMinKind::kMax, dst, src1, src2, &skip)) {
24313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (dst.is(src1)) {
24323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF64(&skip, nullptr, ge, src1, src2);
24333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_d(dst, src2);
24343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else if (dst.is(src2)) {
24353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF64(&skip, nullptr, le, src1, src2);
24363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_d(dst, src1);
24373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
24383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Label right;
24393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF64(&right, nullptr, lt, src1, src2);
24403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_d(dst, src1);
24413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Branch(&skip);
24423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        bind(&right);
24433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_d(dst, src2);
24443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
24453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
24463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    bind(&skip);
24473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
24483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
24493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
24503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::MinNaNCheck_s(FPURegister dst, FPURegister src1,
24513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                   FPURegister src2, Label* nan) {
24523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (nan) {
24533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    BranchF32(nullptr, nan, eq, src1, src2);
24543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
24553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
24563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    min_s(dst, src1, src2);
24573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
24583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Label skip;
24593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (!ZeroHelper_s(this, MaxMinKind::kMin, dst, src1, src2, &skip)) {
24603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (dst.is(src1)) {
24613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF32(&skip, nullptr, le, src1, src2);
24623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_s(dst, src2);
24633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else if (dst.is(src2)) {
24643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF32(&skip, nullptr, ge, src1, src2);
24653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_s(dst, src1);
24663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
24673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Label right;
24683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF32(&right, nullptr, gt, src1, src2);
24693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_s(dst, src1);
24703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Branch(&skip);
24713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        bind(&right);
24723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_s(dst, src2);
24733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
24743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
24753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    bind(&skip);
24763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
24773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
24783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
24793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::MaxNaNCheck_s(FPURegister dst, FPURegister src1,
24803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                   FPURegister src2, Label* nan) {
24813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (nan) {
24823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    BranchF32(nullptr, nan, eq, src1, src2);
24833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
24843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
24853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    max_s(dst, src1, src2);
24863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
24873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Label skip;
24883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (!ZeroHelper_s(this, MaxMinKind::kMax, dst, src1, src2, &skip)) {
24893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (dst.is(src1)) {
24903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF32(&skip, nullptr, ge, src1, src2);
24913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_s(dst, src2);
24923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else if (dst.is(src2)) {
24933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF32(&skip, nullptr, le, src1, src2);
24943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_s(dst, src1);
24953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
24963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Label right;
24973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BranchF32(&right, nullptr, lt, src1, src2);
24983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_s(dst, src1);
24993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Branch(&skip);
25003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        bind(&right);
25013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Move_s(dst, src2);
25023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
25033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
25043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    bind(&skip);
25053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
25063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
25073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Clz(Register rd, Register rs) {
2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson)) {
2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!(rd.is(t8) || rd.is(t9)) && !(rs.is(t8) || rs.is(t9)));
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register mask = t8;
25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = t9;
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label loop, end;
25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(at, rs);
25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, zero_reg);
25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lui(mask, 0x8000);
25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&loop);
25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, at, mask);
25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&end, ne, scratch, Operand(zero_reg));
25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    addiu(rd, rd, 1);
25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&loop, ne, mask, Operand(zero_reg), USE_DELAY_SLOT);
25223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(mask, mask, 1);
25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&end);
25243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    clz(rd, rs);
25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register result,
25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     DoubleRegister double_input,
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register scratch,
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     DoubleRegister double_scratch,
25353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register except_flag,
25363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     CheckForInexactConversion check_inexact) {
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(scratch));
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!double_input.is(double_scratch));
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!except_flag.is(scratch));
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clear the except flag (0 = no exception)
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(except_flag, zero_reg);
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test for values that can be exactly represented as a signed 32-bit integer.
2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvt_w_d(double_scratch, double_input);
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mfc1(result, double_scratch);
2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvt_d_w(double_scratch, double_scratch);
2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BranchF(&done, NULL, eq, double_input, double_scratch);
25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int32_t except_mask = kFCSRFlagMask;  // Assume interested in all exceptions.
25533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (check_inexact == kDontCheckForInexactConversion) {
2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Ignore inexact exceptions.
25563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    except_mask &= ~kFCSRInexactFlagMask;
25573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Save FCSR.
2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cfc1(scratch, FCSR);
25613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable FPU exceptions.
25623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctc1(zero_reg, FCSR);
25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do operation based on rounding mode.
25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (rounding_mode) {
25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToNearest:
2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Round_w_d(double_scratch, double_input);
25683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
25693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToZero:
2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Trunc_w_d(double_scratch, double_input);
25713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
25723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToPlusInf:
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Ceil_w_d(double_scratch, double_input);
25743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
25753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToMinusInf:
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Floor_w_d(double_scratch, double_input);
25773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
25783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }  // End of switch-statement.
25793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Retrieve FCSR.
25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cfc1(except_flag, FCSR);
25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore FCSR.
2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ctc1(scratch, FCSR);
2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Move the converted value into the result register.
2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mfc1(result, double_scratch);
25863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for fpu exceptions.
25883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(except_flag, except_flag, Operand(except_mask));
25893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
2591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TryInlineTruncateDoubleToI(Register result,
2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                DoubleRegister double_input,
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Label* done) {
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister single_scratch = kLithiumScratchDouble.low();
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = at;
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = t9;
26003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Clear cumulative exception flags and save the FCSR.
26023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cfc1(scratch2, FCSR);
26033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ctc1(zero_reg, FCSR);
26043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Try a conversion to a signed integer.
26053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  trunc_w_d(single_scratch, double_input);
26063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  mfc1(result, single_scratch);
26073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Retrieve and restore the FCSR.
26083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cfc1(scratch, FCSR);
26093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ctc1(scratch2, FCSR);
26103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check for overflow and NaNs.
26113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  And(scratch,
26123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      scratch,
26133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask);
26143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If we had no exceptions we are done.
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(done, eq, scratch, Operand(zero_reg));
2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateDoubleToI(Register result,
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       DoubleRegister double_input) {
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TryInlineTruncateDoubleToI(result, double_input, &done);
2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we fell through then inline version didn't succeed - call stub instead.
2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ra);
2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Subu(sp, sp, Operand(kDoubleSize));  // Put input on stack.
2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sdc1(double_input, MemOperand(sp, 0));
2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(), sp, result, 0, true, true);
2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Addu(sp, sp, Operand(kDoubleSize));
2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(ra);
2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateHeapNumberToI(Register result, Register object) {
2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister double_scratch = f12;
2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(object));
2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ldc1(double_scratch,
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag));
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TryInlineTruncateDoubleToI(result, double_scratch, &done);
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we fell through then inline version didn't succeed - call stub instead.
2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ra);
2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(),
2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     object,
2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     result,
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     HeapNumber::kValueOffset - kHeapObjectTag,
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     true,
2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     true);
2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(ra);
2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateNumberToI(Register object,
2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register result,
2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register heap_number_map,
2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register scratch,
2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Label* not_number) {
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(object));
2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UntagAndJumpIfSmi(result, object, &done);
2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number);
2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TruncateHeapNumberToI(result, object);
2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
26773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
26783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::GetLeastBitsFromSmi(Register dst,
2681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                         Register src,
2682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                         int num_least_bits) {
2683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Ext(dst, src, kSmiTagSize, num_least_bits);
2684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::GetLeastBitsFromInt32(Register dst,
2688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           Register src,
2689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           int num_least_bits) {
2690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  And(dst, src, Operand((1 << num_least_bits) - 1));
2691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
269444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Emulated condtional branches do not emit a nop in the branch delay slot.
269544f0eee88ff00398ff7f715fab053374d808c90dSteve Block//
269644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// BRANCH_ARGS_CHECK checks that conditional jump arguments are correct.
2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define BRANCH_ARGS_CHECK(cond, rs, rt) DCHECK(                                \
269844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) ||          \
269944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg))))
270044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
270144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Branch(int32_t offset, BranchDelaySlot bdslot) {
2703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6) ? is_int26(offset) : is_int16(offset));
27043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BranchShort(offset, bdslot);
27053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
27063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Branch(int32_t offset, Condition cond, Register rs,
2709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            const Operand& rt, BranchDelaySlot bdslot) {
2710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_near = BranchShortCheck(offset, nullptr, cond, rs, rt, bdslot);
2711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(is_near);
2712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  USE(is_near);
27133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
27143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) {
27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
2718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (is_near_branch(L)) {
27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(L, bdslot);
27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchLong(L, bdslot);
27223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
27233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
27243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchLong(L, bdslot);
27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(L, bdslot);
27283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
27293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
27303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
27313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Branch(Label* L, Condition cond, Register rs,
27343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                            const Operand& rt,
27353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                            BranchDelaySlot bdslot) {
27363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
2737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!BranchShortCheck(0, L, cond, rs, rt, bdslot)) {
2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (cond != cc_always) {
2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label skip;
2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Condition neg_cond = NegateCondition(cond);
2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        BranchShort(&skip, neg_cond, rs, rt);
2742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchLong(L, bdslot);
2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        bind(&skip);
2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchLong(L, bdslot);
2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
27483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (cond != cc_always) {
2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label skip;
2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Condition neg_cond = NegateCondition(cond);
2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        BranchShort(&skip, neg_cond, rs, rt);
2754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchLong(L, bdslot);
2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        bind(&skip);
2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchLong(L, bdslot);
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(L, cond, rs, rt, bdslot);
27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
27623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
27633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
27643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Branch(Label* L,
27673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Condition cond,
27683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Register rs,
27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Heap::RootListIndex index,
27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            BranchDelaySlot bdslot) {
27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(at, index);
27723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(L, cond, rs, Operand(at), bdslot);
27733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShortHelper(int16_t offset, Label* L,
2777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       BranchDelaySlot bdslot) {
2778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
2779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  offset = GetOffset(offset, L, OffsetSize::kOffset16);
278044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(offset);
278144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
278244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
278344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
278444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
27853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
27863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShortHelperR6(int32_t offset, Label* L) {
2789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
2790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  offset = GetOffset(offset, L, OffsetSize::kOffset26);
2791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bc(offset);
2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
279344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShort(int32_t offset, BranchDelaySlot bdslot) {
2796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
2797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_int26(offset));
2798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchShortHelperR6(offset, nullptr);
279944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
2800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_int16(offset));
2801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchShortHelper(offset, nullptr, bdslot);
28023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
280344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
280444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
28053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) {
2807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
2808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchShortHelperR6(0, L);
2809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchShortHelper(0, L, bdslot);
2811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
28133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic inline bool IsZero(const Operand& rt) {
2816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (rt.is_reg()) {
2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return rt.rm().is(zero_reg);
2818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return rt.immediate() == 0;
2820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
282144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
28223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochint32_t MacroAssembler::GetOffset(int32_t offset, Label* L, OffsetSize bits) {
2825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (L) {
2826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    offset = branch_offset_helper(L, bits) >> 2;
2827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_intn(offset, bits));
2829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return offset;
2831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
283244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRegister MacroAssembler::GetRtAsRegisterHelper(const Operand& rt,
2835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                               Register scratch) {
283644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register r2 = no_reg;
283744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (rt.is_reg()) {
283844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    r2 = rt.rm_;
2839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    r2 = scratch;
2841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    li(r2, rt);
2842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return r2;
2845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchShortHelperR6(int32_t offset, Label* L,
2849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         Condition cond, Register rs,
2850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         const Operand& rt) {
2851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
2852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = rs.is(at) ? t8 : at;
2853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  OffsetSize bits = OffsetSize::kOffset16;
2854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Be careful to always use shifted_branch_offset only just before the
2856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // branch instruction, as the location will be remember for patching the
2857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // target.
2858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
2859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
286044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    switch (cond) {
286144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case cc_always:
2862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bits = OffsetSize::kOffset26;
2863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
2864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
2865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bc(offset);
286644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
286744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case eq:
2868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Pre R6 beq is used here to make the code patchable. Otherwise bc
2870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // should be used which has no condition field so is not patchable.
2871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(rs, scratch, offset);
2876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          nop();
2877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
2879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beqzc(rs, offset);
2882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
2883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // We don't want any other register but scratch clobbered.
2884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beqc(rs, scratch, offset);
2889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
289044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
289144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case ne:
2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Pre R6 bne is used here to make the code patchable. Otherwise we
2894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // should not generate any instruction.
2895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(rs, scratch, offset);
2900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          nop();
2901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
2903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bnezc(rs, offset);
2906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
2907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // We don't want any other register but scratch clobbered.
2908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bnec(rs, scratch, offset);
2913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
291444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
2915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Signed comparison.
291744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater:
2918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs > rt
2919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;  // No code needs to be emitted.
2921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltzc(scratch, offset);
2927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgtzc(rs, offset);
293244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltc(scratch, rs, offset);
293944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
294044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
294144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater_equal:
2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs >= rt
2943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
2945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
2948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          blezc(scratch, offset);
2954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgezc(rs, offset);
295944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgec(rs, scratch, offset);
296644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
296744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
296844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less:
2969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs < rt
2970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;  // No code needs to be emitted.
2972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgtzc(scratch, offset);
2978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltzc(rs, offset);
298344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltc(rs, scratch, offset);
299044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
299144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
299244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less_equal:
2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs <= rt
2994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
2996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
2999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
3000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
3001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgezc(scratch, offset);
3005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
3006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
3007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          blezc(rs, offset);
301044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
3012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
3015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgec(scratch, rs, offset);
301744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
301844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
3019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
302044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Unsigned comparison.
302144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater:
3022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs > rt
3023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
3024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;  // No code needs to be emitted.
3025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
3026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
3027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bnezc(scratch, offset);
3031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
3032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
3033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bnezc(rs, offset);
303644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
3038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
3041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltuc(scratch, rs, offset);
304344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
304544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater_equal:
3046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs >= rt
3047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
3048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
3049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
3052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
3053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
3054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beqzc(scratch, offset);
3058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
3059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
3060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
306344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
3065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
3068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgeuc(rs, scratch, offset);
307044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
307144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
307244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless:
3073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs < rt
3074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
3075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;  // No code needs to be emitted.
3076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
3077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
3078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bnezc(scratch, offset);
3082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
3083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;  // No code needs to be emitted.
308444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
3086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
3089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltuc(rs, scratch, offset);
309144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
309244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
309344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless_equal:
3094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs <= rt
3095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
3096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
3097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
3100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
3101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
3102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
3106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
3107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
3108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beqzc(rs, offset);
311144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
3113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
3114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
3116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
3117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgeuc(scratch, rs, offset);
311844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
311944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
312044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      default:
312144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        UNREACHABLE();
312244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
3123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckTrampolinePoolQuick(1);
3125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
3126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchShortHelper(int16_t offset, Label* L, Condition cond,
3130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register rs, const Operand& rt,
3131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       BranchDelaySlot bdslot) {
3132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
3133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!is_near(L, OffsetSize::kOffset16)) return false;
3134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = at;
3136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int32_t offset32;
3137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Be careful to always use shifted_branch_offset only just before the
3139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // branch instruction, as the location will be remember for patching the
3140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // target.
3141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
314344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    switch (cond) {
314444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case cc_always:
3145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        b(offset32);
314744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
314844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case eq:
3149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(rs, zero_reg, offset32);
3152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else {
3153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // We don't want any other register but scratch clobbered.
3154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(rs, scratch, offset32);
3157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
315844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
315944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case ne:
3160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(rs, zero_reg, offset32);
3163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else {
3164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // We don't want any other register but scratch clobbered.
3165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(rs, scratch, offset32);
3168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
316944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
3170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Signed comparison.
317244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater:
3173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgtz(rs, offset32);
317644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(scratch, zero_reg, offset32);
318044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
318144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
318244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater_equal:
3183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgez(rs, offset32);
318644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Slt(scratch, rs, rt);
3188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(scratch, zero_reg, offset32);
319044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
319144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
319244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less:
3193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltz(rs, offset32);
319644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Slt(scratch, rs, rt);
3198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(scratch, zero_reg, offset32);
320044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
320144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
320244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less_equal:
3203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          blez(rs, offset32);
320644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(scratch, zero_reg, offset32);
321044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
321144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
3212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
321344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Unsigned comparison.
321444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater:
3215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(rs, zero_reg, offset32);
321844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(scratch, zero_reg, offset32);
322244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
322344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
322444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater_equal:
3225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          b(offset32);
322844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Sltu(scratch, rs, rt);
3230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(scratch, zero_reg, offset32);
323244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
323344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
3234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case Uless:
3235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          return true;  // No code needs to be emitted.
323744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Sltu(scratch, rs, rt);
3239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(scratch, zero_reg, offset32);
324144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
324244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
324344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless_equal:
3244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(rs, zero_reg, offset32);
324744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(scratch, zero_reg, offset32);
325144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
325244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
325344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      default:
325444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        UNREACHABLE();
325544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
32563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
325744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
325844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
325944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
3260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
3262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchShortCheck(int32_t offset, Label* L, Condition cond,
3266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      Register rs, const Operand& rt,
3267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      BranchDelaySlot bdslot) {
3268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BRANCH_ARGS_CHECK(cond, rs, rt);
3269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!L) {
3270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(is_int26(offset));
3272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchShortHelperR6(offset, nullptr, cond, rs, rt);
3273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
3274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(is_int16(offset));
3275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchShortHelper(offset, nullptr, cond, rs, rt, bdslot);
3276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(offset == 0);
3279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchShortHelperR6(0, L, cond, rs, rt);
3281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
3282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchShortHelper(0, L, cond, rs, rt, bdslot);
3283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return false;
3286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShort(int32_t offset, Condition cond, Register rs,
3290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 const Operand& rt, BranchDelaySlot bdslot) {
3291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BranchShortCheck(offset, nullptr, cond, rs, rt, bdslot);
3292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
3296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 const Operand& rt, BranchDelaySlot bdslot) {
3297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BranchShortCheck(0, L, cond, rs, rt, bdslot);
32983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
32993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
33003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLink(int32_t offset, BranchDelaySlot bdslot) {
33023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BranchAndLinkShort(offset, bdslot);
33033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
33043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLink(int32_t offset, Condition cond, Register rs,
3307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   const Operand& rt, BranchDelaySlot bdslot) {
3308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_near = BranchAndLinkShortCheck(offset, nullptr, cond, rs, rt, bdslot);
3309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(is_near);
3310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  USE(is_near);
33113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
33123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) {
33153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
3316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (is_near_branch(L)) {
33173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchAndLinkShort(L, bdslot);
33183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
3319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchAndLinkLong(L, bdslot);
33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
33213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
33223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
3323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchAndLinkLong(L, bdslot);
33243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
33253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchAndLinkShort(L, bdslot);
33263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
33283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
33293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs,
33323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   const Operand& rt,
33333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   BranchDelaySlot bdslot) {
33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
3335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!BranchAndLinkShortCheck(0, L, cond, rs, rt, bdslot)) {
33363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label skip;
33373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Condition neg_cond = NegateCondition(cond);
33383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(&skip, neg_cond, rs, rt);
3339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchAndLinkLong(L, bdslot);
33403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bind(&skip);
33413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
33423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label skip;
33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Condition neg_cond = NegateCondition(cond);
33463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(&skip, neg_cond, rs, rt);
3347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchAndLinkLong(L, bdslot);
33483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bind(&skip);
33493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
3350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchAndLinkShortCheck(0, L, cond, rs, rt, bdslot);
33513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
33523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
33533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
33543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLinkShortHelper(int16_t offset, Label* L,
3357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                              BranchDelaySlot bdslot) {
3358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
3359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  offset = GetOffset(offset, L, OffsetSize::kOffset16);
336044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bal(offset);
336144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
336244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
336344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
336444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
336544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
336644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
336744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLinkShortHelperR6(int32_t offset, Label* L) {
3369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
3370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  offset = GetOffset(offset, L, OffsetSize::kOffset26);
3371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  balc(offset);
3372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
33733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLinkShort(int32_t offset,
3376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        BranchDelaySlot bdslot) {
3377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_int26(offset));
3379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchAndLinkShortHelperR6(offset, nullptr);
3380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_int16(offset));
3382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchAndLinkShortHelper(offset, nullptr, bdslot);
3383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
33853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
33863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) {
3388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchAndLinkShortHelperR6(0, L);
3390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchAndLinkShortHelper(0, L, bdslot);
33923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
339344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
339444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
339544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchAndLinkShortHelperR6(int32_t offset, Label* L,
3397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Condition cond, Register rs,
3398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                const Operand& rt) {
3399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
3400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = rs.is(at) ? t8 : at;
3401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  OffsetSize bits = OffsetSize::kOffset16;
340244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
3404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((cond == cc_always && is_int26(offset)) || is_int16(offset));
3405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (cond) {
3406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case cc_always:
3407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bits = OffsetSize::kOffset26;
3408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      balc(offset);
3411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case eq:
3413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Subu(scratch, rs, rt);
3415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      beqzalc(scratch, offset);
3417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case ne:
3419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Subu(scratch, rs, rt);
3421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bnezalc(scratch, offset);
3423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
34243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Signed comparison.
3426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case greater:
3427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs > rt
3428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (rs.code() == rt.rm_.reg_code) {
3429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;  // No code needs to be emitted.
3430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (rs.is(zero_reg)) {
3431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        scratch = GetRtAsRegisterHelper(rt, scratch);
3433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bltzalc(scratch, offset);
3435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (IsZero(rt)) {
3436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bgtzalc(rs, offset);
3439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
3440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bnezalc(scratch, offset);
3444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
3445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case greater_equal:
3447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs >= rt
3448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (rs.code() == rt.rm_.reg_code) {
3449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bits = OffsetSize::kOffset26;
3450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        balc(offset);
3453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (rs.is(zero_reg)) {
3454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        scratch = GetRtAsRegisterHelper(rt, scratch);
3456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        blezalc(scratch, offset);
3458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (IsZero(rt)) {
3459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bgezalc(rs, offset);
3462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
3463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Slt(scratch, rs, rt);
3465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        beqzalc(scratch, offset);
3467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
3468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case less:
3470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs < rt
3471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (rs.code() == rt.rm_.reg_code) {
3472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;  // No code needs to be emitted.
3473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (rs.is(zero_reg)) {
3474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        scratch = GetRtAsRegisterHelper(rt, scratch);
3476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bgtzalc(scratch, offset);
3478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (IsZero(rt)) {
3479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bltzalc(rs, offset);
3482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
3483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Slt(scratch, rs, rt);
3485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bnezalc(scratch, offset);
3487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
3488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case less_equal:
3490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs <= r2
3491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (rs.code() == rt.rm_.reg_code) {
3492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bits = OffsetSize::kOffset26;
3493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        balc(offset);
3496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (rs.is(zero_reg)) {
3497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        scratch = GetRtAsRegisterHelper(rt, scratch);
3499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bgezalc(scratch, offset);
3501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (IsZero(rt)) {
3502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        blezalc(rs, offset);
3505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
3506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        beqzalc(scratch, offset);
3510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
3511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
35123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
351344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Unsigned comparison.
3515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Ugreater:
3516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs > r2
3517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bnezalc(scratch, offset);
3521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Ugreater_equal:
3523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs >= r2
3524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, rs, rt);
3526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      beqzalc(scratch, offset);
3528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Uless:
3530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs < r2
3531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, rs, rt);
3533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bnezalc(scratch, offset);
3535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Uless_equal:
3537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs <= r2
3538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      beqzalc(scratch, offset);
3542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    default:
3544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UNREACHABLE();
35453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
3546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
3547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
35483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
35493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Pre r6 we need to use a bgezal or bltzal, but they can't be used directly
3551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// with the slt instructions. We could use sub or add instead but we would miss
3552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// overflow cases, so we keep slt and add an intermediate third instruction.
3553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchAndLinkShortHelper(int16_t offset, Label* L,
3554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                              Condition cond, Register rs,
3555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                              const Operand& rt,
3556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                              BranchDelaySlot bdslot) {
3557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
3558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!is_near(L, OffsetSize::kOffset16)) return false;
3559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = t8;
3561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
3562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (cond) {
3564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case cc_always:
3565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bal(offset);
3567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case eq:
3569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bne(rs, GetRtAsRegisterHelper(rt, scratch), 2);
3570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      nop();
3571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bal(offset);
3573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case ne:
3575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      beq(rs, GetRtAsRegisterHelper(rt, scratch), 2);
3576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      nop();
3577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bal(offset);
3579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Signed comparison.
3582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case greater:
3583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bgezal(scratch, offset);
3587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case greater_equal:
3589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Slt(scratch, rs, rt);
3590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bltzal(scratch, offset);
3593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case less:
3595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Slt(scratch, rs, rt);
3596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bgezal(scratch, offset);
3599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case less_equal:
3601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bltzal(scratch, offset);
3605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Unsigned comparison.
3608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Ugreater:
3609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bgezal(scratch, offset);
3613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Ugreater_equal:
3615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, rs, rt);
3616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bltzal(scratch, offset);
3619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Uless:
3621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, rs, rt);
3622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bgezal(scratch, offset);
3625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Uless_equal:
3627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bltzal(scratch, offset);
3631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
36323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    default:
3634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UNREACHABLE();
36353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
363644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
363744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
363844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
363944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
3640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
3642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchAndLinkShortCheck(int32_t offset, Label* L,
3646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             Condition cond, Register rs,
3647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const Operand& rt,
3648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             BranchDelaySlot bdslot) {
3649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BRANCH_ARGS_CHECK(cond, rs, rt);
3650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!L) {
3652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(is_int26(offset));
3654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchAndLinkShortHelperR6(offset, nullptr, cond, rs, rt);
3655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
3656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(is_int16(offset));
3657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchAndLinkShortHelper(offset, nullptr, cond, rs, rt, bdslot);
3658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(offset == 0);
3661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchAndLinkShortHelperR6(0, L, cond, rs, rt);
3663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
3664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchAndLinkShortHelper(0, L, cond, rs, rt, bdslot);
3665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return false;
366844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
366944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
367044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
36713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(Register target,
36723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
36733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
36743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
36753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
367644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
36773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bd == PROTECT) {
36783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (cond == cc_always) {
36793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jic(target, 0);
36803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
36813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      BRANCH_ARGS_CHECK(cond, rs, rt);
36823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Branch(2, NegateCondition(cond), rs, rt);
36833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jic(target, 0);
36843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
368544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
36863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (cond == cc_always) {
36873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jr(target);
36883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
36893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      BRANCH_ARGS_CHECK(cond, rs, rt);
36903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Branch(2, NegateCondition(cond), rs, rt);
36913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jr(target);
36923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
36933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Emit a nop in the branch delay slot if required.
36943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (bd == PROTECT) nop();
369544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
36963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
36973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
36983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
36993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(intptr_t target,
37003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
37013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
37023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
37033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
37043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label skip;
37063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cond != cc_always) {
37073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(USE_DELAY_SLOT, &skip, NegateCondition(cond), rs, rt);
37083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The first instruction of 'li' may be placed in the delay slot.
37103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is not an issue, t9 is expected to be clobbered anyway.
37113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  li(t9, Operand(target, rmode));
37123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Jump(t9, al, zero_reg, Operand(zero_reg), bd);
37133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&skip);
371444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
371544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
371644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
37173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(Address target,
37183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
37193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
37203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
37213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
37223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
3723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!RelocInfo::IsCodeTarget(rmode));
37243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd);
3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
37283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(Handle<Code> code,
37293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
37303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
37313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
37323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
37333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
3734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(RelocInfo::IsCodeTarget(rmode));
3735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference embedding_raw_address;
37363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd);
3737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
37403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint MacroAssembler::CallSize(Register target,
37413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Condition cond,
37423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Register rs,
37433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             const Operand& rt,
37443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             BranchDelaySlot bd) {
37453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int size = 0;
37463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond == cc_always) {
37483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    size += 1;
37493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
37503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    size += 3;
375144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
37523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (bd == PROTECT && !IsMipsArchVariant(kMips32r6)) size += 1;
37543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return size * kInstrSize;
37563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
37573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
37583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
375944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Note: To call gcc-compiled C code on mips, you must call thru t9.
37603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Call(Register target,
37613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
37623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
37633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
37643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
3765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef DEBUG
3766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int size = IsPrevInstrCompactBranch() ? kInstrSize : 0;
3767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
3768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
376944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
37703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label start;
37713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&start);
37723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bd == PROTECT) {
37733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (cond == cc_always) {
37743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jialc(target, 0);
37753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
37763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      BRANCH_ARGS_CHECK(cond, rs, rt);
37773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Branch(2, NegateCondition(cond), rs, rt);
37783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jialc(target, 0);
37793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
37803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
37813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (cond == cc_always) {
37823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jalr(target);
37833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
37843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      BRANCH_ARGS_CHECK(cond, rs, rt);
37853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Branch(2, NegateCondition(cond), rs, rt);
37863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jalr(target);
37873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
37883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Emit a nop in the branch delay slot if required.
37893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (bd == PROTECT) nop();
37903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
37913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef DEBUG
3793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK_EQ(size + CallSize(target, cond, rs, rt, bd),
3794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           SizeOfCodeGeneratedSince(&start));
3795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
37963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
37973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
379844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
37993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint MacroAssembler::CallSize(Address target,
38003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             RelocInfo::Mode rmode,
38013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Condition cond,
38023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Register rs,
38033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             const Operand& rt,
38043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             BranchDelaySlot bd) {
38053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int size = CallSize(t9, cond, rs, rt, bd);
38063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return size + 2 * kInstrSize;
3807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
38103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Call(Address target,
38113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
381244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Condition cond,
38133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
38143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
38153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
38163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
38173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label start;
38183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&start);
38193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int32_t target_int = reinterpret_cast<int32_t>(target);
38203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t9, Operand(target_int, rmode), CONSTANT_SIZE);
38213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Call(t9, cond, rs, rt, bd);
3822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(CallSize(target, rmode, cond, rs, rt, bd),
38233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            SizeOfCodeGeneratedSince(&start));
38243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
38253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint MacroAssembler::CallSize(Handle<Code> code,
38283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             RelocInfo::Mode rmode,
3829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             TypeFeedbackId ast_id,
38303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Condition cond,
38313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Register rs,
38323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             const Operand& rt,
38333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             BranchDelaySlot bd) {
3834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference using_raw_address;
38353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return CallSize(reinterpret_cast<Address>(code.location()),
38363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      rmode, cond, rs, rt, bd);
38373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
38383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Call(Handle<Code> code,
38413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
3842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          TypeFeedbackId ast_id,
38433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
38443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
38453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
38463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
38473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
38483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label start;
38493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&start);
3850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(RelocInfo::IsCodeTarget(rmode));
3851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
38523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SetRecordedAstId(ast_id);
38533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    rmode = RelocInfo::CODE_TARGET_WITH_ID;
385444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference embedding_raw_address;
38563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd);
3857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(CallSize(code, rmode, ast_id, cond, rs, rt, bd),
38583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            SizeOfCodeGeneratedSince(&start));
38593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
386044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
386144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Ret(Condition cond,
38633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         Register rs,
38643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         const Operand& rt,
38653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         BranchDelaySlot bd) {
38663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Jump(ra, cond, rs, rt, bd);
38673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
38683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchLong(Label* L, BranchDelaySlot bdslot) {
3871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT &&
3872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (!L->is_bound() || is_near_r6(L))) {
3873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchShortHelperR6(0, L);
3874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
3876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t imm32;
3877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    imm32 = jump_address(L);
38783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
38793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      uint32_t lui_offset, jic_offset;
38803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      UnpackTargetAddressUnsigned(imm32, lui_offset, jic_offset);
38813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      {
38823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BlockGrowBufferScope block_buf_growth(this);
38833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // Buffer growth (and relocation) must be blocked for internal
38843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // references until associated instructions are emitted and
38853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // available to be patched.
38863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
38873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        lui(at, lui_offset);
38883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        jic(at, jic_offset);
38893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
38903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      CheckBuffer();
38913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
38923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      {
38933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BlockGrowBufferScope block_buf_growth(this);
38943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // Buffer growth (and relocation) must be blocked for internal
38953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // references
38963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // until associated instructions are emitted and available to be
38973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // patched.
38983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
38993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        lui(at, (imm32 & kHiMask) >> kLuiShift);
39003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        ori(at, at, (imm32 & kImm16Mask));
39013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
39023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      CheckBuffer();
39033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jr(at);
39043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      // Emit a nop in the branch delay slot if required.
39053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (bdslot == PROTECT) nop();
3906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
39083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
39093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLinkLong(Label* L, BranchDelaySlot bdslot) {
3912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT &&
3913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (!L->is_bound() || is_near_r6(L))) {
3914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchAndLinkShortHelperR6(0, L);
3915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
3917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t imm32;
3918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    imm32 = jump_address(L);
39193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
39203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      uint32_t lui_offset, jic_offset;
39213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      UnpackTargetAddressUnsigned(imm32, lui_offset, jic_offset);
39223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      {
39233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BlockGrowBufferScope block_buf_growth(this);
39243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // Buffer growth (and relocation) must be blocked for internal
39253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // references until associated instructions are emitted and
39263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // available to be patched.
39273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
39283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        lui(at, lui_offset);
39293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        jialc(at, jic_offset);
39303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
39313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      CheckBuffer();
39323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
39333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      {
39343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BlockGrowBufferScope block_buf_growth(this);
39353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // Buffer growth (and relocation) must be blocked for internal
39363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // references
39373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // until associated instructions are emitted and available to be
39383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // patched.
39393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
39403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        lui(at, (imm32 & kHiMask) >> kLuiShift);
39413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        ori(at, at, (imm32 & kImm16Mask));
39423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
39433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      CheckBuffer();
39443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jalr(at);
39453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      // Emit a nop in the branch delay slot if required.
39463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (bdslot == PROTECT) nop();
3947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
394844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
39493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
39503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::DropAndRet(int drop) {
3953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(is_int16(drop * kPointerSize));
39543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ret(USE_DELAY_SLOT);
39553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addiu(sp, sp, drop * kPointerSize);
39563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
39573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
395844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::DropAndRet(int drop,
395944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Condition cond,
396044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Register r1,
396144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                const Operand& r2) {
39623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Both Drop and Ret need to be conditional.
396344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label skip;
396444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (cond != cc_always) {
396544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&skip, NegateCondition(cond), r1, r2);
396644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
396744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
396844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Drop(drop);
396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Ret();
397044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (cond != cc_always) {
397244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&skip);
397344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
397444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
397544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
39773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Drop(int count,
39783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
39793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register reg,
39803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& op) {
39813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (count <= 0) {
39823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return;
39833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
39843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label skip;
39863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond != al) {
39883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch     Branch(&skip, NegateCondition(cond), reg, op);
39893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
39903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Addu(sp, sp, Operand(count * kPointerSize));
39923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond != al) {
39943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bind(&skip);
39953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
39963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
39973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
400044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Swap(Register reg1,
400144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register reg2,
400244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register scratch) {
400344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (scratch.is(no_reg)) {
400444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Xor(reg1, reg1, Operand(reg2));
400544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Xor(reg2, reg2, Operand(reg1));
400644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Xor(reg1, reg1, Operand(reg2));
400744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
400844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(scratch, reg1);
400944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(reg1, reg2);
401044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(reg2, scratch);
401144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
40123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
40133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
40143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
40153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Call(Label* target) {
401644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BranchAndLink(target);
401744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
401844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
401944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
40203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Push(Handle<Object> handle) {
40213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  li(at, Operand(handle));
40223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  push(at);
40233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
40243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
40253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
402644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::DebugBreak() {
40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryArgs(0);
4028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PrepareCEntryFunction(
4029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ExternalReference(Runtime::kHandleDebuggerStatement, isolate()));
4030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1);
4031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(&ces));
4032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
403344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
403444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
40356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
40363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ---------------------------------------------------------------------------
4037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Exception handling.
40383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushStackHandler() {
40406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Adjust this code if not the case.
4041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
404269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
40463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t1, MemOperand(t2));
40473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(t1);
4048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(sp, MemOperand(t2));
40513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
40523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
40533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PopStackHandler() {
405569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
405644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pop(a1);
405744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
4058589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(at, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
405944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(a1, MemOperand(at));
406044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
406144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
406244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int object_size,
4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
4065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch1,
4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch2,
4067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
4068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
4069f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(object_size <= kMaxRegularHeapObjectSize);
4070bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
407144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!FLAG_inline_new) {
4072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
407344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Trash the registers to simulate an allocation failure.
407444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(result, 0x7091);
407544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(scratch1, 0x7191);
407644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(scratch2, 0x7291);
407744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
407844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    jmp(gc_required);
407944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return;
408044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
408144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4082109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!AreAliased(result, scratch1, scratch2, t9, at));
408344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
408444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make object size into bytes.
408544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & SIZE_IN_WORDS) != 0) {
408644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    object_size *= kPointerSize;
408744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
4088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, object_size & kObjectAlignmentMask);
408944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
409044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check relative positions of allocation top and limit addresses.
409144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // ARM adds additional checks to make sure the ldm instruction can be
409244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // used. On MIPS we don't have ldm so we don't need additional checks either.
4093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
4094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
4097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
4099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((limit - top) == kPointerSize);
410144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Set up allocation top address and allocation limit registers.
4103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register top_address = scratch1;
410444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // This code stores a temporary value in t9.
4105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register alloc_limit = t9;
4106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register result_end = scratch2;
4107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  li(top_address, Operand(allocation_top));
4108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
410944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & RESULT_CONTAINS_TOP) == 0) {
4110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Load allocation top into result and allocation limit into alloc_limit.
4111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(result, MemOperand(top_address));
4112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(alloc_limit, MemOperand(top_address, kPointerSize));
411344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
4114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
4115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Assert that result actually contains top on entry.
4116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      lw(alloc_limit, MemOperand(top_address));
4117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit));
411844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
4119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Load allocation limit. Result already contains allocation top.
4120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(alloc_limit, MemOperand(top_address, limit - top));
412144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
412244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Align the next allocation. Storing the filler map without checking top is
4125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // safe in new-space because the limit of the heap is aligned there.
4126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
4127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    And(result_end, result, Operand(kDoubleAlignmentMask));
4128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
4129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Branch(&aligned, eq, result_end, Operand(zero_reg));
4130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
4131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Branch(gc_required, Ugreater_equal, result, Operand(alloc_limit));
4132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    li(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
4134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sw(result_end, MemOperand(result));
4135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Addu(result, result, Operand(kDoubleSize / 2));
4136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
4137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
413944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate new top and bail out if new space is exhausted. Use result
414044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to calculate the new top.
4141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Addu(result_end, result, Operand(object_size));
4142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(gc_required, Ugreater, result_end, Operand(alloc_limit));
414344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
4145bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
4146bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sw(result_end, MemOperand(top_address));
414744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
4148bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4149bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag object.
4150bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(result, result, Operand(kHeapObjectTag));
41513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
41523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
41533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Allocate(Register object_size, Register result,
4155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              Register result_end, Register scratch,
4156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              Label* gc_required, AllocationFlags flags) {
4157bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
415844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!FLAG_inline_new) {
4159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
416044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Trash the registers to simulate an allocation failure.
416144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(result, 0x7091);
4162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      li(scratch, 0x7191);
4163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      li(result_end, 0x7291);
416444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
416544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    jmp(gc_required);
416644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return;
416744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
41683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
4170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // is not specified. Other registers must not overlap.
4171109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!AreAliased(object_size, result, scratch, t9, at));
4172109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!AreAliased(result_end, result, scratch, t9, at));
4173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
417444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
417544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check relative positions of allocation top and limit addresses.
417644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // ARM adds additional checks to make sure the ldm instruction can be
417744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // used. On MIPS we don't have ldm so we don't need additional checks either.
4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
4181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
4182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
4183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
4184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((limit - top) == kPointerSize);
418544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Set up allocation top address and allocation limit registers.
4187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register top_address = scratch;
418844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // This code stores a temporary value in t9.
4189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register alloc_limit = t9;
4190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  li(top_address, Operand(allocation_top));
4191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
419244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & RESULT_CONTAINS_TOP) == 0) {
4193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Load allocation top into result and allocation limit into alloc_limit.
4194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(result, MemOperand(top_address));
4195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(alloc_limit, MemOperand(top_address, kPointerSize));
419644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
4197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
4198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Assert that result actually contains top on entry.
4199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      lw(alloc_limit, MemOperand(top_address));
4200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit));
420144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
4202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Load allocation limit. Result already contains allocation top.
4203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(alloc_limit, MemOperand(top_address, limit - top));
420444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
42053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Align the next allocation. Storing the filler map without checking top is
4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // safe in new-space because the limit of the heap is aligned there.
4209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
4210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    And(result_end, result, Operand(kDoubleAlignmentMask));
4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
4212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Branch(&aligned, eq, result_end, Operand(zero_reg));
4213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
4214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Branch(gc_required, Ugreater_equal, result, Operand(alloc_limit));
4215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    li(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
4217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sw(result_end, MemOperand(result));
4218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Addu(result, result, Operand(kDoubleSize / 2));
4219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
4220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
422244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate new top and bail out if new space is exhausted. Use result
422344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to calculate the new top. Object size may be in words so a shift is
422444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // required to get the number of bytes.
422544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & SIZE_IN_WORDS) != 0) {
4226109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Lsa(result_end, result, object_size, kPointerSizeLog2);
422744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
4228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Addu(result_end, result, Operand(object_size));
422944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
4230bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(gc_required, Ugreater, result_end, Operand(alloc_limit));
423244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
423344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Update allocation top. result temporarily holds the new top.
4234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
4235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    And(alloc_limit, result_end, Operand(kObjectAlignmentMask));
4236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(eq, kUnalignedAllocationInNewSpace, alloc_limit, Operand(zero_reg));
423744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
42386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4239bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
4240bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
4241bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sw(result_end, MemOperand(top_address));
424244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
4243bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4244bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag object.
4245bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(result, result, Operand(kHeapObjectTag));
424644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
42476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4248bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(int object_size, Register result,
4249bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register scratch1, Register scratch2,
4250bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  AllocationFlags flags) {
4251f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(object_size <= kMaxRegularHeapObjectSize);
4252bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!AreAliased(result, scratch1, scratch2, t9, at));
4253bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Make object size into bytes.
4255bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & SIZE_IN_WORDS) != 0) {
4256bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    object_size *= kPointerSize;
4257bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4258bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK_EQ(0, object_size & kObjectAlignmentMask);
4259bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4260bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ExternalReference allocation_top =
4261bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4262bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4263bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Set up allocation top address and allocation limit registers.
4264bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register top_address = scratch1;
4265bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // This code stores a temporary value in t9.
4266bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register result_end = scratch2;
4267bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(top_address, Operand(allocation_top));
4268bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lw(result, MemOperand(top_address));
4269bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4270bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4271bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Align the next allocation. Storing the filler map without checking top is
4272bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // safe in new-space because the limit of the heap is aligned there.
4273bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
4274bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    And(result_end, result, Operand(kDoubleAlignmentMask));
4275bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
4276bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Branch(&aligned, eq, result_end, Operand(zero_reg));
4277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    li(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
4278bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sw(result_end, MemOperand(result));
4279bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Addu(result, result, Operand(kDoubleSize / 2));
4280bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
4281bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4282bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4283bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(result_end, result, Operand(object_size));
4284bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4285bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // The top pointer is not updated for allocation folding dominators.
4286bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sw(result_end, MemOperand(top_address));
4287bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4288bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(result, result, Operand(kHeapObjectTag));
4289bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
4290bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4291bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(Register object_size, Register result,
4292bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, Register scratch,
4293bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  AllocationFlags flags) {
4294bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
4295bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // is not specified. Other registers must not overlap.
4296bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!AreAliased(object_size, result, scratch, t9, at));
4297bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!AreAliased(result_end, result, scratch, t9, at));
4298bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
4299bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4300bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ExternalReference allocation_top =
4301bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4302bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4303bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Set up allocation top address and allocation limit registers.
4304bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register top_address = scratch;
4305bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // This code stores a temporary value in t9.
4306bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(top_address, Operand(allocation_top));
4307bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lw(result, MemOperand(top_address));
4308bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4309bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4310bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Align the next allocation. Storing the filler map without checking top is
4311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // safe in new-space because the limit of the heap is aligned there.
4312bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
4313bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    And(result_end, result, Operand(kDoubleAlignmentMask));
4314bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
4315bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Branch(&aligned, eq, result_end, Operand(zero_reg));
4316bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    li(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
4317bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sw(result_end, MemOperand(result));
4318bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Addu(result, result, Operand(kDoubleSize / 2));
4319bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
4320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4321bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4322bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Calculate new top and bail out if new space is exhausted. Use result
4323bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // to calculate the new top. Object size may be in words so a shift is
4324bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // required to get the number of bytes.
4325bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & SIZE_IN_WORDS) != 0) {
4326bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Lsa(result_end, result, object_size, kPointerSizeLog2);
4327bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
4328bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Addu(result_end, result, Operand(object_size));
4329bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4330bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4331bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // The top pointer is not updated for allocation folding dominators.
4332bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sw(result_end, MemOperand(top_address));
4333bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4334bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(result, result, Operand(kHeapObjectTag));
4335bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
433644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
433744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateTwoByteString(Register result,
433844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register length,
433944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register scratch1,
434044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register scratch2,
434144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register scratch3,
434244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Label* gc_required) {
434344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate the number of bytes needed for the characters in the string while
434444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // observing object alignment.
4345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
434644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sll(scratch1, length, 1);  // Length in bytes, not chars.
434744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  addiu(scratch1, scratch1,
434844f0eee88ff00398ff7f715fab053374d808c90dSteve Block       kObjectAlignmentMask + SeqTwoByteString::kHeaderSize);
434944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
435044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
435144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate two-byte string in new space.
4352bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(scratch1, result, scratch2, scratch3, gc_required,
4353bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
435444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
435544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Set the map, length and hash field.
435644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeNewString(result,
435744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      length,
435844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Heap::kStringMapRootIndex,
435944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch1,
436044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch2);
436144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
436244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
436344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, Register length,
4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch1, Register scratch2,
4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch3,
4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Label* gc_required) {
436844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate the number of bytes needed for the characters in the string
436944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // while observing object alignment.
4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kCharSize == 1);
4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addiu(scratch1, length, kObjectAlignmentMask + SeqOneByteString::kHeaderSize);
437344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
437444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate one-byte string in new space.
4376bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(scratch1, result, scratch2, scratch3, gc_required,
4377bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
437844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
437944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Set the map, length and hash field.
4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
4381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch1, scratch2);
438244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
438344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
438444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
438544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateTwoByteConsString(Register result,
438644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register length,
438744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register scratch1,
438844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register scratch2,
438944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Label* gc_required) {
4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
4391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
439244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeNewString(result,
439344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      length,
439444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Heap::kConsStringMapRootIndex,
439544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch1,
439644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch2);
439744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
439844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
439944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteConsString(Register result, Register length,
4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch1,
4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch2,
4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Label* gc_required) {
4404bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
4405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch1, scratch2);
440944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
441044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
441144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4412589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
4413589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                 Register length,
4414589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                 Register scratch1,
4415589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                 Register scratch2,
4416589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                 Label* gc_required) {
4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
4418bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
4419589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4420589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  InitializeNewString(result,
4421589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      length,
4422589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      Heap::kSlicedStringMapRootIndex,
4423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      scratch1,
4424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      scratch2);
4425589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
4426589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteSlicedString(Register result,
4429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register length,
4430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch1,
4431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch2,
4432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Label* gc_required) {
4433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
4434bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
4435589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
4437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch1, scratch2);
4438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Register reg,
4442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name) {
4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label succeed;
4445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  And(at, reg, Operand(kIsNotStringMask | kIsNotInternalizedMask));
4446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(&succeed, eq, at, Operand(zero_reg));
4447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(not_unique_name, ne, reg, Operand(SYMBOL_TYPE));
4448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&succeed);
4450589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
4451589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4452589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
445344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Allocates a heap number or jumps to the label if the young space is full and
445444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// a scavenge is needed.
445544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
445644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch1,
445744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch2,
445844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register heap_number_map,
4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Label* need_gc,
4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        MutableMode mode) {
446144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate an object in the heap for the heap number and tag it as a heap
446244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // object.
4463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc,
4464bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
4465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap::RootListIndex map_index = mode == MUTABLE
4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? Heap::kMutableHeapNumberMapRootIndex
4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Heap::kHeapNumberMapRootIndex;
4469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertIsRoot(heap_number_map, map_index);
447044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
447144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Store heap number map in the allocated object.
4472bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
447344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
447444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
447544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
447644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateHeapNumberWithValue(Register result,
447744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 FPURegister value,
447844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Register scratch1,
447944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Register scratch2,
448044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Label* gc_required) {
44813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
44823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required);
448344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset));
448444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
448544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
448644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AllocateJSValue(Register result, Register constructor,
4488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register value, Register scratch1,
4489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register scratch2, Label* gc_required) {
4490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(constructor));
4491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch1));
4492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch2));
4493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(value));
449444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate JSValue in new space.
4496bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
4497bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
44986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize the JSValue.
4500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
4501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sw(scratch1, FieldMemOperand(result, HeapObject::kMapOffset));
4502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
4503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sw(scratch1, FieldMemOperand(result, JSObject::kPropertiesOffset));
4504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sw(scratch1, FieldMemOperand(result, JSObject::kElementsOffset));
4505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sw(value, FieldMemOperand(result, JSValue::kValueOffset));
4506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
450744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
45086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register current_address,
4510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Register end_address,
45113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
45123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
45133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&entry);
45143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
4515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sw(filler, MemOperand(current_address));
4516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Addu(current_address, current_address, kPointerSize);
45173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
4518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(&loop, ult, current_address, Operand(end_address));
45193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
45203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map,
45223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register scratch,
45233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* fail) {
4524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
4525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
4526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 2);
4527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
45283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
45293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(fail, ls, scratch,
4530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
45313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(fail, hi, scratch,
4532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(Map::kMaximumBitField2FastHoleyElementValue));
45333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
45343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckFastSmiElements(Register map,
4537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Register scratch,
4538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label* fail) {
4539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
4540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
45413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
45423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(fail, hi, scratch,
4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
45443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
45453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
45483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register key_reg,
45493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register elements_reg,
45503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register scratch1,
45513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register scratch2,
45523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register scratch3,
4553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Label* fail,
4554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 int elements_offset) {
4555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!AreAliased(value_reg, key_reg, elements_reg, scratch1, scratch2,
4556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     scratch3));
455713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Label smi_value, done;
45583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle smi values specially.
45603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(value_reg, &smi_value);
45613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Ensure that the object is a heap number
45633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckMap(value_reg,
45643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           scratch1,
45653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Heap::kHeapNumberMapRootIndex,
45663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fail,
45673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           DONT_DO_SMI_CHECK);
45683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
456913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Double value, turn potential sNaN into qNan.
457013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DoubleRegister double_result = f0;
457113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DoubleRegister double_scratch = f2;
457213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
457313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ldc1(double_result, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
457413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Branch(USE_DELAY_SLOT, &done);  // Canonicalization is one instruction.
457513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  FPUCanonicalizeNaN(double_result, double_result);
45763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&smi_value);
457813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Register untagged_value = scratch2;
457913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SmiUntag(untagged_value, value_reg);
458013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  mtc1(untagged_value, double_scratch);
458113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  cvt_d_w(double_result, double_scratch);
458213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
458313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bind(&done);
45843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(scratch1, elements_reg,
4585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag -
4586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              elements_offset));
4587109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Lsa(scratch1, scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize);
45883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // scratch1 is now effective address of the double element
458913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  sdc1(double_result, MemOperand(scratch1, 0));
459013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
459113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
45923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CompareMapAndBranch(Register obj,
45933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch,
45943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Handle<Map> map,
45953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Label* early_success,
45963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Condition cond,
4597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label* branch_to) {
45983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
4599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMapAndBranch(scratch, map, early_success, cond, branch_to);
4600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
46013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareMapAndBranch(Register obj_map,
4604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Handle<Map> map,
4605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label* early_success,
4606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Condition cond,
4607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label* branch_to) {
4608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(branch_to, cond, obj_map, Operand(map));
46093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
461244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CheckMap(Register obj,
461344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Register scratch,
461444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Handle<Map> map,
461544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Label* fail,
4616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              SmiCheckType smi_check_type) {
4617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
461844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    JumpIfSmi(obj, fail);
461944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
46203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label success;
4621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMapAndBranch(obj, scratch, map, &success, ne, fail);
46223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&success);
46236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
46246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
4627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Register scratch2, Handle<WeakCell> cell,
4628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Handle<Code> success,
4629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     SmiCheckType smi_check_type) {
4630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
4631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
4632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
4633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  lw(scratch1, FieldMemOperand(obj, HeapObject::kMapOffset));
4635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GetWeakValue(scratch2, cell);
4636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Jump(success, RelocInfo::CODE_TARGET, eq, scratch1, Operand(scratch2));
4637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
4638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
464144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CheckMap(Register obj,
464244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Register scratch,
464344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Heap::RootListIndex index,
464444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Label* fail,
4645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                              SmiCheckType smi_check_type) {
4646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
464744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    JumpIfSmi(obj, fail);
464844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
464944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
465044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadRoot(at, index);
465144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(fail, ne, scratch, Operand(at));
46526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
46536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
465413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid MacroAssembler::FPUCanonicalizeNaN(const DoubleRegister dst,
465513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                        const DoubleRegister src) {
465613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  sub_d(dst, src, kDoubleRegZero);
465713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
46586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
4660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  li(value, Operand(cell));
4661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  lw(value, FieldMemOperand(value, WeakCell::kValueOffset));
4662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
4663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
4666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                   Label* miss) {
4667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GetWeakValue(value, cell);
4668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JumpIfSmi(value, miss);
4669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
4670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MovFromFloatResult(DoubleRegister dst) {
4673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IsMipsSoftFloatABI) {
4674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
4675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(dst, v0, v1);
4676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(dst, v1, v0);
4678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(dst, f0);  // Reg f0 is o32 ABI FP return value.
4681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MovFromFloatParameter(DoubleRegister dst) {
4686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsSoftFloatABI) {
4687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
4688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(dst, a0, a1);
4689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(dst, a1, a0);
4691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, f12);  // Reg f12 is o32 ABI FP first argument value.
4694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MovToFloatParameter(DoubleRegister src) {
4699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!IsMipsSoftFloatABI) {
4700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(f12, src);
4701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
4703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a0, a1, src);
4704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
4705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a1, a0, src);
4706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MovToFloatResult(DoubleRegister src) {
4712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!IsMipsSoftFloatABI) {
4713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(f0, src);
4714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
4716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(v0, v1, src);
4717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(v1, v0, src);
4719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MovToFloatParameters(DoubleRegister src1,
4725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          DoubleRegister src2) {
4726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsMipsSoftFloatABI) {
4727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (src2.is(f12)) {
4728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!src1.is(f14));
4729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(f14, src2);
4730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(f12, src1);
4731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(f12, src1);
4733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(f14, src2);
4734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
4737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a0, a1, src1);
4738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a2, a3, src2);
4739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a1, a0, src1);
4741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a3, a2, src2);
4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
47476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// -----------------------------------------------------------------------------
4748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// JavaScript invokes.
47496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
47503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
47513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                        Register caller_args_count_reg,
47523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                        Register scratch0, Register scratch1) {
47533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
47543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
47553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
47563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                       scratch1));
47573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
47583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
47593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
47603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
47613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
47623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Calculate the end of destination area where we will put the arguments
47633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // after we drop current frame. We add kPointerSize to count the receiver
47643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // argument which is not included into formal parameters count.
47653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register dst_reg = scratch0;
47663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Lsa(dst_reg, fp, caller_args_count_reg, kPointerSizeLog2);
47673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Addu(dst_reg, dst_reg,
47683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize));
47693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
47703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register src_reg = caller_args_count_reg;
47713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Calculate the end of source area. +kPointerSize is for the receiver.
47723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
47733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Lsa(src_reg, sp, callee_args_count.reg(), kPointerSizeLog2);
47743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Addu(src_reg, src_reg, Operand(kPointerSize));
47753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
47763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Addu(src_reg, sp,
47773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Operand((callee_args_count.immediate() + 1) * kPointerSize));
47783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
47793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
47803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (FLAG_debug_code) {
47813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(lo, kStackAccessBelowStackPointer, src_reg, Operand(dst_reg));
47823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
47833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
47843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Restore caller's frame pointer and return address now as they will be
47853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // overwritten by the copying loop.
47863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
47873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
47883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
47893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Now copy callee arguments to the caller frame going backwards to avoid
47903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // callee arguments corruption (source and destination areas could overlap).
47913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
47923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Both src_reg and dst_reg are pointing to the word after the one to copy,
47933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // so they must be pre-decremented in the loop.
47943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register tmp_reg = scratch1;
47953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, entry;
47963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Branch(&entry);
47973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&loop);
47983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Subu(src_reg, src_reg, Operand(kPointerSize));
47993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Subu(dst_reg, dst_reg, Operand(kPointerSize));
48003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(tmp_reg, MemOperand(src_reg));
48013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(tmp_reg, MemOperand(dst_reg));
48023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&entry);
48033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Branch(&loop, ne, sp, Operand(src_reg));
48043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
48053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Leave current frame.
48063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(sp, dst_reg);
48073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
48083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
48096ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
48106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    const ParameterCount& actual,
48116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    Label* done,
48123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
481344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    InvokeFlag flag,
4814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
48156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool definitely_matches = false;
48163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
48176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label regular_invoke;
48186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
48196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check whether the expected and actual arguments count match. If not,
48206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // setup registers according to contract with ArgumentsAdaptorTrampoline:
48216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  a0: actual arguments count
48226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  a1: function (passed through to callee)
48236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  a2: expected arguments count
48246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
48256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // The code below is made a lot easier because the calling code already sets
48266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // up actual and expected registers according to the contract if values are
48276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // passed in registers.
4828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(actual.is_immediate() || actual.reg().is(a0));
4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expected.is_immediate() || expected.reg().is(a2));
48306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
48316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (expected.is_immediate()) {
4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(actual.is_immediate());
4833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    li(a0, Operand(actual.immediate()));
48346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (expected.immediate() == actual.immediate()) {
48356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      definitely_matches = true;
48366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
48376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
48386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (expected.immediate() == sentinel) {
48396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // Don't worry about adapting arguments for builtins that
48406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // don't want that done. Skip adaption code by making it look
48416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // like we have a match between expected and actual number of
48426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // arguments.
48436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        definitely_matches = true;
48446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
48453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
48466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        li(a2, Operand(expected.immediate()));
48476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
48486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
4849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (actual.is_immediate()) {
4850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    li(a0, Operand(actual.immediate()));
4851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Branch(&regular_invoke, eq, expected.reg(), Operand(a0));
48526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
4853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Branch(&regular_invoke, eq, expected.reg(), Operand(actual.reg()));
48546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
48556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
48566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!definitely_matches) {
485744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> adaptor =
485844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->builtins()->ArgumentsAdaptorTrampoline();
48596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (flag == CALL_FUNCTION) {
48603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor));
48613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Call(adaptor);
4862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
48633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
48643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Branch(done);
48653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
48666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
486744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Jump(adaptor, RelocInfo::CODE_TARGET);
48686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
48696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&regular_invoke);
48706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
48716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
48726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
487344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target,
4875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& expected,
4876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& actual) {
4877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label skip_flooding;
487813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ExternalReference last_step_action =
487913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ExternalReference::debug_last_step_action_address(isolate());
488013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  STATIC_ASSERT(StepFrame > StepIn);
488113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  li(t0, Operand(last_step_action));
4882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lb(t0, MemOperand(t0));
488313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Branch(&skip_flooding, lt, t0, Operand(StepIn));
4884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
4885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(this,
4886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
4887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
4888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(expected.reg());
4889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(expected.reg());
4890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
4892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(actual.reg());
4893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(actual.reg());
4894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
4896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(new_target);
4897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
4899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
4900109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
4901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(fun);
4902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
4903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(new_target);
4904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
4906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(actual.reg());
4907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(actual.reg());
4908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
4910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(expected.reg());
4911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(expected.reg());
4912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&skip_flooding);
4915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
4919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& expected,
4920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& actual,
4921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        InvokeFlag flag,
4922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const CallWrapper& call_wrapper) {
49233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
4925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(a1));
4926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_IMPLIES(new_target.is_valid(), new_target.is(a3));
49273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (call_wrapper.NeedsDebugStepCheck()) {
4929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FloodFunctionIfStepping(function, new_target, expected, actual);
4930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear the new.target register if not given.
4933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!new_target.is_valid()) {
4934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadRoot(a3, Heap::kUndefinedValueRootIndex);
4935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
49366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done;
49383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
4939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 call_wrapper);
49413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
4942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We call indirectly through the code field in the function to
4943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // allow recompilation to take effect without changing any of the
4944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // call sites.
4945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register code = t0;
4946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(code, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
49473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
49483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
49493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Call(code);
49503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
49513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(flag == JUMP_FUNCTION);
49533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jump(code);
49543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
49553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Continue here if InvokePrologue does handle the invocation due to
49563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // mismatched parameter counts.
49573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
49586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
49596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
49606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
49616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
49626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InvokeFunction(Register function,
4963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Register new_target,
49646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    const ParameterCount& actual,
496544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    InvokeFlag flag,
4966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
49673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
4968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
49693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Contract with called JS functions requires that function is passed in a1.
4971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(function.is(a1));
49726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register expected_reg = a2;
4973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register temp_reg = t0;
49746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(temp_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
49766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
49776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(expected_reg,
4978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch     FieldMemOperand(temp_reg,
4979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     SharedFunctionInfo::kFormalParameterCountOffset));
498044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sra(expected_reg, expected_reg, kSmiTagSize);
49816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
49826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ParameterCount expected(expected_reg);
4983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(function, new_target, expected, actual, flag,
4984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     call_wrapper);
498544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
498644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
498744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Register function,
4989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
499044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    const ParameterCount& actual,
49913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                    InvokeFlag flag,
4992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
49933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
4994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Contract with called JS functions requires that function is passed in a1.
4997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(function.is(a1));
499844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
499944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the function and setup the context.
500044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
500144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(a1, no_reg, expected, actual, flag, call_wrapper);
5003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
5007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
5008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& actual,
5009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    InvokeFlag flag,
5010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
5011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  li(a1, function);
5012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InvokeFunction(a1, expected, actual, flag, call_wrapper);
501344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
501444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
501544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
501644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::IsObjectJSStringType(Register object,
501744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Register scratch,
501844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Label* fail) {
5019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kNotStringTag != 0);
502044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
502144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
502244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
502344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch, scratch, Operand(kIsNotStringMask));
502444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(fail, ne, scratch, Operand(zero_reg));
50256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
50266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
50276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::IsObjectNameType(Register object,
5029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Register scratch,
5030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Label* fail) {
5031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
5032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
5033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(fail, hi, scratch, Operand(LAST_NAME_TYPE));
5034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// ---------------------------------------------------------------------------
50386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Support functions.
50396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
50406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetMapConstructor(Register result, Register map,
5042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register temp, Register temp2) {
5043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done, loop;
5044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
5045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&loop);
5046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(result, &done);
5047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GetObjectType(result, temp, temp2);
5048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(&done, ne, temp2, Operand(MAP_TYPE));
5049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
5050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(&loop);
5051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
5052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
50536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TryGetFunctionPrototype(Register function, Register result,
5056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             Register scratch, Label* miss) {
505744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the prototype or initial map from the function.
505844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(result,
505944f0eee88ff00398ff7f715fab053374d808c90dSteve Block     FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
50606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
506144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the prototype or initial map is the hole, don't return it and
506244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // simply miss the cache instead. This will allow us to allocate a
506344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // prototype object on-demand in the runtime system.
506444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadRoot(t8, Heap::kTheHoleValueRootIndex);
506544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(miss, eq, result, Operand(t8));
50666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
506744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the function does not have an initial map, we're done.
506844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done;
506944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GetObjectType(result, scratch, scratch);
507044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&done, ne, scratch, Operand(MAP_TYPE));
50716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
507244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the prototype from the initial map.
507344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(result, FieldMemOperand(result, Map::kPrototypeOffset));
50746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
507544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // All done.
507644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
507744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
507844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
507944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
508044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::GetObjectType(Register object,
508144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register map,
508244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register type_reg) {
508344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(map, FieldMemOperand(object, HeapObject::kMapOffset));
508444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
508544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
50866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
50876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
50886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// -----------------------------------------------------------------------------
5089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Runtime calls.
50906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
50913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub,
5092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              TypeFeedbackId ast_id,
50933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Condition cond,
50943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register r1,
50953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              const Operand& r2,
50963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              BranchDelaySlot bd) {
5097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(stub));  // Stub calls are not allowed in some stubs.
5098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id,
5099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       cond, r1, r2, bd);
51003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
51013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TailCallStub(CodeStub* stub,
5104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Condition cond,
5105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Register r1,
5106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  const Operand& r2,
5107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  BranchDelaySlot bd) {
5108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2, bd);
51093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
51103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
51123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
5113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return has_frame_ || !stub->SometimesSetsUpAFrame();
51146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
51156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
511644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::ObjectToDoubleFPURegister(Register object,
511744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               FPURegister result,
511844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register scratch1,
511944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register scratch2,
512044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register heap_number_map,
512144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Label* not_number,
512244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               ObjectToDoubleFlags flags) {
512344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done;
512444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & OBJECT_NOT_SMI) == 0) {
512544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label not_smi;
512644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    JumpIfNotSmi(object, &not_smi);
512744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Remove smi tag and convert to double.
512844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sra(scratch1, object, kSmiTagSize);
512944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mtc1(scratch1, result);
513044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cvt_d_w(result, result);
513144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&done);
513244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&not_smi);
513344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
513444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check for heap number and load double value from it.
513544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
513644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(not_number, ne, scratch1, Operand(heap_number_map));
513744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
513844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & AVOID_NANS_AND_INFINITIES) != 0) {
513944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // If exponent is all ones the number is either a NaN or +/-Infinity.
514044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register exponent = scratch1;
514144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register mask_reg = scratch2;
514244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(exponent, FieldMemOperand(object, HeapNumber::kExponentOffset));
514344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(mask_reg, HeapNumber::kExponentMask);
514444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
514544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    And(exponent, exponent, mask_reg);
514644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(not_number, eq, exponent, Operand(mask_reg));
514744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
514844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ldc1(result, FieldMemOperand(object, HeapNumber::kValueOffset));
514944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
515044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
515144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
515244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
515344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::SmiToDoubleFPURegister(Register smi,
515444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            FPURegister value,
515544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Register scratch1) {
515644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sra(scratch1, smi, kSmiTagSize);
515744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mtc1(scratch1, value);
515844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cvt_d_w(value, value);
515944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
516044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
516144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic inline void BranchOvfHelper(MacroAssembler* masm, Register overflow_dst,
5163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* overflow_label,
5164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* no_overflow_label) {
5165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(overflow_label || no_overflow_label);
5166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!overflow_label) {
5167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(no_overflow_label);
5168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    masm->Branch(no_overflow_label, ge, overflow_dst, Operand(zero_reg));
5169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
5170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    masm->Branch(overflow_label, lt, overflow_dst, Operand(zero_reg));
5171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (no_overflow_label) masm->Branch(no_overflow_label);
5172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
5173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
5174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AddBranchOvf(Register dst, Register left,
5177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  const Operand& right, Label* overflow_label,
5178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* no_overflow_label, Register scratch) {
5179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (right.is_reg()) {
5180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    AddBranchOvf(dst, left, right.rm(), overflow_label, no_overflow_label,
5181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 scratch);
5182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
5183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6)) {
5184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register right_reg = t9;
5185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!left.is(right_reg));
5186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      li(right_reg, Operand(right));
5187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      AddBranchOvf(dst, left, right_reg, overflow_label, no_overflow_label);
5188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
5189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register overflow_dst = t9;
5190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!dst.is(scratch));
5191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!dst.is(overflow_dst));
5192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!scratch.is(overflow_dst));
5193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!left.is(overflow_dst));
5194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (dst.is(left)) {
5195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        mov(scratch, left);                  // Preserve left.
5196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Addu(dst, left, right.immediate());  // Left is overwritten.
5197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        xor_(scratch, dst, scratch);         // Original left.
5198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Load right since xori takes uint16 as immediate.
5199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Addu(overflow_dst, zero_reg, right);
5200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        xor_(overflow_dst, dst, overflow_dst);
5201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        and_(overflow_dst, overflow_dst, scratch);
5202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
5203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Addu(dst, left, right.immediate());
5204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        xor_(overflow_dst, dst, left);
5205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Load right since xori takes uint16 as immediate.
5206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Addu(scratch, zero_reg, right);
5207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        xor_(scratch, dst, scratch);
5208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        and_(overflow_dst, scratch, overflow_dst);
5209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
5210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
5212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
5213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
5214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AddBranchOvf(Register dst, Register left, Register right,
5217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* overflow_label,
5218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* no_overflow_label, Register scratch) {
5219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
5220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!overflow_label) {
5221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(no_overflow_label);
5222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!dst.is(scratch));
5223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register left_reg = left.is(dst) ? scratch : left;
5224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register right_reg = right.is(dst) ? t9 : right;
5225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!dst.is(left_reg));
5226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!dst.is(right_reg));
5227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(left_reg, left);
5228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(right_reg, right);
5229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(dst, left, right);
5230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Bnvc(left_reg, right_reg, no_overflow_label);
5231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
5232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Bovc(left, right, overflow_label);
5233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(dst, left, right);
5234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (no_overflow_label) bc(no_overflow_label);
5235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
5236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
5237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register overflow_dst = t9;
5238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!dst.is(scratch));
5239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!dst.is(overflow_dst));
5240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!scratch.is(overflow_dst));
5241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!left.is(overflow_dst));
5242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!right.is(overflow_dst));
5243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!left.is(scratch));
5244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!right.is(scratch));
5245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (left.is(right) && dst.is(left)) {
5247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(overflow_dst, right);
5248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      right = overflow_dst;
5249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
5250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (dst.is(left)) {
5252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(scratch, left);           // Preserve left.
5253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(dst, left, right);       // Left is overwritten.
5254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(scratch, dst, scratch);  // Original left.
5255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(overflow_dst, dst, right);
5256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      and_(overflow_dst, overflow_dst, scratch);
5257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (dst.is(right)) {
5258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(scratch, right);          // Preserve right.
5259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(dst, left, right);       // Right is overwritten.
5260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(scratch, dst, scratch);  // Original right.
5261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(overflow_dst, dst, left);
5262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      and_(overflow_dst, overflow_dst, scratch);
5263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
5264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(dst, left, right);
5265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(overflow_dst, dst, left);
5266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(scratch, dst, right);
5267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      and_(overflow_dst, scratch, overflow_dst);
5268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
5269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
5271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
5272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::SubBranchOvf(Register dst, Register left,
5275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  const Operand& right, Label* overflow_label,
5276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* no_overflow_label, Register scratch) {
5277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(overflow_label || no_overflow_label);
5278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (right.is_reg()) {
5279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SubBranchOvf(dst, left, right.rm(), overflow_label, no_overflow_label,
5280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 scratch);
5281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
5282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register overflow_dst = t9;
5283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!dst.is(scratch));
5284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!dst.is(overflow_dst));
5285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!scratch.is(overflow_dst));
5286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!left.is(overflow_dst));
5287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!left.is(scratch));
5288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (dst.is(left)) {
5289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mov(scratch, left);                      // Preserve left.
5290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Subu(dst, left, right.immediate());      // Left is overwritten.
5291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Load right since xori takes uint16 as immediate.
5292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Addu(overflow_dst, zero_reg, right);
5293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(overflow_dst, scratch, overflow_dst);  // scratch is original left.
5294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(scratch, dst, scratch);                // scratch is original left.
5295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      and_(overflow_dst, scratch, overflow_dst);
5296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
5297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Subu(dst, left, right);
5298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      xor_(overflow_dst, dst, left);
5299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Load right since xori takes uint16 as immediate.
5300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Addu(scratch, zero_reg, right);
5301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(scratch, left, scratch);
5302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      and_(overflow_dst, scratch, overflow_dst);
5303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
5304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
5306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
5307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::SubBranchOvf(Register dst, Register left, Register right,
5310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* overflow_label,
5311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* no_overflow_label, Register scratch) {
5312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(overflow_label || no_overflow_label);
5313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register overflow_dst = t9;
5314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(scratch));
5315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!dst.is(overflow_dst));
5316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!scratch.is(overflow_dst));
5317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!overflow_dst.is(left));
5318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!overflow_dst.is(right));
5319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch.is(left));
5320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch.is(right));
5321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
53223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This happens with some crankshaft code. Since Subu works fine if
53233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // left == right, let's not make that restriction here.
53243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (left.is(right)) {
53253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(dst, zero_reg);
5326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (no_overflow_label) {
5327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Branch(no_overflow_label);
5328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
53293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
53303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(left)) {
53323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(scratch, left);  // Preserve left.
53333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subu(dst, left, right);  // Left is overwritten.
53343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(overflow_dst, dst, scratch);  // scratch is original left.
53353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(scratch, scratch, right);  // scratch is original left.
53363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(overflow_dst, scratch, overflow_dst);
5337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(right)) {
53383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(scratch, right);  // Preserve right.
53393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subu(dst, left, right);  // Right is overwritten.
53403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(overflow_dst, dst, left);
53413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(scratch, left, scratch);  // Original right.
53423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(overflow_dst, scratch, overflow_dst);
5343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
5344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subu(dst, left, right);
5345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(overflow_dst, dst, left);
5346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(scratch, left, right);
5347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    and_(overflow_dst, scratch, overflow_dst);
5348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
5349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
5351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5352f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochstatic inline void BranchOvfHelperMult(MacroAssembler* masm,
5353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register overflow_dst,
5354f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Label* overflow_label,
5355f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Label* no_overflow_label) {
5356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(overflow_label || no_overflow_label);
5357f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!overflow_label) {
5358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(no_overflow_label);
5359f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    masm->Branch(no_overflow_label, eq, overflow_dst, Operand(zero_reg));
5360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
5361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    masm->Branch(overflow_label, ne, overflow_dst, Operand(zero_reg));
5362f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (no_overflow_label) masm->Branch(no_overflow_label);
5363f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
5364f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
5365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5366f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::MulBranchOvf(Register dst, Register left,
5367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  const Operand& right, Label* overflow_label,
5368f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  Label* no_overflow_label, Register scratch) {
5369f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(overflow_label || no_overflow_label);
5370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (right.is_reg()) {
5371f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    MulBranchOvf(dst, left, right.rm(), overflow_label, no_overflow_label,
5372f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 scratch);
5373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
5374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Register overflow_dst = t9;
5375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!dst.is(scratch));
5376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!dst.is(overflow_dst));
5377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!scratch.is(overflow_dst));
5378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!left.is(overflow_dst));
5379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!left.is(scratch));
5380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Mul(overflow_dst, dst, left, right.immediate());
5382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sra(scratch, dst, 31);
5383f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    xor_(overflow_dst, overflow_dst, scratch);
5384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    BranchOvfHelperMult(this, overflow_dst, overflow_label, no_overflow_label);
5386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
5387f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
5388f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5389f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::MulBranchOvf(Register dst, Register left, Register right,
5390f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  Label* overflow_label,
5391f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  Label* no_overflow_label, Register scratch) {
5392f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(overflow_label || no_overflow_label);
5393f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Register overflow_dst = t9;
5394f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!dst.is(scratch));
5395f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!dst.is(overflow_dst));
5396f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!scratch.is(overflow_dst));
5397f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!overflow_dst.is(left));
5398f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!overflow_dst.is(right));
5399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!scratch.is(left));
5400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!scratch.is(right));
5401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5402f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (IsMipsArchVariant(kMips32r6) && dst.is(right)) {
5403f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    mov(scratch, right);
5404f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Mul(overflow_dst, dst, left, scratch);
5405f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sra(scratch, dst, 31);
5406f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    xor_(overflow_dst, overflow_dst, scratch);
5407f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
5408f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Mul(overflow_dst, dst, left, right);
5409f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sra(scratch, dst, 31);
5410f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    xor_(overflow_dst, overflow_dst, scratch);
5411f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
5412f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5413f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BranchOvfHelperMult(this, overflow_dst, overflow_label, no_overflow_label);
5414f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
5415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
5417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 SaveFPRegsMode save_doubles,
5418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 BranchDelaySlot bd) {
54196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // All parameters are on the stack. v0 has the return value after call.
54206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
54216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If the expected number of arguments of the runtime function is
54226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // constant, we check that the actual number of arguments match the
54236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // expectation.
5424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->nargs < 0 || f->nargs == num_arguments);
54256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
54266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(1236192): Most runtime routines don't need the number of
54276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // arguments passed in because it is constant. At some point we
54286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // should remove this need and make the runtime routine entry code
54296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // smarter.
54303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryArgs(num_arguments);
54313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(ExternalReference(f, isolate()));
5432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1, save_doubles);
5433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallStub(&stub, TypeFeedbackId::None(), al, zero_reg, Operand(zero_reg), bd);
543444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
543544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
543644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
543744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
54383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           int num_arguments,
54393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           BranchDelaySlot bd) {
54403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryArgs(num_arguments);
54413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(ext);
544244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1);
5444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub, TypeFeedbackId::None(), al, zero_reg, Operand(zero_reg), bd);
544544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
544644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
544744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
5449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const Runtime::Function* function = Runtime::FunctionForId(fid);
5450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, function->result_size);
5451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (function->nargs >= 0) {
5452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PrepareCEntryArgs(function->nargs);
5453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
5454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpToExternalReference(ExternalReference(fid, isolate()));
54553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
54563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
54573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
5458f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             BranchDelaySlot bd,
5459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             bool builtin_exit_frame) {
54603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(builtin);
5461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CEntryStub stub(isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
5462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                  builtin_exit_frame);
54633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Jump(stub.GetCode(),
54643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       RelocInfo::CODE_TARGET,
54653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       al,
54663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       zero_reg,
54673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Operand(zero_reg),
54683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       bd);
54693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
54703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
54713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::SetCounter(StatsCounter* counter, int value,
54723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                Register scratch1, Register scratch2) {
547344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
547444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch1, Operand(value));
547544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch2, Operand(ExternalReference(counter)));
547644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch1, MemOperand(scratch2));
547744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
54783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
54793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
54803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
54813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
54823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Register scratch1, Register scratch2) {
5483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
548444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
548544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch2, Operand(ExternalReference(counter)));
548644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(scratch1, MemOperand(scratch2));
548744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(scratch1, scratch1, Operand(value));
548844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch1, MemOperand(scratch2));
548944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
54903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
54913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
54923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
54933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
54943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Register scratch1, Register scratch2) {
5495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
549644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
549744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch2, Operand(ExternalReference(counter)));
549844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(scratch1, MemOperand(scratch2));
549944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(scratch1, scratch1, Operand(value));
550044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch1, MemOperand(scratch2));
550144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
55023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
55033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
55043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
55056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// -----------------------------------------------------------------------------
5506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Debugging.
55073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Assert(Condition cc, BailoutReason reason,
55093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                            Register rs, Operand rt) {
5510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code())
5511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(cc, reason, rs, rt);
551244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
551344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
551444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
551544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AssertFastElements(Register elements) {
5516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
5517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!elements.is(at));
551844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label ok;
5519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    push(elements);
552044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
552144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadRoot(at, Heap::kFixedArrayMapRootIndex);
552244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&ok, eq, elements, Operand(at));
55233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex);
55243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Branch(&ok, eq, elements, Operand(at));
552544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);
552644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&ok, eq, elements, Operand(at));
5527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kJSObjectWithFastElementsMapHasSlowElements);
552844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&ok);
5529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    pop(elements);
553044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
55313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
55323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
55333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Check(Condition cc, BailoutReason reason,
55353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                           Register rs, Operand rt) {
553644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label L;
553744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&L, cc, rs, rt);
5538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(reason);
5539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Will not return here.
554044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&L);
55413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
55423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
55433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Abort(BailoutReason reason) {
554544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label abort_start;
554644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&abort_start);
554744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
5548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* msg = GetBailoutReason(reason);
554944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (msg != NULL) {
555044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RecordComment("Abort message: ");
555144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RecordComment(msg);
555244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trap_on_abort) {
5555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stop(msg);
5556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
5557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
555844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
555944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if Abort() has already been initialized.
5561f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(isolate()->builtins()->Abort()->IsHeapObject());
5562f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5563f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Move(a0, Smi::FromInt(static_cast<int>(reason)));
5564f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
55653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable stub call restrictions to always allow calls to abort.
55663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
55673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
55683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
55693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
5570f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
55713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5572f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
55733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Will not return here.
557544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_trampoline_pool_blocked()) {
557644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // If the calling code cares about the exact number of
557744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // instructions generated, we insert padding here to keep the size
557844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // of the Abort macro constant.
557944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Currently in debug mode with debug_code enabled the number of
5580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // generated instructions is 10, so we use this as a maximum value.
5581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const int kExpectedAbortInstructions = 10;
558244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int abort_instructions = InstructionsGeneratedSince(&abort_start);
5583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(abort_instructions <= kExpectedAbortInstructions);
558444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    while (abort_instructions++ < kExpectedAbortInstructions) {
558544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      nop();
558644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
558744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
558844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
558944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
559044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
559144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
559244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (context_chain_length > 0) {
559344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Move up the chain of contexts to the context containing the slot.
55943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lw(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
559544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 1; i < context_chain_length; i++) {
55963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      lw(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
559744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
5598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
5599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Slot is in the current function context.  Move it into the
5600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // destination register in case we store into it (the write barrier
5601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // cannot be allowed to destroy the context in esi).
5602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(dst, cp);
5603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
560444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
560544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
560644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
56073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional(
56083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind expected_kind,
56093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind transitioned_kind,
56103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register map_in_out,
56113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
56123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* no_map_match) {
5613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(expected_kind));
5614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(transitioned_kind));
56153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function's map is the same as the expected cached map.
5617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(scratch, NativeContextMemOperand());
5618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(at, ContextMemOperand(scratch, Context::ArrayMapIndex(expected_kind)));
56193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(no_map_match, ne, map_in_out, Operand(at));
56203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the transitioned cached map.
5622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(map_in_out,
5623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch     ContextMemOperand(scratch, Context::ArrayMapIndex(transitioned_kind)));
56243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
56253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadNativeContextSlot(int index, Register dst) {
5628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(dst, NativeContextMemOperand());
5629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(dst, ContextMemOperand(dst, index));
563044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
563144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
563244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
563344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
563444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  Register map,
563544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  Register scratch) {
563644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the initial map. The global functions all have initial maps.
563744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
5638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
563944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label ok, fail;
5640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
564144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&ok);
564244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&fail);
5643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kGlobalFunctionsMustHaveInitialMap);
564444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&ok);
564544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
56463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
56473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
56483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::StubPrologue(StackFrame::Type type) {
56493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  li(at, Operand(Smi::FromInt(type)));
56503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  PushCommonFrame(at);
5651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Prologue(bool code_pre_aging) {
5655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictible_code_size_scope(
5656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      this, kNoCodeAgeSequenceLength);
5657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The following three instructions must remain together and unmodified
5658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for code aging to work properly.
5659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_pre_aging) {
5660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Pre-age the code.
5661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
5662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop(Assembler::CODE_AGE_MARKER_NOP);
5663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the stub address to t9 and call it,
5664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // GetCodeAgeAndParity() extracts the stub address from this instruction.
5665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(t9,
5666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Operand(reinterpret_cast<uint32_t>(stub->instruction_start())),
5667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       CONSTANT_SIZE);
5668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop();  // Prevent jalr to jal optimization.
5669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jalr(t9, a0);
5670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop();  // Branch delay slot nop.
5671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop();  // Pad the empty space.
5672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
56733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    PushStandardFrame(a1);
5674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop(Assembler::CODE_AGE_SEQUENCE_NOP);
5675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
5680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
568113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  lw(vector, FieldMemOperand(vector, JSFunction::kLiteralsOffset));
568213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  lw(vector, FieldMemOperand(vector, LiteralsArray::kFeedbackVectorOffset));
5683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
5684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::EnterFrame(StackFrame::Type type,
5687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                bool load_constant_pool_pointer_reg) {
5688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Out-of-line constant pool not implemented on mips.
5689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  UNREACHABLE();
5690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
5691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
56936ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
56943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int stack_offset, fp_offset;
56953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (type == StackFrame::INTERNAL) {
56963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    stack_offset = -4 * kPointerSize;
56973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    fp_offset = 2 * kPointerSize;
56983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
56993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    stack_offset = -3 * kPointerSize;
57003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    fp_offset = 1 * kPointerSize;
57013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
57023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  addiu(sp, sp, stack_offset);
57033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  stack_offset = -stack_offset - kPointerSize;
57043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(ra, MemOperand(sp, stack_offset));
57053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  stack_offset -= kPointerSize;
57063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(fp, MemOperand(sp, stack_offset));
57073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  stack_offset -= kPointerSize;
57083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  li(t9, Operand(Smi::FromInt(type)));
57093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(t9, MemOperand(sp, stack_offset));
57103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (type == StackFrame::INTERNAL) {
57113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_EQ(stack_offset, kPointerSize);
57123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    li(t9, Operand(CodeObject()));
57133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sw(t9, MemOperand(sp, 0));
57143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
57153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_EQ(stack_offset, 0);
57163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
5717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Adjust FP to point to saved FP.
57183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Addu(fp, sp, Operand(fp_offset));
57196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
57206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
57216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
57226ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
57233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  addiu(sp, fp, 2 * kPointerSize);
57243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(ra, MemOperand(fp, 1 * kPointerSize));
57253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(fp, MemOperand(fp, 0 * kPointerSize));
57266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
57276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5728f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterBuiltinFrame(Register context, Register target,
5729f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register argc) {
5730f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(ra, fp);
5731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Move(fp, sp);
5732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(context, target, argc);
5733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
5734f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
5736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register argc) {
5737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(context, target, argc);
5738f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(ra, fp);
5739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
5740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
5742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                    StackFrame::Type frame_type) {
5743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(frame_type == StackFrame::EXIT ||
5744f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch         frame_type == StackFrame::BUILTIN_EXIT);
5745f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
57463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
5747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement);
5748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset);
5749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset);
57506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This is how the stack will look:
5752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // fp + 2 (==kCallerSPDisplacement) - old stack's end
5753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // [fp + 1 (==kCallerPCOffset)] - saved old ra
5754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // [fp + 0 (==kCallerFPOffset)] - saved old fp
57553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // [fp - 1 StackFrame::EXIT Smi
57563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // [fp - 2 (==kSPOffset)] - sp of the called function
57573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // [fp - 3 (==kCodeOffset)] - CodeObject
5758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the
5759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //   new stack (will contain saved ra)
57606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
57613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Save registers and reserve room for saved entry sp and code object.
57623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  addiu(sp, sp, -2 * kPointerSize - ExitFrameConstants::kFixedFrameSizeFromFp);
57633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(ra, MemOperand(sp, 4 * kPointerSize));
57643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(fp, MemOperand(sp, 3 * kPointerSize));
5765f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  li(at, Operand(Smi::FromInt(frame_type)));
57663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(at, MemOperand(sp, 2 * kPointerSize));
57673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Set up new frame pointer.
57683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  addiu(fp, sp, ExitFrameConstants::kFixedFrameSizeFromFp);
57696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
5771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    sw(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset));
5772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
5773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
57743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Accessed from ExitFrame::code_slot.
57753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(CodeObject()), CONSTANT_SIZE);
5776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
57776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
57786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Save the frame pointer and the context in top.
5779589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
578044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(fp, MemOperand(t8));
5781589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
578244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(cp, MemOperand(t8));
57836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
578544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (save_doubles) {
5786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The stack  must be allign to 0 modulo 8 for stores with sdc1.
5787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kDoubleSize == frame_alignment);
5788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (frame_alignment > 0) {
5789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
5790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      And(sp, sp, Operand(-frame_alignment));  // Align stack.
5791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
5792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int space = FPURegister::kMaxNumRegisters * kDoubleSize;
579344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(sp, sp, Operand(space));
579444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Remember: we only need to save every 2nd double FPU value.
5795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
579644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FPURegister reg = FPURegister::from_code(i);
5797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      sdc1(reg, MemOperand(sp, i * kDoubleSize));
579844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
579944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Reserve place for the return address, stack space and an optional slot
5802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (used by the DirectCEntryStub to hold the return value if a struct is
5803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // returned) and align the frame preparing for calling the runtime function.
5804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(stack_space >= 0);
5805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(sp, sp, Operand((stack_space + 2) * kPointerSize));
5806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (frame_alignment > 0) {
5807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
5808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    And(sp, sp, Operand(-frame_alignment));  // Align stack.
5809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
5810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Set the exit frame sp value to point just before the return address
5812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // location.
5813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  addiu(at, sp, kPointerSize);
5814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(at, MemOperand(fp, ExitFrameConstants::kSPOffset));
58156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
58166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
58176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
5819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    bool restore_context, bool do_return,
5820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    bool argument_count_is_length) {
582144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Optionally restore all double registers.
582244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (save_doubles) {
582344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Remember: we only need to restore every 2nd double FPU value.
5824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    lw(t8, MemOperand(fp, ExitFrameConstants::kSPOffset));
5825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
582644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FPURegister reg = FPURegister::from_code(i);
5827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ldc1(reg, MemOperand(t8, i * kDoubleSize + kPointerSize));
582844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
582944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
583044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
58316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Clear top frame.
5832589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
583344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(zero_reg, MemOperand(t8));
58346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
58356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Restore current context from top and clear it in debug mode.
5836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (restore_context) {
5837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
5838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lw(cp, MemOperand(t8));
5839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
58406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
5841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
584244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(a3, MemOperand(t8));
58436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
58446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
58456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pop the arguments, restore registers, and return.
58466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(sp, fp);  // Respect ABI stack constraint.
5847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(fp, MemOperand(sp, ExitFrameConstants::kCallerFPOffset));
5848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset));
58493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (argument_count.is_valid()) {
5851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (argument_count_is_length) {
5852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(sp, sp, argument_count);
5853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
5854109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Lsa(sp, sp, argument_count, kPointerSizeLog2, t8);
5855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
5856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
58573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
58583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (do_return) {
58593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Ret(USE_DELAY_SLOT);
58603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If returning, the instruction in the delay slot will be the addiu below.
58613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
58623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addiu(sp, sp, 8);
58636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
58646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
58656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
586644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::InitializeNewString(Register string,
586744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register length,
586844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Heap::RootListIndex map_index,
586944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch1,
587044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch2) {
587144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sll(scratch1, length, kSmiTagSize);
587244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadRoot(scratch2, map_index);
587344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(scratch1, FieldMemOperand(string, String::kLengthOffset));
587444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  li(scratch1, Operand(String::kEmptyHashField));
587544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(scratch2, FieldMemOperand(string, HeapObject::kMapOffset));
587644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(scratch1, FieldMemOperand(string, String::kHashFieldOffset));
587744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
587844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
587944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
588044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::ActivationFrameAlignment() {
5881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_HOST_ARCH_MIPS
588244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Running on the real platform. Use the alignment as mandated by the local
588344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // environment.
588444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Note: This will break if we ever start generating snapshots on one Mips
588544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // platform for another Mips platform with a different alignment.
5886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return base::OS::ActivationFrameAlignment();
5887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else  // V8_HOST_ARCH_MIPS
588844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If we are using the simulator then we should always align to the expected
588944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // alignment. As the simulator is used to generate snapshots we do not know
589044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // if the target platform will need alignment, so this is controlled from a
589144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // flag.
589244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return FLAG_sim_stack_alignment;
5893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_HOST_ARCH_MIPS
589444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
589544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
58963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::AssertStackIsAligned() {
5898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
5899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      const int frame_alignment = ActivationFrameAlignment();
5900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      const int frame_alignment_mask = frame_alignment - 1;
5901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (frame_alignment > kPointerSize) {
5903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label alignment_as_expected;
5904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
5905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        andi(at, sp, frame_alignment_mask);
5906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
5907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Don't use Check here, as it will call Runtime_Abort re-entering here.
5908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        stop("Unexpected stack alignment");
5909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        bind(&alignment_as_expected);
5910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
591144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
591244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
591344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
591444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
591544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotPowerOfTwoOrZero(
591644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register reg,
591744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register scratch,
591844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* not_power_of_two_or_zero) {
591944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Subu(scratch, reg, Operand(1));
592044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt,
592144f0eee88ff00398ff7f715fab053374d808c90dSteve Block         scratch, Operand(zero_reg));
592244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  and_(at, scratch, reg);  // In the delay slot.
592344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg));
592444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
592544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
592644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
59273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) {
5928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!reg.is(overflow));
59293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(overflow, reg);  // Save original value.
59303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiTag(reg);
59313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(overflow, overflow, reg);  // Overflow if (value ^ 2 * value) < 0.
59323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
59333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::SmiTagCheckOverflow(Register dst,
59363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register src,
59373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register overflow) {
59383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (dst.is(src)) {
59393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Fall back to slower case.
59403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiTagCheckOverflow(dst, overflow);
59413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(src));
5943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(overflow));
5944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src.is(overflow));
59453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiTag(dst, src);
59463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(overflow, dst, src);  // Overflow if (value ^ 2 * value) < 0.
59473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
59483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
59493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::UntagAndJumpIfSmi(Register dst,
59523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register src,
59533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* smi_case) {
59543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT);
59553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(dst, src);
59563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
59573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::UntagAndJumpIfNotSmi(Register dst,
59603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Register src,
59613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Label* non_smi_case) {
59623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT);
59633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(dst, src);
59643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
59653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfSmi(Register value,
59673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Label* smi_label,
59683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register scratch,
59693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               BranchDelaySlot bd) {
5970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kSmiTag);
59713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  andi(scratch, value, kSmiTagMask);
59723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(bd, smi_label, eq, scratch, Operand(zero_reg));
59733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
59743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfNotSmi(Register value,
59763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Label* not_smi_label,
59773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register scratch,
59783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  BranchDelaySlot bd) {
5979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kSmiTag);
59803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  andi(scratch, value, kSmiTagMask);
59813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg));
59823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
59833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
598544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotBothSmi(Register reg1,
598644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      Register reg2,
598744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      Label* on_not_both_smi) {
598844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
5989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(1, kSmiTagMask);
599044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  or_(at, reg1, reg2);
59913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfNotSmi(at, on_not_both_smi);
599244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
599344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
599444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
599544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfEitherSmi(Register reg1,
599644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                     Register reg2,
599744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                     Label* on_either_smi) {
599844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
5999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(1, kSmiTagMask);
600044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Both Smi tags must be 1 (not Smi).
600144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  and_(at, reg1, reg2);
60023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(at, on_either_smi);
600344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
600444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
60053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::AssertNotNumber(Register object) {
60063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (emit_debug_code()) {
60073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
60083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    andi(at, object, kSmiTagMask);
60093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(ne, kOperandIsANumber, at, Operand(zero_reg));
60103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    GetObjectType(object, t8, t8);
60113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(ne, kOperandIsNotANumber, t8, Operand(HEAP_NUMBER_TYPE));
60123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
60133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
601444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNotSmi(Register object) {
6016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
6017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
6018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andi(at, object, kSmiTagMask);
6019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(ne, kOperandIsASmi, at, Operand(zero_reg));
6020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
602144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
602244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
602344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(Register object) {
6025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
6026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
6027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andi(at, object, kSmiTagMask);
6028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(eq, kOperandIsASmi, at, Operand(zero_reg));
6029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
603044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
603144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
603244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertString(Register object) {
6034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
6035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
6036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SmiTst(object, t8);
6037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(ne, kOperandIsASmiAndNotAString, t8, Operand(zero_reg));
6038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GetObjectType(object, t8, t8);
6039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(lo, kOperandIsNotAString, t8, Operand(FIRST_NONSTRING_TYPE));
6040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertName(Register object) {
6045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
6046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
6047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SmiTst(object, t8);
6048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(ne, kOperandIsASmiAndNotAName, t8, Operand(zero_reg));
6049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GetObjectType(object, t8, t8);
6050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(le, kOperandIsNotAName, t8, Operand(LAST_NAME_TYPE));
6051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
6052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
6053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertFunction(Register object) {
6056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
6057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
6058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SmiTst(object, t8);
6059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(ne, kOperandIsASmiAndNotAFunction, t8, Operand(zero_reg));
6060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GetObjectType(object, t8, t8);
6061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(eq, kOperandIsNotAFunction, t8, Operand(JS_FUNCTION_TYPE));
6062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
6063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
6064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertBoundFunction(Register object) {
6067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
6068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
6069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SmiTst(object, t8);
6070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(ne, kOperandIsASmiAndNotABoundFunction, t8, Operand(zero_reg));
6071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GetObjectType(object, t8, t8);
6072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(eq, kOperandIsNotABoundFunction, t8, Operand(JS_BOUND_FUNCTION_TYPE));
6073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6076bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::AssertGeneratorObject(Register object) {
6077bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (emit_debug_code()) {
6078bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
6079bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    SmiTst(object, t8);
6080bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(ne, kOperandIsASmiAndNotAGeneratorObject, t8, Operand(zero_reg));
6081bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    GetObjectType(object, t8, t8);
6082bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(eq, kOperandIsNotAGeneratorObject, t8,
6083bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          Operand(JS_GENERATOR_OBJECT_TYPE));
6084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
6085bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
6086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6087109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::AssertReceiver(Register object) {
6088109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
6089109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
6090109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    SmiTst(object, t8);
6091109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(ne, kOperandIsASmiAndNotAReceiver, t8, Operand(zero_reg));
6092109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    GetObjectType(object, t8, t8);
6093109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(ge, kOperandIsNotAReceiver, t8, Operand(FIRST_JS_RECEIVER_TYPE));
6094109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
6095109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
6096109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
6097109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
6098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
6099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Register scratch) {
6100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
6101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done_checking;
6102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AssertNotSmi(object);
6103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
6104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Branch(&done_checking, eq, object, Operand(scratch));
6105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(t8, FieldMemOperand(object, HeapObject::kMapOffset));
6106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex);
6107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assert(eq, kExpectedUndefinedOrCell, t8, Operand(scratch));
6108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done_checking);
6109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
6114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
6115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!reg.is(at));
6116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadRoot(at, index);
6117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at));
6118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
611944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
612044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
612144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
612244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotHeapNumber(Register object,
612344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register heap_number_map,
612444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch,
612544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Label* on_not_heap_number) {
612644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
6127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
612844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map));
612944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
613044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
613144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNonSmisNotBothSequentialOneByteStrings(
6133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register first, Register second, Register scratch1, Register scratch2,
613444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* failure) {
6135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test that both first and second are sequential one-byte strings.
613644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Assume that they are non-smis.
613744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
613844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
613944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
614044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
614144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfBothInstanceTypesAreNotSequentialOneByte(scratch1, scratch2, scratch1,
6143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 scratch2, failure);
614444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
614544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
614644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register first,
6148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register second,
6149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch1,
6150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch2,
6151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Label* failure) {
615244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that neither is a smi.
615344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
615444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch1, first, Operand(second));
61553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(scratch1, failure);
6156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNonSmisNotBothSequentialOneByteStrings(first, second, scratch1,
6157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               scratch2, failure);
615844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
615944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
616044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
6162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register first, Register second, Register scratch1, Register scratch2,
616344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* failure) {
6164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
616544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
6166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
6167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
6168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kFlatOneByteStringTag <= 0xffff);  // Ensure this fits 16-bit immed.
6169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andi(scratch1, first, kFlatOneByteStringMask);
6170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(failure, ne, scratch1, Operand(kFlatOneByteStringTag));
6171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andi(scratch2, second, kFlatOneByteStringMask);
6172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(failure, ne, scratch2, Operand(kFlatOneByteStringTag));
617344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
617444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
617544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(Register type,
6177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                              Register scratch,
6178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                              Label* failure) {
6179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
618044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
6181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
6182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
6183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  And(scratch, type, Operand(kFlatOneByteStringMask));
6184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(failure, ne, scratch, Operand(kFlatOneByteStringTag));
618544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
618644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
618744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
618844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 4;
618944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
61903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
61913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              int num_double_arguments) {
61923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int stack_passed_words = 0;
61933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  num_reg_arguments += 2 * num_double_arguments;
61943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Up to four simple arguments are passed in registers a0..a3.
61963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (num_reg_arguments > kRegisterPassedArguments) {
61973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
61983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
61993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  stack_passed_words += kCArgSlotCount;
62003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return stack_passed_words;
62013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
62023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
6205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register index,
6206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register value,
6207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch,
6208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               uint32_t encoding_mask) {
6209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_object;
6210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTst(string, at);
6211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(ne, kNonObject, at, Operand(zero_reg));
6212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
6214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
6215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andi(at, at, kStringRepresentationMask | kStringEncodingMask);
6217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  li(scratch, Operand(encoding_mask));
6218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(eq, kUnexpectedStringType, at, Operand(scratch));
6219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The index is assumed to be untagged coming in, tag it to compare with the
6221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // string length without using a temp register, it is restored at the end of
6222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this function.
6223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label index_tag_ok, index_tag_bad;
6224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TrySmiTag(index, scratch, &index_tag_bad);
6225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(&index_tag_ok);
6226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&index_tag_bad);
6227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(kIndexIsTooLarge);
6228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&index_tag_ok);
6229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(at, FieldMemOperand(string, String::kLengthOffset));
6231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(lt, kIndexIsTooLarge, index, Operand(at));
6232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6233c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK(Smi::kZero == 0);
6234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(ge, kIndexIsNegative, index, Operand(zero_reg));
6235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiUntag(index, index);
6237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
62403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
62413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          int num_double_arguments,
62423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Register scratch) {
624344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int frame_alignment = ActivationFrameAlignment();
624444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
624544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Up to four simple arguments are passed in registers a0..a3.
624644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Those four arguments must have reserved argument slots on the stack for
624744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // mips, even though those argument slots are not normally used.
624844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Remaining arguments are pushed on the stack, above (higher address than)
624944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the argument slots.
62503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int stack_passed_arguments = CalculateStackPassedWords(
62513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      num_reg_arguments, num_double_arguments);
625244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (frame_alignment > kPointerSize) {
625344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Make stack end at alignment and make room for num_arguments - 4 words
625444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // and the original value of sp.
625544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(scratch, sp);
625644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
6257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
625844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    And(sp, sp, Operand(-frame_alignment));
625944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
626044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
626144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
626244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
626344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
626444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
626544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
62663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
62673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Register scratch) {
62683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCallCFunction(num_reg_arguments, 0, scratch);
62693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
62703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallCFunction(ExternalReference function,
62733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_reg_arguments,
62743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_double_arguments) {
62753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(function));
62763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunctionHelper(t8, num_reg_arguments, num_double_arguments);
62773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
62783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallCFunction(Register function,
62813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_reg_arguments,
62823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_double_arguments) {
62833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
62843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
62853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
628744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunction(ExternalReference function,
628844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   int num_arguments) {
62893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunction(function, num_arguments, 0);
629044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
629144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
629244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
629344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunction(Register function,
629444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   int num_arguments) {
62953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunction(function, num_arguments, 0);
629644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
629744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
629844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
629944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunctionHelper(Register function,
63003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         int num_reg_arguments,
63013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         int num_double_arguments) {
6302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(has_frame());
630344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make sure that the stack is aligned before calling a C function unless
630444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // running in the simulator. The simulator has its own alignment check which
630544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // provides more information.
630644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The argument stots are presumed to have been set up by
630744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // PrepareCallCFunction. The C function must be called via t9, for mips ABI.
630844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_HOST_ARCH_MIPS
631044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
6311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int frame_alignment = base::OS::ActivationFrameAlignment();
631244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int frame_alignment_mask = frame_alignment - 1;
631344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (frame_alignment > kPointerSize) {
6314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
631544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Label alignment_as_expected;
631644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      And(at, sp, Operand(frame_alignment_mask));
631744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
631844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Don't use Check here, as it will call Runtime_Abort possibly
631944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // re-entering here.
632044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      stop("Unexpected alignment in CallCFunction");
632144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bind(&alignment_as_expected);
63226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
63236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
632444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif  // V8_HOST_ARCH_MIPS
632544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
632644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Just call directly. The function called cannot cause a GC, or
632744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // allow preemption, so the return address in the link register
632844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // stays correct.
632944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
63303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!function.is(t9)) {
6331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    mov(t9, function);
633244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    function = t9;
633344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
633444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
633544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Call(function);
633644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
63373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int stack_passed_arguments = CalculateStackPassedWords(
63383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      num_reg_arguments, num_double_arguments);
633944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (base::OS::ActivationFrameAlignment() > kPointerSize) {
634144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
634244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
6343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Addu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
634444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
63456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
63466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
634744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
634844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef BRANCH_ARGS_CHECK
634944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
635044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
63513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
63523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
63533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
63543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
63553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
63563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met) {
63573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(scratch, object, Operand(~Page::kPageAlignmentMask));
63583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
63593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(scratch, scratch, Operand(mask));
63603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(condition_met, cc, scratch, Operand(zero_reg));
63613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
63623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
63653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch0,
63663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch1,
63673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black) {
6368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HasColor(object, scratch0, scratch1, on_black, 1, 1);  // kBlackBitPattern.
6369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
63703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
63713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::HasColor(Register object,
63743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register bitmap_scratch,
63753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register mask_scratch,
63763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label* has_color,
63773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int first_bit,
63783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int second_bit) {
6379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t8));
6380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t9));
63813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
63833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label other_color, word_boundary;
63853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
63863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, t9, Operand(mask_scratch));
63873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg));
63883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Shift left 1 by adding.
63893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(mask_scratch, mask_scratch, Operand(mask_scratch));
63903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&word_boundary, eq, mask_scratch, Operand(zero_reg));
63913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, t9, Operand(mask_scratch));
63923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg));
63933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&other_color);
63943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&word_boundary);
63963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize));
63973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t9, t9, Operand(1));
63983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(has_color, second_bit == 1 ? ne : eq, t9, Operand(zero_reg));
63993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&other_color);
64003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
64013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
64023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
64033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
64043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
64053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
6406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
64073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask));
64083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2);
64093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
64103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits);
6411109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Lsa(bitmap_reg, bitmap_reg, t8, kPointerSizeLog2, t8);
64123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(1));
64133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sllv(mask_reg, t8, mask_reg);
64143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
64153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
64163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
6418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Register mask_scratch, Register load_scratch,
6419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Label* value_is_white) {
6420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, t8));
64213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
64223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
64233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
6424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
6425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
6426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
6427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
64283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
64293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
64303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
64313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
64323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, mask_scratch, load_scratch);
6433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(value_is_white, eq, t8, Operand(zero_reg));
64343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
64353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
64363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
6438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
6439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
6440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
6444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(dst, FieldMemOperand(map, Map::kBitField3Offset));
6445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
6446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnumLength(Register dst, Register map) {
6450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
6451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(dst, FieldMemOperand(map, Map::kBitField3Offset));
6452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  And(dst, dst, Operand(Map::EnumLengthBits::kMask));
6453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(dst);
6454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadAccessor(Register dst, Register holder,
6458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int accessor_index,
6459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  AccessorComponent accessor) {
6460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(dst, FieldMemOperand(holder, HeapObject::kMapOffset));
6461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadInstanceDescriptors(dst, dst);
6462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(dst,
6463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch     FieldMemOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
6464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
6465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           : AccessorPair::kSetterOffset;
6466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(dst, FieldMemOperand(dst, offset));
6467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
6468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6470109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) {
6471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Register null_value = t1;
64723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register  empty_fixed_array_value = t2;
64733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
6474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label next, start;
6475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(a2, a0);
64763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the enum length field is properly initialized, indicating that
6478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // there is an enum cache.
6479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset));
64803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(a3, a1);
6482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(
6483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      call_runtime, eq, a3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel)));
64843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6485109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  LoadRoot(null_value, Heap::kNullValueRootIndex);
6486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&start);
6487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&next);
6489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset));
64903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
64913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For all objects but the receiver, check that the cache is empty.
6492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(a3, a1);
6493c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(call_runtime, ne, a3, Operand(Smi::kZero));
6494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&start);
6496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that there are no elements. Register a2 contains the current JS
6498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object we've reached through the prototype chain.
6499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_elements;
6500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(a2, FieldMemOperand(a2, JSObject::kElementsOffset));
6501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(&no_elements, eq, a2, Operand(empty_fixed_array_value));
6502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Second chance, the object may be using the empty slow element dictionary.
6504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex);
6505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(call_runtime, ne, a2, Operand(at));
65063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&no_elements);
6508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset));
6509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(&next, ne, a2, Operand(null_value));
65103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
65113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
65123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
65133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
6514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!output_reg.is(input_reg));
65153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
65163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(output_reg, Operand(255));
65173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Normal branch: nop in delay slot.
65183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done, gt, input_reg, Operand(output_reg));
65193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use delay slot in this branch.
65203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(USE_DELAY_SLOT, &done, lt, input_reg, Operand(zero_reg));
65213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(output_reg, zero_reg);  // In delay slot.
65223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(output_reg, input_reg);  // Value is in range 0..255.
65233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
65243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
65253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
65263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
65273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ClampDoubleToUint8(Register result_reg,
65283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        DoubleRegister input_reg,
65293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        DoubleRegister temp_double_reg) {
65303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label above_zero;
65313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
65323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label in_bounds;
65333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
65343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Move(temp_double_reg, 0.0);
65353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BranchF(&above_zero, NULL, gt, input_reg, temp_double_reg);
65363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
65373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Double value is less than zero, NaN or Inf, return 0.
65383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(result_reg, zero_reg);
65393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done);
65403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
65413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Double value is >= 255, return 255.
65423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&above_zero);
65433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Move(temp_double_reg, 255.0);
65443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BranchF(&in_bounds, NULL, le, input_reg, temp_double_reg);
65453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(result_reg, Operand(255));
65463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done);
65473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
65483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // In 0-255 range, round and truncate.
65493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&in_bounds);
6550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvt_w_d(temp_double_reg, input_reg);
65513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mfc1(result_reg, temp_double_reg);
65523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
65533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
65543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
65553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::TestJSArrayForAllocationMemento(Register receiver_reg,
65563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                                     Register scratch_reg,
65573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                                     Label* no_memento_found) {
65583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label map_check;
65593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label top_check;
6560bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ExternalReference new_space_allocation_top_adr =
6561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::new_space_allocation_top_address(isolate());
65623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
6563c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int kMementoLastWordOffset =
6564c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      kMementoMapOffset + AllocationMemento::kSize - kPointerSize;
65653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
65663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Bail out if the object is not in new space.
65673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
65683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If the object is in new space, we need to check whether it is on the same
65693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // page as the current top.
6570c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Addu(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
6571bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(at, Operand(new_space_allocation_top_adr));
6572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lw(at, MemOperand(at));
6573bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Xor(scratch_reg, scratch_reg, Operand(at));
65743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  And(scratch_reg, scratch_reg, Operand(~Page::kPageAlignmentMask));
65753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Branch(&top_check, eq, scratch_reg, Operand(zero_reg));
65763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // The object is on a different page than allocation top. Bail out if the
65773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // object sits on the page boundary as no memento can follow and we cannot
65783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // touch the memory following it.
6579c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Addu(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
65803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Xor(scratch_reg, scratch_reg, Operand(receiver_reg));
65813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  And(scratch_reg, scratch_reg, Operand(~Page::kPageAlignmentMask));
65823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Branch(no_memento_found, ne, scratch_reg, Operand(zero_reg));
65833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Continue with the actual map check.
65843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&map_check);
65853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If top is on the same page as the current object, we need to check whether
65863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // we are below top.
65873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&top_check);
6588c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Addu(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
6589bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(at, Operand(new_space_allocation_top_adr));
6590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(at, MemOperand(at));
6591c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(no_memento_found, ge, scratch_reg, Operand(at));
65923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Memento map check.
65933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&map_check);
65943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(scratch_reg, MemOperand(receiver_reg, kMementoMapOffset));
65953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Branch(no_memento_found, ne, scratch_reg,
65963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Operand(isolate()->factory()->allocation_memento_map()));
6597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister GetRegisterThatIsNotOneOf(Register reg1,
6601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg2,
6602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg3,
6603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg4,
6604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg5,
6605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg6) {
6606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
6607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
6608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
6609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
6610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
6611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
6612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
6613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
661413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
6615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
6616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int code = config->GetAllocatableGeneralCode(i);
6617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register candidate = Register::from_code(code);
6618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (regs & candidate.bit()) continue;
6619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return candidate;
6620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UNREACHABLE();
6622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return no_reg;
66233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
66243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
66253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfDictionaryInPrototypeChain(
6627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
6628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch0,
6629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1,
6630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* found) {
6631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(scratch0));
6632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
6633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register current = scratch0;
6634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label loop_again, end;
6635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Scratch contained elements pointer.
6637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(current, object);
6638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(current, FieldMemOperand(current, HeapObject::kMapOffset));
6639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(current, FieldMemOperand(current, Map::kPrototypeOffset));
6640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(&end, eq, current, Operand(factory->null_value()));
6641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loop based on the map going up the prototype chain.
6643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&loop_again);
6644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(current, FieldMemOperand(current, HeapObject::kMapOffset));
6645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lbu(scratch1, FieldMemOperand(current, Map::kInstanceTypeOffset));
6646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
6647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
6648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(found, lo, scratch1, Operand(JS_OBJECT_TYPE));
6649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lb(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
6650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::ElementsKindBits>(scratch1);
6651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(found, eq, scratch1, Operand(DICTIONARY_ELEMENTS));
6652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(current, FieldMemOperand(current, Map::kPrototypeOffset));
6653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(&loop_again, ne, current, Operand(factory->null_value()));
6654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&end);
6656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool AreAliased(Register reg1, Register reg2, Register reg3, Register reg4,
6660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register reg5, Register reg6, Register reg7, Register reg8,
6661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register reg9, Register reg10) {
6662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() + reg3.is_valid() +
6663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
6664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        reg7.is_valid() + reg8.is_valid() + reg9.is_valid() +
6665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        reg10.is_valid();
6666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
6668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
6669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
6670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
6671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
6672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
6673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
6674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg7.is_valid()) regs |= reg7.bit();
6675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg8.is_valid()) regs |= reg8.bit();
6676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (reg9.is_valid()) regs |= reg9.bit();
6677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (reg10.is_valid()) regs |= reg10.bit();
6678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_non_aliasing_regs = NumRegs(regs);
6679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return n_of_valid_regs != n_of_non_aliasing_regs;
6681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodePatcher::CodePatcher(Isolate* isolate, byte* address, int instructions,
6685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         FlushICache flush_cache)
668644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : address_(address),
668744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      size_(instructions * Assembler::kInstrSize),
6688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      masm_(isolate, address, size_ + Assembler::kGap, CodeObjectRequired::kNo),
6689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      flush_cache_(flush_cache) {
669044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
669144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
669244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // bytes of instructions without failing with buffer size constraints.
6693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
669444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
669544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
669644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
669744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockCodePatcher::~CodePatcher() {
669844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Indicate that code has changed.
6699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (flush_cache_ == FLUSH) {
6700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler::FlushICache(masm_.isolate(), address_, size_);
6701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
670244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
670344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the code was patched as expected.
6704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.pc_ == address_ + size_);
6705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
670644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
670744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
670844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid CodePatcher::Emit(Instr instr) {
6710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  masm()->emit(instr);
671144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
671244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
671344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
671444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid CodePatcher::Emit(Address addr) {
671544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  masm()->emit(reinterpret_cast<Instr>(addr));
671644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
671744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
671844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CodePatcher::ChangeBranchCondition(Instr current_instr,
6720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        uint32_t new_opcode) {
6721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  current_instr = (current_instr & ~kOpcodeMask) | new_opcode;
6722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  masm_.emit(current_instr);
6723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
672444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
672544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncatingDiv(Register result,
6727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register dividend,
6728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   int32_t divisor) {
6729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(result));
6730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(at));
6731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(at));
6732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::MagicNumbersForDivision<uint32_t> mag =
6733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
6734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  li(at, Operand(mag.multiplier));
6735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Mulh(result, dividend, Operand(at));
6736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
6737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 0 && neg) {
6738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Addu(result, result, Operand(dividend));
6739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0 && !neg && mag.multiplier > 0) {
6741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Subu(result, result, Operand(dividend));
6742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mag.shift > 0) sra(result, result, mag.shift);
6744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  srl(at, dividend, 31);
6745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Addu(result, result, Operand(at));
6746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
6750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
67513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_MIPS
6753