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
200162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Madd_s(FPURegister fd, FPURegister fr, FPURegister fs,
200262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            FPURegister ft, FPURegister scratch) {
200362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (IsMipsArchVariant(kMips32r2)) {
200462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    madd_s(fd, fr, fs, ft);
200562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
200662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(!fr.is(scratch) && !fs.is(scratch) && !ft.is(scratch));
200762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    mul_s(scratch, fs, ft);
200862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    add_s(fd, fr, scratch);
200962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
201062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
201162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
201262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
201362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            FPURegister ft, FPURegister scratch) {
201462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (IsMipsArchVariant(kMips32r2)) {
201562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    madd_d(fd, fr, fs, ft);
201662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
201762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(!fr.is(scratch) && !fs.is(scratch) && !ft.is(scratch));
201862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    mul_d(scratch, fs, ft);
201962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    add_d(fd, fr, scratch);
202062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
202162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
202262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
202362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Msub_s(FPURegister fd, FPURegister fr, FPURegister fs,
202462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            FPURegister ft, FPURegister scratch) {
202562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (IsMipsArchVariant(kMips32r2)) {
202662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    msub_s(fd, fr, fs, ft);
202762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
202862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(!fr.is(scratch) && !fs.is(scratch) && !ft.is(scratch));
202962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    mul_s(scratch, fs, ft);
203062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    sub_s(fd, scratch, fr);
203162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
203262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
203362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
203462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Msub_d(FPURegister fd, FPURegister fr, FPURegister fs,
203562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            FPURegister ft, FPURegister scratch) {
203662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (IsMipsArchVariant(kMips32r2)) {
203762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    msub_d(fd, fr, fs, ft);
203862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
203962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(!fr.is(scratch) && !fs.is(scratch) && !ft.is(scratch));
204062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    mul_d(scratch, fs, ft);
204162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    sub_d(fd, scratch, fr);
204262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
204362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchFCommon(SecondaryField sizeField, Label* target,
2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* nan, Condition cond, FPURegister cmp1,
2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   FPURegister cmp2, BranchDelaySlot bd) {
2048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
2049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
2050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (cond == al) {
2051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Branch(bd, target);
2052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return;
2053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
20543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6)) {
2056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      sizeField = sizeField == D ? L : W;
2057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(nan || target);
2059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check for unordered (NaN) cases.
2060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (nan) {
2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bool long_branch =
2062f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          nan->is_bound() ? !is_near(nan) : is_trampoline_emitted();
2063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!IsMipsArchVariant(kMips32r6)) {
2064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (long_branch) {
2065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Label skip;
2066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(UN, sizeField, cmp1, cmp2);
2067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1f(&skip);
2068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          nop();
2069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          BranchLong(nan, bd);
2070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bind(&skip);
2071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
2072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(UN, sizeField, cmp1, cmp2);
2073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1t(nan);
2074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (bd == PROTECT) {
2075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            nop();
2076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
2077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
2078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
2079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Use kDoubleCompareReg for comparison result. It has to be unavailable
2080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // to lithium register allocator.
2081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(!cmp1.is(kDoubleCompareReg) && !cmp2.is(kDoubleCompareReg));
2082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (long_branch) {
2083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Label skip;
2084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(UN, sizeField, kDoubleCompareReg, cmp1, cmp2);
2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1eqz(&skip, kDoubleCompareReg);
2086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          nop();
2087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          BranchLong(nan, bd);
2088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bind(&skip);
2089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
2090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(UN, sizeField, kDoubleCompareReg, cmp1, cmp2);
2091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1nez(nan, kDoubleCompareReg);
2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (bd == PROTECT) {
2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            nop();
2094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
2097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (target) {
2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bool long_branch =
2101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          target->is_bound() ? !is_near(target) : is_trampoline_emitted();
2102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (long_branch) {
2103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Label skip;
2104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Condition neg_cond = NegateFpuCondition(cond);
2105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchShortF(sizeField, &skip, neg_cond, cmp1, cmp2, bd);
2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchLong(target, bd);
2107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bind(&skip);
2108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
2109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchShortF(sizeField, target, cond, cmp1, cmp2, bd);
2110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
21123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
21143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShortF(SecondaryField sizeField, Label* target,
2116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Condition cc, FPURegister cmp1,
2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  FPURegister cmp2, BranchDelaySlot bd) {
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsMipsArchVariant(kMips32r6)) {
2119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (target) {
2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Here NaN cases were either handled by this function or are assumed to
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // have been handled by the caller.
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (cc) {
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case lt:
2125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(OLT, sizeField, cmp1, cmp2);
2126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1t(target);
2127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ult:
2129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(ULT, sizeField, cmp1, cmp2);
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1t(target);
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case gt:
2133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(ULE, sizeField, cmp1, cmp2);
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1f(target);
2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ugt:
2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(OLE, sizeField, cmp1, cmp2);
2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1f(target);
2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case ge:
2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(ULT, sizeField, cmp1, cmp2);
2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1f(target);
2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case uge:
2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(OLT, sizeField, cmp1, cmp2);
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1f(target);
2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case le:
2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(OLE, sizeField, cmp1, cmp2);
2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1t(target);
2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ule:
2153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(ULE, sizeField, cmp1, cmp2);
2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1t(target);
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case eq:
2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(EQ, sizeField, cmp1, cmp2);
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1t(target);
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case ueq:
2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(UEQ, sizeField, cmp1, cmp2);
2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1t(target);
2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ne:  // Unordered or not equal.
2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(EQ, sizeField, cmp1, cmp2);
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1f(target);
2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ogl:
2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          c(UEQ, sizeField, cmp1, cmp2);
2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1f(target);
2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        default:
2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CHECK(0);
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (target) {
2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Here NaN cases were either handled by this function or are assumed to
2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // have been handled by the caller.
2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Unsigned conditions are treated as their signed counterpart.
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Use kDoubleCompareReg for comparison result, it is
2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // valid in fp64 (FR = 1) mode which is implied for mips32r6.
2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!cmp1.is(kDoubleCompareReg) && !cmp2.is(kDoubleCompareReg));
2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (cc) {
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case lt:
2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(OLT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1nez(target, kDoubleCompareReg);
2189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ult:
2191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(ULT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1nez(target, kDoubleCompareReg);
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case gt:
2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(ULE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1eqz(target, kDoubleCompareReg);
2197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ugt:
2199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(OLE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1eqz(target, kDoubleCompareReg);
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case ge:
2203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(ULT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1eqz(target, kDoubleCompareReg);
2205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case uge:
2207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(OLT, sizeField, kDoubleCompareReg, cmp1, cmp2);
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1eqz(target, kDoubleCompareReg);
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case le:
2211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(OLE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc1nez(target, kDoubleCompareReg);
2213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
2214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ule:
2215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(ULE, sizeField, kDoubleCompareReg, cmp1, cmp2);
2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1nez(target, kDoubleCompareReg);
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case eq:
2219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(EQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1nez(target, kDoubleCompareReg);
2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case ueq:
2223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(UEQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1nez(target, kDoubleCompareReg);
2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case ne:
2227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(EQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1eqz(target, kDoubleCompareReg);
2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case ogl:
2231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cmp(UEQ, sizeField, kDoubleCompareReg, cmp1, cmp2);
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          bc1eqz(target, kDoubleCompareReg);
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        default:
2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CHECK(0);
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
22383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (bd == PROTECT) {
22403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nop();
22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::FmoveLow(FPURegister dst, Register src_low) {
2246109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (IsFp32Mode()) {
2247109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    mtc1(src_low, dst);
2248109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
2249109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsFp64Mode() || IsFpxxMode());
2250109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!src_low.is(at));
2252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mfhc1(at, dst);
2253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mtc1(src_low, dst);
2254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mthc1(at, dst);
2255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(FPURegister dst, float imm) {
2260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  li(at, Operand(bit_cast<int32_t>(imm)));
2261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  mtc1(at, dst);
2262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Move(FPURegister dst, double imm) {
2266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int64_t imm_bits = bit_cast<int64_t>(imm);
22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle special values first.
2268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (imm_bits == bit_cast<int64_t>(0.0) && has_double_zero_reg_set_) {
22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov_d(dst, kDoubleRegZero);
2270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (imm_bits == bit_cast<int64_t>(-0.0) && has_double_zero_reg_set_) {
2271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Neg_d(dst, kDoubleRegZero);
22723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
22733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t lo, hi;
22743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoubleAsTwoUInt32(imm, &lo, &hi);
22753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Move the low part of the double into the lower of the corresponding FPU
22763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // register of FPU register pair.
22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (lo != 0) {
22783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      li(at, Operand(lo));
22793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mtc1(at, dst);
22803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
22813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mtc1(zero_reg, dst);
22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Move the high part of the double into the higher of the corresponding FPU
22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // register of FPU register pair.
22853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (hi != 0) {
22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      li(at, Operand(hi));
2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Mthc1(at, dst);
22883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Mthc1(zero_reg, dst);
22903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (dst.is(kDoubleRegZero)) has_double_zero_reg_set_ = true;
22923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movz(Register rd, Register rs, Register rt) {
2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r6)) {
22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, ne, rt, Operand(zero_reg));
23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movz(rd, rs, rt);
23043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movn(Register rd, Register rs, Register rt) {
2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r6)) {
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, eq, rt, Operand(zero_reg));
23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
23143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movn(rd, rs, rt);
23163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) {
2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson)) {
23223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tests an FP condition code and then conditionally move rs to rd.
23233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We do not currently use any FPU cc bit other than bit 0.
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(cc == 0);
2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!(rs.is(t8) || rd.is(t8)));
23263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
23273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = t8;
23283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For testing purposes we need to fetch content of the FCSR register and
23293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // than test its cc (floating point condition code) bit (for cc = 0, it is
23303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 24. bit of the FCSR).
23313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cfc1(scratch, FCSR);
23323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For the MIPS I, II and III architectures, the contents of scratch is
23333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // UNPREDICTABLE for the instruction immediately following CFC1.
23343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nop();
23353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(scratch, scratch, 16);
23363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    andi(scratch, scratch, 0x0080);
23373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, eq, scratch, Operand(zero_reg));
23383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
23393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
23403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movt(rd, rs, cc);
23423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) {
2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson)) {
23483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tests an FP condition code and then conditionally move rs to rd.
23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We do not currently use any FPU cc bit other than bit 0.
2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(cc == 0);
2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!(rs.is(t8) || rd.is(t8)));
23523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
23533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = t8;
23543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For testing purposes we need to fetch content of the FCSR register and
23553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // than test its cc (floating point condition code) bit (for cc = 0, it is
23563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 24. bit of the FCSR).
23573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cfc1(scratch, FCSR);
23583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For the MIPS I, II and III architectures, the contents of scratch is
23593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // UNPREDICTABLE for the instruction immediately following CFC1.
23603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nop();
23613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(scratch, scratch, 16);
23623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    andi(scratch, scratch, 0x0080);
23633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, ne, scratch, Operand(zero_reg));
23643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
23653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
23663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movf(rd, rs, cc);
23683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Clz(Register rd, Register rs) {
2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsArchVariant(kLoongson)) {
2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!(rd.is(t8) || rd.is(t9)) && !(rs.is(t8) || rs.is(t9)));
23743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register mask = t8;
23753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = t9;
23763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label loop, end;
23773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(at, rs);
23783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, zero_reg);
23793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lui(mask, 0x8000);
23803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&loop);
23813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, at, mask);
23823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&end, ne, scratch, Operand(zero_reg));
23833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    addiu(rd, rd, 1);
23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&loop, ne, mask, Operand(zero_reg), USE_DELAY_SLOT);
23853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(mask, mask, 1);
23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&end);
23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    clz(rd, rs);
23893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register result,
23953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     DoubleRegister double_input,
2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register scratch,
2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     DoubleRegister double_scratch,
23983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register except_flag,
23993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     CheckForInexactConversion check_inexact) {
2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(scratch));
2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!double_input.is(double_scratch));
2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!except_flag.is(scratch));
2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clear the except flag (0 = no exception)
2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(except_flag, zero_reg);
2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test for values that can be exactly represented as a signed 32-bit integer.
2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvt_w_d(double_scratch, double_input);
2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mfc1(result, double_scratch);
2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvt_d_w(double_scratch, double_scratch);
2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BranchF(&done, NULL, eq, double_input, double_scratch);
24143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int32_t except_mask = kFCSRFlagMask;  // Assume interested in all exceptions.
24163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (check_inexact == kDontCheckForInexactConversion) {
2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Ignore inexact exceptions.
24193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    except_mask &= ~kFCSRInexactFlagMask;
24203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
24213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Save FCSR.
2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cfc1(scratch, FCSR);
24243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable FPU exceptions.
24253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctc1(zero_reg, FCSR);
24263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do operation based on rounding mode.
24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (rounding_mode) {
24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToNearest:
2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Round_w_d(double_scratch, double_input);
24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
24323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToZero:
2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Trunc_w_d(double_scratch, double_input);
24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToPlusInf:
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Ceil_w_d(double_scratch, double_input);
24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
24383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToMinusInf:
2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Floor_w_d(double_scratch, double_input);
24403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
24413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }  // End of switch-statement.
24423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Retrieve FCSR.
24443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cfc1(except_flag, FCSR);
24453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore FCSR.
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ctc1(scratch, FCSR);
2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Move the converted value into the result register.
2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mfc1(result, double_scratch);
24493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for fpu exceptions.
24513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(except_flag, except_flag, Operand(except_mask));
24523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
2454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TryInlineTruncateDoubleToI(Register result,
2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                DoubleRegister double_input,
2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Label* done) {
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister single_scratch = kLithiumScratchDouble.low();
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = at;
2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = t9;
24633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
24643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Clear cumulative exception flags and save the FCSR.
24653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cfc1(scratch2, FCSR);
24663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ctc1(zero_reg, FCSR);
24673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Try a conversion to a signed integer.
24683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  trunc_w_d(single_scratch, double_input);
24693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  mfc1(result, single_scratch);
24703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Retrieve and restore the FCSR.
24713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cfc1(scratch, FCSR);
24723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ctc1(scratch2, FCSR);
24733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check for overflow and NaNs.
24743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  And(scratch,
24753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      scratch,
24763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask);
24773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If we had no exceptions we are done.
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(done, eq, scratch, Operand(zero_reg));
2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateDoubleToI(Register result,
2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       DoubleRegister double_input) {
2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TryInlineTruncateDoubleToI(result, double_input, &done);
2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we fell through then inline version didn't succeed - call stub instead.
2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ra);
2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Subu(sp, sp, Operand(kDoubleSize));  // Put input on stack.
2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sdc1(double_input, MemOperand(sp, 0));
2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(), sp, result, 0, true, true);
2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Addu(sp, sp, Operand(kDoubleSize));
2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(ra);
2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
2500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateHeapNumberToI(Register result, Register object) {
2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister double_scratch = f12;
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(object));
2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ldc1(double_scratch,
2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag));
2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TryInlineTruncateDoubleToI(result, double_scratch, &done);
2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we fell through then inline version didn't succeed - call stub instead.
2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  push(ra);
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(),
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     object,
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     result,
2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     HeapNumber::kValueOffset - kHeapObjectTag,
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     true,
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     true);
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop(ra);
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateNumberToI(Register object,
2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register result,
2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register heap_number_map,
2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register scratch,
2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Label* not_number) {
2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(object));
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UntagAndJumpIfSmi(result, object, &done);
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number);
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TruncateHeapNumberToI(result, object);
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
25393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
25403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
25413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::GetLeastBitsFromSmi(Register dst,
2544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                         Register src,
2545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                         int num_least_bits) {
2546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Ext(dst, src, kSmiTagSize, num_least_bits);
2547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::GetLeastBitsFromInt32(Register dst,
2551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           Register src,
2552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           int num_least_bits) {
2553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  And(dst, src, Operand((1 << num_least_bits) - 1));
2554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
255744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Emulated condtional branches do not emit a nop in the branch delay slot.
255844f0eee88ff00398ff7f715fab053374d808c90dSteve Block//
255944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// BRANCH_ARGS_CHECK checks that conditional jump arguments are correct.
2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define BRANCH_ARGS_CHECK(cond, rs, rt) DCHECK(                                \
256144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) ||          \
256244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg))))
256344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
256444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Branch(int32_t offset, BranchDelaySlot bdslot) {
2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6) ? is_int26(offset) : is_int16(offset));
25673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BranchShort(offset, bdslot);
25683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
25693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Branch(int32_t offset, Condition cond, Register rs,
2572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            const Operand& rt, BranchDelaySlot bdslot) {
2573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_near = BranchShortCheck(offset, nullptr, cond, rs, rt, bdslot);
2574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(is_near);
2575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  USE(is_near);
25763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
25773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) {
25803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
2581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (is_near_branch(L)) {
25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(L, bdslot);
25833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchLong(L, bdslot);
25853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
25863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
2588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchLong(L, bdslot);
25893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(L, bdslot);
25913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
25923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
25933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
25943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Branch(Label* L, Condition cond, Register rs,
25973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                            const Operand& rt,
25983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                            BranchDelaySlot bdslot) {
25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
2600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!BranchShortCheck(0, L, cond, rs, rt, bdslot)) {
2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (cond != cc_always) {
2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label skip;
2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Condition neg_cond = NegateCondition(cond);
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        BranchShort(&skip, neg_cond, rs, rt);
2605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchLong(L, bdslot);
2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        bind(&skip);
2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchLong(L, bdslot);
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
26103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
26113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
26123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (cond != cc_always) {
2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label skip;
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Condition neg_cond = NegateCondition(cond);
2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        BranchShort(&skip, neg_cond, rs, rt);
2617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchLong(L, bdslot);
2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        bind(&skip);
2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        BranchLong(L, bdslot);
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
26223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
26233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(L, cond, rs, rt, bdslot);
26243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
26253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
26263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
26273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Branch(Label* L,
26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Condition cond,
26313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Register rs,
26323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Heap::RootListIndex index,
26333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            BranchDelaySlot bdslot) {
26343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(at, index);
26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(L, cond, rs, Operand(at), bdslot);
26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShortHelper(int16_t offset, Label* L,
2640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       BranchDelaySlot bdslot) {
2641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
2642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  offset = GetOffset(offset, L, OffsetSize::kOffset16);
264344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(offset);
264444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
264544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
264644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
264744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
26483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
26493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShortHelperR6(int32_t offset, Label* L) {
2652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
2653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  offset = GetOffset(offset, L, OffsetSize::kOffset26);
2654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bc(offset);
2655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
265644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShort(int32_t offset, BranchDelaySlot bdslot) {
2659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
2660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_int26(offset));
2661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchShortHelperR6(offset, nullptr);
266244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
2663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_int16(offset));
2664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchShortHelper(offset, nullptr, bdslot);
26653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
266744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
26683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) {
2670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
2671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchShortHelperR6(0, L);
2672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchShortHelper(0, L, bdslot);
2674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
26763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic inline bool IsZero(const Operand& rt) {
2679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (rt.is_reg()) {
2680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return rt.rm().is(zero_reg);
2681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return rt.immediate() == 0;
2683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
268444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
26853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochint32_t MacroAssembler::GetOffset(int32_t offset, Label* L, OffsetSize bits) {
2688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (L) {
2689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    offset = branch_offset_helper(L, bits) >> 2;
2690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_intn(offset, bits));
2692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return offset;
2694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
269544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRegister MacroAssembler::GetRtAsRegisterHelper(const Operand& rt,
2698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                               Register scratch) {
269944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register r2 = no_reg;
270044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (rt.is_reg()) {
270144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    r2 = rt.rm_;
2702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    r2 = scratch;
2704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    li(r2, rt);
2705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return r2;
2708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchShortHelperR6(int32_t offset, Label* L,
2712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         Condition cond, Register rs,
2713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         const Operand& rt) {
2714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
2715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = rs.is(at) ? t8 : at;
2716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  OffsetSize bits = OffsetSize::kOffset16;
2717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Be careful to always use shifted_branch_offset only just before the
2719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // branch instruction, as the location will be remember for patching the
2720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // target.
2721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
2722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
272344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    switch (cond) {
272444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case cc_always:
2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bits = OffsetSize::kOffset26;
2726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
2728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bc(offset);
272944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
273044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case eq:
2731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Pre R6 beq is used here to make the code patchable. Otherwise bc
2733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // should be used which has no condition field so is not patchable.
2734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(rs, scratch, offset);
2739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          nop();
2740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
2742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beqzc(rs, offset);
2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
2746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // We don't want any other register but scratch clobbered.
2747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beqc(rs, scratch, offset);
2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
275344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
275444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case ne:
2755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2756014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Pre R6 bne is used here to make the code patchable. Otherwise we
2757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // should not generate any instruction.
2758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(rs, scratch, offset);
2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          nop();
2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bnezc(rs, offset);
2769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
2770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // We don't want any other register but scratch clobbered.
2771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bnec(rs, scratch, offset);
2776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
277744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
2778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Signed comparison.
278044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater:
2781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs > rt
2782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;  // No code needs to be emitted.
2784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltzc(scratch, offset);
2790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgtzc(rs, offset);
279544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltc(scratch, rs, offset);
280244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
280344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
280444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater_equal:
2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs >= rt
2806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
2808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
2811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          blezc(scratch, offset);
2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgezc(rs, offset);
282244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgec(rs, scratch, offset);
282944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
283044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
283144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less:
2832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs < rt
2833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;  // No code needs to be emitted.
2835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgtzc(scratch, offset);
2841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltzc(rs, offset);
284644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltc(rs, scratch, offset);
285344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
285444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
285544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less_equal:
2856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs <= rt
2857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
2859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
2862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgezc(scratch, offset);
2868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          blezc(rs, offset);
287344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgec(scratch, rs, offset);
288044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
288144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
2882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
288344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Unsigned comparison.
288444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater:
2885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs > rt
2886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;  // No code needs to be emitted.
2888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
2890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bnezc(scratch, offset);
2894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
2896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bnezc(rs, offset);
289944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltuc(scratch, rs, offset);
290644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
290744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
290844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater_equal:
2909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs >= rt
2910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
2912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
2915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
2917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beqzc(scratch, offset);
2921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
2923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
292644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgeuc(rs, scratch, offset);
293344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
293444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
293544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless:
2936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs < rt
2937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;  // No code needs to be emitted.
2939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
2941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bnezc(scratch, offset);
2945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;  // No code needs to be emitted.
294744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltuc(rs, scratch, offset);
295444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
295544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
295644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless_equal:
2957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // rs <= rt
2958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (rs.code() == rt.rm_.reg_code) {
2959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
2960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
2963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (rs.is(zero_reg)) {
2964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset26;
2965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bc(offset);
2969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (IsZero(rt)) {
2970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset21;
2971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beqzc(rs, offset);
297444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
2975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bits = OffsetSize::kOffset16;
2976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!is_near(L, bits)) return false;
2977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
2978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(!rs.is(scratch));
2979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset = GetOffset(offset, L, bits);
2980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgeuc(scratch, rs, offset);
298144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
298244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
298344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      default:
298444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        UNREACHABLE();
298544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
2986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckTrampolinePoolQuick(1);
2988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
2989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchShortHelper(int16_t offset, Label* L, Condition cond,
2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register rs, const Operand& rt,
2994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       BranchDelaySlot bdslot) {
2995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
2996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!is_near(L, OffsetSize::kOffset16)) return false;
2997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = at;
2999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int32_t offset32;
3000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Be careful to always use shifted_branch_offset only just before the
3002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // branch instruction, as the location will be remember for patching the
3003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // target.
3004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
3005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
300644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    switch (cond) {
300744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case cc_always:
3008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        b(offset32);
301044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
301144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case eq:
3012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(rs, zero_reg, offset32);
3015958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else {
3016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // We don't want any other register but scratch clobbered.
3017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(rs, scratch, offset32);
3020958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
302144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
302244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case ne:
3023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(rs, zero_reg, offset32);
3026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else {
3027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // We don't want any other register but scratch clobbered.
3028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          scratch = GetRtAsRegisterHelper(rt, scratch);
3029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(rs, scratch, offset32);
3031958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
303244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
3033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Signed comparison.
303544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater:
3036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgtz(rs, offset32);
303944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(scratch, zero_reg, offset32);
304344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
304544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater_equal:
3046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bgez(rs, offset32);
304944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Slt(scratch, rs, rt);
3051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(scratch, zero_reg, offset32);
305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
305444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
305544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less:
3056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bltz(rs, offset32);
305944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Slt(scratch, rs, rt);
3061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(scratch, zero_reg, offset32);
306344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
306444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
306544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less_equal:
3066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          blez(rs, offset32);
306944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(scratch, zero_reg, offset32);
307344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
307444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
3075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
307644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Unsigned comparison.
307744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater:
3078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(rs, zero_reg, offset32);
308144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(scratch, zero_reg, offset32);
308544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
308644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
308744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater_equal:
3088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          b(offset32);
309144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Sltu(scratch, rs, rt);
3093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(scratch, zero_reg, offset32);
309544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
309644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
3097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case Uless:
3098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          return true;  // No code needs to be emitted.
310044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Sltu(scratch, rs, rt);
3102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          bne(scratch, zero_reg, offset32);
310444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
310544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
310644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless_equal:
3107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (IsZero(rt)) {
3108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(rs, zero_reg, offset32);
311044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
3111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          offset32 = GetOffset(offset, L, OffsetSize::kOffset16);
3113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          beq(scratch, zero_reg, offset32);
311444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
311544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
311644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      default:
311744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        UNREACHABLE();
311844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
31193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
312044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
312144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
312244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
3123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
3125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchShortCheck(int32_t offset, Label* L, Condition cond,
3129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      Register rs, const Operand& rt,
3130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      BranchDelaySlot bdslot) {
3131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BRANCH_ARGS_CHECK(cond, rs, rt);
3132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!L) {
3133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(is_int26(offset));
3135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchShortHelperR6(offset, nullptr, cond, rs, rt);
3136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
3137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(is_int16(offset));
3138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchShortHelper(offset, nullptr, cond, rs, rt, bdslot);
3139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(offset == 0);
3142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchShortHelperR6(0, L, cond, rs, rt);
3144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
3145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchShortHelper(0, L, cond, rs, rt, bdslot);
3146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return false;
3149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShort(int32_t offset, Condition cond, Register rs,
3153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 const Operand& rt, BranchDelaySlot bdslot) {
3154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BranchShortCheck(offset, nullptr, cond, rs, rt, bdslot);
3155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
3159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 const Operand& rt, BranchDelaySlot bdslot) {
3160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BranchShortCheck(0, L, cond, rs, rt, bdslot);
31613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
31623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
31633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLink(int32_t offset, BranchDelaySlot bdslot) {
31653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BranchAndLinkShort(offset, bdslot);
31663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
31673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLink(int32_t offset, Condition cond, Register rs,
3170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   const Operand& rt, BranchDelaySlot bdslot) {
3171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_near = BranchAndLinkShortCheck(offset, nullptr, cond, rs, rt, bdslot);
3172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(is_near);
3173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  USE(is_near);
31743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
31753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) {
31783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
3179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (is_near_branch(L)) {
31803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchAndLinkShort(L, bdslot);
31813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
3182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchAndLinkLong(L, bdslot);
31833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
31843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
31853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
3186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchAndLinkLong(L, bdslot);
31873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
31883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchAndLinkShort(L, bdslot);
31893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
31903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
31913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
31923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs,
31953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   const Operand& rt,
31963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   BranchDelaySlot bdslot) {
31973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
3198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!BranchAndLinkShortCheck(0, L, cond, rs, rt, bdslot)) {
31993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label skip;
32003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Condition neg_cond = NegateCondition(cond);
32013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(&skip, neg_cond, rs, rt);
3202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchAndLinkLong(L, bdslot);
32033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bind(&skip);
32043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
32053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
32063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
32073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label skip;
32083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Condition neg_cond = NegateCondition(cond);
32093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(&skip, neg_cond, rs, rt);
3210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchAndLinkLong(L, bdslot);
32113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bind(&skip);
32123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
3213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchAndLinkShortCheck(0, L, cond, rs, rt, bdslot);
32143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
32153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
32163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
32173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLinkShortHelper(int16_t offset, Label* L,
3220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                              BranchDelaySlot bdslot) {
3221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
3222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  offset = GetOffset(offset, L, OffsetSize::kOffset16);
322344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bal(offset);
322444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
322544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
322644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
322744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
322844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
322944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
323044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLinkShortHelperR6(int32_t offset, Label* L) {
3232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
3233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  offset = GetOffset(offset, L, OffsetSize::kOffset26);
3234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  balc(offset);
3235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
32363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLinkShort(int32_t offset,
3239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        BranchDelaySlot bdslot) {
3240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_int26(offset));
3242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchAndLinkShortHelperR6(offset, nullptr);
3243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_int16(offset));
3245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchAndLinkShortHelper(offset, nullptr, bdslot);
3246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
32483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
32493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) {
3251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchAndLinkShortHelperR6(0, L);
3253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchAndLinkShortHelper(0, L, bdslot);
32553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
325644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
325744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
325844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchAndLinkShortHelperR6(int32_t offset, Label* L,
3260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Condition cond, Register rs,
3261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                const Operand& rt) {
3262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
3263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = rs.is(at) ? t8 : at;
3264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  OffsetSize bits = OffsetSize::kOffset16;
326544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
3267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((cond == cc_always && is_int26(offset)) || is_int16(offset));
3268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (cond) {
3269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case cc_always:
3270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bits = OffsetSize::kOffset26;
3271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      balc(offset);
3274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case eq:
3276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Subu(scratch, rs, rt);
3278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      beqzalc(scratch, offset);
3280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case ne:
3282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Subu(scratch, rs, rt);
3284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bnezalc(scratch, offset);
3286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
32873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Signed comparison.
3289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case greater:
3290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs > rt
3291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (rs.code() == rt.rm_.reg_code) {
3292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;  // No code needs to be emitted.
3293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (rs.is(zero_reg)) {
3294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        scratch = GetRtAsRegisterHelper(rt, scratch);
3296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bltzalc(scratch, offset);
3298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (IsZero(rt)) {
3299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bgtzalc(rs, offset);
3302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
3303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bnezalc(scratch, offset);
3307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
3308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case greater_equal:
3310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs >= rt
3311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (rs.code() == rt.rm_.reg_code) {
3312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bits = OffsetSize::kOffset26;
3313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        balc(offset);
3316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (rs.is(zero_reg)) {
3317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        scratch = GetRtAsRegisterHelper(rt, scratch);
3319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        blezalc(scratch, offset);
3321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (IsZero(rt)) {
3322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bgezalc(rs, offset);
3325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
3326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Slt(scratch, rs, rt);
3328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        beqzalc(scratch, offset);
3330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
3331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case less:
3333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs < rt
3334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (rs.code() == rt.rm_.reg_code) {
3335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;  // No code needs to be emitted.
3336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (rs.is(zero_reg)) {
3337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        scratch = GetRtAsRegisterHelper(rt, scratch);
3339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bgtzalc(scratch, offset);
3341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (IsZero(rt)) {
3342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bltzalc(rs, offset);
3345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
3346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Slt(scratch, rs, rt);
3348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bnezalc(scratch, offset);
3350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
3351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case less_equal:
3353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs <= r2
3354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (rs.code() == rt.rm_.reg_code) {
3355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bits = OffsetSize::kOffset26;
3356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        balc(offset);
3359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (rs.is(zero_reg)) {
3360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        scratch = GetRtAsRegisterHelper(rt, scratch);
3362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bgezalc(scratch, offset);
3364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (IsZero(rt)) {
3365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        blezalc(rs, offset);
3368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
3369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!is_near(L, bits)) return false;
3370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        offset = GetOffset(offset, L, bits);
3372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        beqzalc(scratch, offset);
3373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
3374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
33753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
337644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Unsigned comparison.
3378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Ugreater:
3379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs > r2
3380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bnezalc(scratch, offset);
3384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Ugreater_equal:
3386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs >= r2
3387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, rs, rt);
3389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      beqzalc(scratch, offset);
3391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Uless:
3393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs < r2
3394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, rs, rt);
3396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bnezalc(scratch, offset);
3398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Uless_equal:
3400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // rs <= r2
3401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!is_near(L, bits)) return false;
3402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, bits);
3404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      beqzalc(scratch, offset);
3405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    default:
3407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UNREACHABLE();
34083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
3409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
3410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
34113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
34123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Pre r6 we need to use a bgezal or bltzal, but they can't be used directly
3414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// with the slt instructions. We could use sub or add instead but we would miss
3415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// overflow cases, so we keep slt and add an intermediate third instruction.
3416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchAndLinkShortHelper(int16_t offset, Label* L,
3417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                              Condition cond, Register rs,
3418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                              const Operand& rt,
3419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                              BranchDelaySlot bdslot) {
3420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L == nullptr || offset == 0);
3421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!is_near(L, OffsetSize::kOffset16)) return false;
3422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = t8;
3424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (cond) {
3427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case cc_always:
3428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bal(offset);
3430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case eq:
3432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bne(rs, GetRtAsRegisterHelper(rt, scratch), 2);
3433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      nop();
3434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bal(offset);
3436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case ne:
3438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      beq(rs, GetRtAsRegisterHelper(rt, scratch), 2);
3439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      nop();
3440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bal(offset);
3442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Signed comparison.
3445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case greater:
3446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bgezal(scratch, offset);
3450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case greater_equal:
3452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Slt(scratch, rs, rt);
3453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bltzal(scratch, offset);
3456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case less:
3458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Slt(scratch, rs, rt);
3459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bgezal(scratch, offset);
3462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case less_equal:
3464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bltzal(scratch, offset);
3468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Unsigned comparison.
3471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Ugreater:
3472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bgezal(scratch, offset);
3476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Ugreater_equal:
3478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, rs, rt);
3479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bltzal(scratch, offset);
3482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Uless:
3484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, rs, rt);
3485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bgezal(scratch, offset);
3488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
3489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case Uless_equal:
3490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs);
3491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addiu(scratch, scratch, -1);
3492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = GetOffset(offset, L, OffsetSize::kOffset16);
3493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bltzal(scratch, offset);
3494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
34953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    default:
3497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UNREACHABLE();
34983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
349944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
350044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
350144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
350244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
3503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
3505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool MacroAssembler::BranchAndLinkShortCheck(int32_t offset, Label* L,
3509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             Condition cond, Register rs,
3510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const Operand& rt,
3511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             BranchDelaySlot bdslot) {
3512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BRANCH_ARGS_CHECK(cond, rs, rt);
3513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!L) {
3515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(is_int26(offset));
3517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchAndLinkShortHelperR6(offset, nullptr, cond, rs, rt);
3518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
3519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(is_int16(offset));
3520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchAndLinkShortHelper(offset, nullptr, cond, rs, rt, bdslot);
3521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(offset == 0);
3524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
3525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchAndLinkShortHelperR6(0, L, cond, rs, rt);
3526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
3527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return BranchAndLinkShortHelper(0, L, cond, rs, rt, bdslot);
3528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return false;
353144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
353244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
353344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(Register target,
35353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
35363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
35373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
35383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
353944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
35403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bd == PROTECT) {
35413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (cond == cc_always) {
35423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jic(target, 0);
35433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
35443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      BRANCH_ARGS_CHECK(cond, rs, rt);
35453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Branch(2, NegateCondition(cond), rs, rt);
35463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jic(target, 0);
35473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
354844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
35493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (cond == cc_always) {
35503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jr(target);
35513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
35523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      BRANCH_ARGS_CHECK(cond, rs, rt);
35533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Branch(2, NegateCondition(cond), rs, rt);
35543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jr(target);
35553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
35563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Emit a nop in the branch delay slot if required.
35573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (bd == PROTECT) nop();
355844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
35593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
35603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
35613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
35623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(intptr_t target,
35633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
35643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
35653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
35663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
35673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
35683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label skip;
35693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cond != cc_always) {
35703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(USE_DELAY_SLOT, &skip, NegateCondition(cond), rs, rt);
35713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
35723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The first instruction of 'li' may be placed in the delay slot.
35733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is not an issue, t9 is expected to be clobbered anyway.
35743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  li(t9, Operand(target, rmode));
35753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Jump(t9, al, zero_reg, Operand(zero_reg), bd);
35763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&skip);
357744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
357844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
357944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(Address target,
35813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
35823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
35833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
35843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
35853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!RelocInfo::IsCodeTarget(rmode));
35873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd);
3588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
35913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(Handle<Code> code,
35923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
35933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
35943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
35953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
35963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
3597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(RelocInfo::IsCodeTarget(rmode));
3598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference embedding_raw_address;
35993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd);
3600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
36033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint MacroAssembler::CallSize(Register target,
36043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Condition cond,
36053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Register rs,
36063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             const Operand& rt,
36073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             BranchDelaySlot bd) {
36083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int size = 0;
36093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond == cc_always) {
36113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    size += 1;
36123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
36133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    size += 3;
361444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
36153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (bd == PROTECT && !IsMipsArchVariant(kMips32r6)) size += 1;
36173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return size * kInstrSize;
36193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
36203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
36213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
362244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Note: To call gcc-compiled C code on mips, you must call thru t9.
36233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Call(Register target,
36243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
36253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
36263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
36273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
3628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef DEBUG
3629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int size = IsPrevInstrCompactBranch() ? kInstrSize : 0;
3630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
3631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
363244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
36333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label start;
36343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&start);
36353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bd == PROTECT) {
36363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (cond == cc_always) {
36373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jialc(target, 0);
36383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
36393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      BRANCH_ARGS_CHECK(cond, rs, rt);
36403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Branch(2, NegateCondition(cond), rs, rt);
36413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jialc(target, 0);
36423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
36433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
36443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (cond == cc_always) {
36453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jalr(target);
36463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
36473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      BRANCH_ARGS_CHECK(cond, rs, rt);
36483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Branch(2, NegateCondition(cond), rs, rt);
36493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jalr(target);
36503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
36513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Emit a nop in the branch delay slot if required.
36523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (bd == PROTECT) nop();
36533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
36543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef DEBUG
3656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK_EQ(size + CallSize(target, cond, rs, rt, bd),
3657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           SizeOfCodeGeneratedSince(&start));
3658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
36593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
36603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
366144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
36623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint MacroAssembler::CallSize(Address target,
36633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             RelocInfo::Mode rmode,
36643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Condition cond,
36653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Register rs,
36663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             const Operand& rt,
36673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             BranchDelaySlot bd) {
36683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int size = CallSize(t9, cond, rs, rt, bd);
36693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return size + 2 * kInstrSize;
3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
36733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Call(Address target,
36743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
367544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Condition cond,
36763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
36773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
36783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
36793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
36803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label start;
36813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&start);
36823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int32_t target_int = reinterpret_cast<int32_t>(target);
36833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t9, Operand(target_int, rmode), CONSTANT_SIZE);
36843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Call(t9, cond, rs, rt, bd);
3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(CallSize(target, rmode, cond, rs, rt, bd),
36863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            SizeOfCodeGeneratedSince(&start));
36873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
36883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint MacroAssembler::CallSize(Handle<Code> code,
36913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             RelocInfo::Mode rmode,
3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             TypeFeedbackId ast_id,
36933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Condition cond,
36943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Register rs,
36953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             const Operand& rt,
36963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             BranchDelaySlot bd) {
3697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference using_raw_address;
36983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return CallSize(reinterpret_cast<Address>(code.location()),
36993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      rmode, cond, rs, rt, bd);
37003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
37013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Call(Handle<Code> code,
37043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
3705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          TypeFeedbackId ast_id,
37063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
37073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
37083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
37103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
37113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label start;
37123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&start);
3713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(RelocInfo::IsCodeTarget(rmode));
3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
37153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SetRecordedAstId(ast_id);
37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    rmode = RelocInfo::CODE_TARGET_WITH_ID;
371744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference embedding_raw_address;
37193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd);
3720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(CallSize(code, rmode, ast_id, cond, rs, rt, bd),
37213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            SizeOfCodeGeneratedSince(&start));
37223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
372344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
372444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
37253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Ret(Condition cond,
37263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         Register rs,
37273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         const Operand& rt,
37283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         BranchDelaySlot bd) {
37293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Jump(ra, cond, rs, rt, bd);
37303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
37313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchLong(Label* L, BranchDelaySlot bdslot) {
3734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT &&
3735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (!L->is_bound() || is_near_r6(L))) {
3736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchShortHelperR6(0, L);
3737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
3739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t imm32;
3740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    imm32 = jump_address(L);
37413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
37423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      uint32_t lui_offset, jic_offset;
37433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      UnpackTargetAddressUnsigned(imm32, lui_offset, jic_offset);
37443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      {
37453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BlockGrowBufferScope block_buf_growth(this);
37463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // Buffer growth (and relocation) must be blocked for internal
37473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // references until associated instructions are emitted and
37483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // available to be patched.
37493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
37503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        lui(at, lui_offset);
37513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        jic(at, jic_offset);
37523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
37533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      CheckBuffer();
37543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
37553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      {
37563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BlockGrowBufferScope block_buf_growth(this);
37573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // Buffer growth (and relocation) must be blocked for internal
37583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // references
37593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // until associated instructions are emitted and available to be
37603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // patched.
37613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
37623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        lui(at, (imm32 & kHiMask) >> kLuiShift);
37633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        ori(at, at, (imm32 & kImm16Mask));
37643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
37653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      CheckBuffer();
37663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jr(at);
37673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      // Emit a nop in the branch delay slot if required.
37683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (bdslot == PROTECT) nop();
3769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
37713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
37723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::BranchAndLinkLong(Label* L, BranchDelaySlot bdslot) {
3775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT &&
3776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (!L->is_bound() || is_near_r6(L))) {
3777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchAndLinkShortHelperR6(0, L);
3778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
3780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t imm32;
3781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    imm32 = jump_address(L);
37823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) {
37833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      uint32_t lui_offset, jic_offset;
37843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      UnpackTargetAddressUnsigned(imm32, lui_offset, jic_offset);
37853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      {
37863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BlockGrowBufferScope block_buf_growth(this);
37873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // Buffer growth (and relocation) must be blocked for internal
37883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // references until associated instructions are emitted and
37893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // available to be patched.
37903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
37913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        lui(at, lui_offset);
37923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        jialc(at, jic_offset);
37933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
37943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      CheckBuffer();
37953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
37963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      {
37973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        BlockGrowBufferScope block_buf_growth(this);
37983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // Buffer growth (and relocation) must be blocked for internal
37993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // references
38003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // until associated instructions are emitted and available to be
38013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // patched.
38023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
38033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        lui(at, (imm32 & kHiMask) >> kLuiShift);
38043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        ori(at, at, (imm32 & kImm16Mask));
38053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
38063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      CheckBuffer();
38073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      jalr(at);
38083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      // Emit a nop in the branch delay slot if required.
38093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (bdslot == PROTECT) nop();
3810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
381144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
38123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
38133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
38153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::DropAndRet(int drop) {
3816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(is_int16(drop * kPointerSize));
38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ret(USE_DELAY_SLOT);
38183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addiu(sp, sp, drop * kPointerSize);
38193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
38203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
382144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::DropAndRet(int drop,
382244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Condition cond,
382344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Register r1,
382444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                const Operand& r2) {
38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Both Drop and Ret need to be conditional.
382644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label skip;
382744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (cond != cc_always) {
382844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&skip, NegateCondition(cond), r1, r2);
382944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
383044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
383144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Drop(drop);
383244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Ret();
383344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
383444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (cond != cc_always) {
383544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&skip);
383644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
383744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
383844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
383944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Drop(int count,
38413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
38423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register reg,
38433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& op) {
38443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (count <= 0) {
38453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return;
38463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
38473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label skip;
38493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond != al) {
38513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch     Branch(&skip, NegateCondition(cond), reg, op);
38523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
38533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Addu(sp, sp, Operand(count * kPointerSize));
38553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond != al) {
38573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bind(&skip);
38583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
38593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
38603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
386344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Swap(Register reg1,
386444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register reg2,
386544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register scratch) {
386644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (scratch.is(no_reg)) {
386744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Xor(reg1, reg1, Operand(reg2));
386844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Xor(reg2, reg2, Operand(reg1));
386944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Xor(reg1, reg1, Operand(reg2));
387044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
387144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(scratch, reg1);
387244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(reg1, reg2);
387344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(reg2, scratch);
387444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
38753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
38763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
38773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
38783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Call(Label* target) {
387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BranchAndLink(target);
388044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
388144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
388244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Push(Handle<Object> handle) {
38843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  li(at, Operand(handle));
38853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  push(at);
38863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
38873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
388862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::MaybeDropFrames() {
388962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check whether we need to drop frames to restart a function on the stack.
389062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ExternalReference restart_fp =
389162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ExternalReference::debug_restart_fp_address(isolate());
389262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  li(a1, Operand(restart_fp));
389362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  lw(a1, MemOperand(a1));
389462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Jump(isolate()->builtins()->FrameDropperTrampoline(), RelocInfo::CODE_TARGET,
389562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       ne, a1, Operand(zero_reg));
389644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
389744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ---------------------------------------------------------------------------
3899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Exception handling.
39003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushStackHandler() {
39026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Adjust this code if not the case.
3903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
390469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
39053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
39073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t1, MemOperand(t2));
39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(t1);
3910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
39113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
39123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(sp, MemOperand(t2));
39133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
39143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
39153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PopStackHandler() {
391769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
391844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pop(a1);
391944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
3920589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(at, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
392144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(a1, MemOperand(at));
392244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
392344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
392444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int object_size,
3926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
3927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch1,
3928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch2,
3929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
3930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
3931f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(object_size <= kMaxRegularHeapObjectSize);
3932bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
393344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!FLAG_inline_new) {
3934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
393544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Trash the registers to simulate an allocation failure.
393644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(result, 0x7091);
393744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(scratch1, 0x7191);
393844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(scratch2, 0x7291);
393944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    jmp(gc_required);
394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return;
394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!AreAliased(result, scratch1, scratch2, t9, at));
394544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
394644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make object size into bytes.
394744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & SIZE_IN_WORDS) != 0) {
394844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    object_size *= kPointerSize;
394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, object_size & kObjectAlignmentMask);
395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
395244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check relative positions of allocation top and limit addresses.
395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // ARM adds additional checks to make sure the ldm instruction can be
395444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // used. On MIPS we don't have ldm so we don't need additional checks either.
3955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
3956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
3957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
3958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
3959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
3961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
3962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((limit - top) == kPointerSize);
396344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Set up allocation top address and allocation limit registers.
3965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register top_address = scratch1;
396644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // This code stores a temporary value in t9.
3967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register alloc_limit = t9;
3968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register result_end = scratch2;
3969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  li(top_address, Operand(allocation_top));
3970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
397144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & RESULT_CONTAINS_TOP) == 0) {
3972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Load allocation top into result and allocation limit into alloc_limit.
3973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(result, MemOperand(top_address));
3974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(alloc_limit, MemOperand(top_address, kPointerSize));
397544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
3976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
3977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Assert that result actually contains top on entry.
3978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      lw(alloc_limit, MemOperand(top_address));
3979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit));
398044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
3981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Load allocation limit. Result already contains allocation top.
3982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(alloc_limit, MemOperand(top_address, limit - top));
398344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
398444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
3986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Align the next allocation. Storing the filler map without checking top is
3987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // safe in new-space because the limit of the heap is aligned there.
3988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
3989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    And(result_end, result, Operand(kDoubleAlignmentMask));
3990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
3991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Branch(&aligned, eq, result_end, Operand(zero_reg));
3992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
3993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Branch(gc_required, Ugreater_equal, result, Operand(alloc_limit));
3994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    li(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
3996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sw(result_end, MemOperand(result));
3997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Addu(result, result, Operand(kDoubleSize / 2));
3998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
3999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
400144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate new top and bail out if new space is exhausted. Use result
400244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to calculate the new top.
4003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Addu(result_end, result, Operand(object_size));
4004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(gc_required, Ugreater, result_end, Operand(alloc_limit));
400544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4006bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
4007bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
4008bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sw(result_end, MemOperand(top_address));
400944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
4010bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4011bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag object.
4012bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(result, result, Operand(kHeapObjectTag));
40133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
40143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
40153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Allocate(Register object_size, Register result,
4017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              Register result_end, Register scratch,
4018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              Label* gc_required, AllocationFlags flags) {
4019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
402044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!FLAG_inline_new) {
4021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
402244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Trash the registers to simulate an allocation failure.
402344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(result, 0x7091);
4024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      li(scratch, 0x7191);
4025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      li(result_end, 0x7291);
402644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
402744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    jmp(gc_required);
402844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return;
402944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
40303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
4032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // is not specified. Other registers must not overlap.
4033109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!AreAliased(object_size, result, scratch, t9, at));
4034109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!AreAliased(result_end, result, scratch, t9, at));
4035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
403644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
403744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check relative positions of allocation top and limit addresses.
403844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // ARM adds additional checks to make sure the ldm instruction can be
403944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // used. On MIPS we don't have ldm so we don't need additional checks either.
4040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
4041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
4043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
4044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
4045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
4046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((limit - top) == kPointerSize);
404744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Set up allocation top address and allocation limit registers.
4049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register top_address = scratch;
405044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // This code stores a temporary value in t9.
4051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register alloc_limit = t9;
4052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  li(top_address, Operand(allocation_top));
4053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
405444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & RESULT_CONTAINS_TOP) == 0) {
4055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Load allocation top into result and allocation limit into alloc_limit.
4056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(result, MemOperand(top_address));
4057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(alloc_limit, MemOperand(top_address, kPointerSize));
405844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
4059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
4060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Assert that result actually contains top on entry.
4061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      lw(alloc_limit, MemOperand(top_address));
4062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit));
406344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
4064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Load allocation limit. Result already contains allocation top.
4065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(alloc_limit, MemOperand(top_address, limit - top));
406644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
40673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Align the next allocation. Storing the filler map without checking top is
4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // safe in new-space because the limit of the heap is aligned there.
4071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
4072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    And(result_end, result, Operand(kDoubleAlignmentMask));
4073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
4074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Branch(&aligned, eq, result_end, Operand(zero_reg));
4075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
4076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Branch(gc_required, Ugreater_equal, result, Operand(alloc_limit));
4077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    li(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
4079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sw(result_end, MemOperand(result));
4080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Addu(result, result, Operand(kDoubleSize / 2));
4081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
4082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
408444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate new top and bail out if new space is exhausted. Use result
408544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to calculate the new top. Object size may be in words so a shift is
408644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // required to get the number of bytes.
408744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & SIZE_IN_WORDS) != 0) {
4088109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Lsa(result_end, result, object_size, kPointerSizeLog2);
408944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
4090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Addu(result_end, result, Operand(object_size));
409144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
4092bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(gc_required, Ugreater, result_end, Operand(alloc_limit));
409444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
409544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Update allocation top. result temporarily holds the new top.
4096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
4097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    And(alloc_limit, result_end, Operand(kObjectAlignmentMask));
4098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(eq, kUnalignedAllocationInNewSpace, alloc_limit, Operand(zero_reg));
409944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
41006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4101bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
4102bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
4103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sw(result_end, MemOperand(top_address));
410444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
4105bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4106bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag object.
4107bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(result, result, Operand(kHeapObjectTag));
410844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
41096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4110bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(int object_size, Register result,
4111bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register scratch1, Register scratch2,
4112bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  AllocationFlags flags) {
4113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(object_size <= kMaxRegularHeapObjectSize);
4114bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!AreAliased(result, scratch1, scratch2, t9, at));
4115bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4116bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Make object size into bytes.
4117bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & SIZE_IN_WORDS) != 0) {
4118bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    object_size *= kPointerSize;
4119bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4120bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK_EQ(0, object_size & kObjectAlignmentMask);
4121bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4122bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ExternalReference allocation_top =
4123bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4124bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4125bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Set up allocation top address and allocation limit registers.
4126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register top_address = scratch1;
4127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // This code stores a temporary value in t9.
4128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register result_end = scratch2;
4129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(top_address, Operand(allocation_top));
4130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lw(result, MemOperand(top_address));
4131bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4132bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Align the next allocation. Storing the filler map without checking top is
4134bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // safe in new-space because the limit of the heap is aligned there.
4135bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
4136bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    And(result_end, result, Operand(kDoubleAlignmentMask));
4137bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
4138bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Branch(&aligned, eq, result_end, Operand(zero_reg));
4139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    li(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
4140bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sw(result_end, MemOperand(result));
4141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Addu(result, result, Operand(kDoubleSize / 2));
4142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
4143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4145bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(result_end, result, Operand(object_size));
4146bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4147bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // The top pointer is not updated for allocation folding dominators.
4148bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sw(result_end, MemOperand(top_address));
4149bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4150bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(result, result, Operand(kHeapObjectTag));
4151bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
4152bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4153bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(Register object_size, Register result,
4154bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, Register scratch,
4155bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  AllocationFlags flags) {
4156bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
4157bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // is not specified. Other registers must not overlap.
4158bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!AreAliased(object_size, result, scratch, t9, at));
4159bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!AreAliased(result_end, result, scratch, t9, at));
4160bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
4161bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4162bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ExternalReference allocation_top =
4163bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4164bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4165bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Set up allocation top address and allocation limit registers.
4166bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register top_address = scratch;
4167bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // This code stores a temporary value in t9.
4168bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(top_address, Operand(allocation_top));
4169bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lw(result, MemOperand(top_address));
4170bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4171bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4172bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Align the next allocation. Storing the filler map without checking top is
4173bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // safe in new-space because the limit of the heap is aligned there.
4174bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
4175bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    And(result_end, result, Operand(kDoubleAlignmentMask));
4176bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label aligned;
4177bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Branch(&aligned, eq, result_end, Operand(zero_reg));
4178bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    li(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
4179bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    sw(result_end, MemOperand(result));
4180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Addu(result, result, Operand(kDoubleSize / 2));
4181bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bind(&aligned);
4182bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4184bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Calculate new top and bail out if new space is exhausted. Use result
4185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // to calculate the new top. Object size may be in words so a shift is
4186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // required to get the number of bytes.
4187bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & SIZE_IN_WORDS) != 0) {
4188bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Lsa(result_end, result, object_size, kPointerSizeLog2);
4189bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
4190bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Addu(result_end, result, Operand(object_size));
4191bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4193bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // The top pointer is not updated for allocation folding dominators.
4194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sw(result_end, MemOperand(top_address));
4195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Addu(result, result, Operand(kHeapObjectTag));
4197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
419844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Register reg,
4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name) {
4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
4202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label succeed;
4203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  And(at, reg, Operand(kIsNotStringMask | kIsNotInternalizedMask));
4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(&succeed, eq, at, Operand(zero_reg));
4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(not_unique_name, ne, reg, Operand(SYMBOL_TYPE));
4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&succeed);
4208589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
4209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
421144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Allocates a heap number or jumps to the label if the young space is full and
421244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// a scavenge is needed.
421344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
421444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch1,
421544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch2,
421644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register heap_number_map,
4217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Label* need_gc,
4218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        MutableMode mode) {
421944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate an object in the heap for the heap number and tag it as a heap
422044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // object.
4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc,
4222bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
4223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap::RootListIndex map_index = mode == MUTABLE
4225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? Heap::kMutableHeapNumberMapRootIndex
4226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Heap::kHeapNumberMapRootIndex;
4227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertIsRoot(heap_number_map, map_index);
422844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
422944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Store heap number map in the allocated object.
4230bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
423144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
423244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
423344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
423444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateHeapNumberWithValue(Register result,
423544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 FPURegister value,
423644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Register scratch1,
423744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Register scratch2,
423844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Label* gc_required) {
42393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
42403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required);
424144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset));
424244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
424344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
424444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AllocateJSValue(Register result, Register constructor,
4246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register value, Register scratch1,
4247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register scratch2, Label* gc_required) {
4248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(constructor));
4249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch1));
4250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch2));
4251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(value));
425244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate JSValue in new space.
4254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
4255bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
42566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize the JSValue.
4258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
4259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sw(scratch1, FieldMemOperand(result, HeapObject::kMapOffset));
4260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
4261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sw(scratch1, FieldMemOperand(result, JSObject::kPropertiesOffset));
4262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sw(scratch1, FieldMemOperand(result, JSObject::kElementsOffset));
4263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sw(value, FieldMemOperand(result, JSValue::kValueOffset));
4264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
426544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
42666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register current_address,
4268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Register end_address,
42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&entry);
42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
4273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sw(filler, MemOperand(current_address));
4274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Addu(current_address, current_address, kPointerSize);
42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
4276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(&loop, ult, current_address, Operand(end_address));
42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CompareMapAndBranch(Register obj,
42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch,
42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Handle<Map> map,
42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Label* early_success,
42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Condition cond,
4284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label* branch_to) {
42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
4286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMapAndBranch(scratch, map, early_success, cond, branch_to);
4287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareMapAndBranch(Register obj_map,
4291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Handle<Map> map,
4292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label* early_success,
4293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Condition cond,
4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label* branch_to) {
4295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(branch_to, cond, obj_map, Operand(map));
42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
429944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CheckMap(Register obj,
430044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Register scratch,
430144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Handle<Map> map,
430244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Label* fail,
4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              SmiCheckType smi_check_type) {
4304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
430544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    JumpIfSmi(obj, fail);
430644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label success;
4308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMapAndBranch(obj, scratch, map, &success, ne, fail);
43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&success);
43106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
43116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
43126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
4314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Register scratch2, Handle<WeakCell> cell,
4315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Handle<Code> success,
4316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     SmiCheckType smi_check_type) {
4317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
4318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
4319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
4320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  lw(scratch1, FieldMemOperand(obj, HeapObject::kMapOffset));
4322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GetWeakValue(scratch2, cell);
4323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Jump(success, RelocInfo::CODE_TARGET, eq, scratch1, Operand(scratch2));
4324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
4325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
432844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CheckMap(Register obj,
432944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Register scratch,
433044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Heap::RootListIndex index,
433144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Label* fail,
4332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                              SmiCheckType smi_check_type) {
4333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
433444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    JumpIfSmi(obj, fail);
433544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
433644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
433744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadRoot(at, index);
433844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(fail, ne, scratch, Operand(at));
43396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
43406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
434113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid MacroAssembler::FPUCanonicalizeNaN(const DoubleRegister dst,
434213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                        const DoubleRegister src) {
434313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  sub_d(dst, src, kDoubleRegZero);
434413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
43456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
4347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  li(value, Operand(cell));
4348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  lw(value, FieldMemOperand(value, WeakCell::kValueOffset));
4349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
4350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
4353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                   Label* miss) {
4354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GetWeakValue(value, cell);
4355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JumpIfSmi(value, miss);
4356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
4357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MovFromFloatResult(DoubleRegister dst) {
4360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IsMipsSoftFloatABI) {
4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(dst, v0, v1);
4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(dst, v1, v0);
4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(dst, f0);  // Reg f0 is o32 ABI FP return value.
4368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MovFromFloatParameter(DoubleRegister dst) {
4373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsMipsSoftFloatABI) {
4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(dst, a0, a1);
4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(dst, a1, a0);
4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, f12);  // Reg f12 is o32 ABI FP first argument value.
4381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MovToFloatParameter(DoubleRegister src) {
4386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!IsMipsSoftFloatABI) {
4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(f12, src);
4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a0, a1, src);
4391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a1, a0, src);
4393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MovToFloatResult(DoubleRegister src) {
4399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!IsMipsSoftFloatABI) {
4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(f0, src);
4401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(v0, v1, src);
4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(v1, v0, src);
4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MovToFloatParameters(DoubleRegister src1,
4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          DoubleRegister src2) {
4413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsMipsSoftFloatABI) {
4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (src2.is(f12)) {
4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!src1.is(f14));
4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(f14, src2);
4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(f12, src1);
4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(f12, src1);
4420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(f14, src2);
4421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
4424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a0, a1, src1);
4425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a2, a3, src2);
4426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a1, a0, src1);
4428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(a3, a2, src2);
4429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
44346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// -----------------------------------------------------------------------------
4435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// JavaScript invokes.
44366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
44373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
44383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                        Register caller_args_count_reg,
44393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                        Register scratch0, Register scratch1) {
44403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
44413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
44423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
44433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                       scratch1));
44443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
44453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
44463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
44473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
44483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
44493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Calculate the end of destination area where we will put the arguments
44503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // after we drop current frame. We add kPointerSize to count the receiver
44513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // argument which is not included into formal parameters count.
44523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register dst_reg = scratch0;
44533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Lsa(dst_reg, fp, caller_args_count_reg, kPointerSizeLog2);
44543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Addu(dst_reg, dst_reg,
44553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize));
44563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
44573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register src_reg = caller_args_count_reg;
44583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Calculate the end of source area. +kPointerSize is for the receiver.
44593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
44603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Lsa(src_reg, sp, callee_args_count.reg(), kPointerSizeLog2);
44613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Addu(src_reg, src_reg, Operand(kPointerSize));
44623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
44633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Addu(src_reg, sp,
44643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Operand((callee_args_count.immediate() + 1) * kPointerSize));
44653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
44663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
44673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (FLAG_debug_code) {
44683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(lo, kStackAccessBelowStackPointer, src_reg, Operand(dst_reg));
44693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
44703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
44713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Restore caller's frame pointer and return address now as they will be
44723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // overwritten by the copying loop.
44733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
44743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
44753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
44763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Now copy callee arguments to the caller frame going backwards to avoid
44773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // callee arguments corruption (source and destination areas could overlap).
44783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
44793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Both src_reg and dst_reg are pointing to the word after the one to copy,
44803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // so they must be pre-decremented in the loop.
44813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register tmp_reg = scratch1;
44823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, entry;
44833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Branch(&entry);
44843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&loop);
44853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Subu(src_reg, src_reg, Operand(kPointerSize));
44863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Subu(dst_reg, dst_reg, Operand(kPointerSize));
44873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(tmp_reg, MemOperand(src_reg));
44883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(tmp_reg, MemOperand(dst_reg));
44893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&entry);
44903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Branch(&loop, ne, sp, Operand(src_reg));
44913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
44923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Leave current frame.
44933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  mov(sp, dst_reg);
44943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
44953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
44966ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
44976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    const ParameterCount& actual,
44986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    Label* done,
44993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
450044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    InvokeFlag flag,
4501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
45026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool definitely_matches = false;
45033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
45046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label regular_invoke;
45056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check whether the expected and actual arguments count match. If not,
45076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // setup registers according to contract with ArgumentsAdaptorTrampoline:
45086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  a0: actual arguments count
45096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  a1: function (passed through to callee)
45106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  a2: expected arguments count
45116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // The code below is made a lot easier because the calling code already sets
45136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // up actual and expected registers according to the contract if values are
45146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // passed in registers.
4515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(actual.is_immediate() || actual.reg().is(a0));
4516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expected.is_immediate() || expected.reg().is(a2));
45176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (expected.is_immediate()) {
4519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(actual.is_immediate());
4520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    li(a0, Operand(actual.immediate()));
45216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (expected.immediate() == actual.immediate()) {
45226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      definitely_matches = true;
45236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
45246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
45256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (expected.immediate() == sentinel) {
45266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // Don't worry about adapting arguments for builtins that
45276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // don't want that done. Skip adaption code by making it look
45286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // like we have a match between expected and actual number of
45296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // arguments.
45306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        definitely_matches = true;
45316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
45323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
45336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        li(a2, Operand(expected.immediate()));
45346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
45356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
4536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (actual.is_immediate()) {
4537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    li(a0, Operand(actual.immediate()));
4538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Branch(&regular_invoke, eq, expected.reg(), Operand(a0));
45396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
4540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Branch(&regular_invoke, eq, expected.reg(), Operand(actual.reg()));
45416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
45426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!definitely_matches) {
454444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> adaptor =
454544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->builtins()->ArgumentsAdaptorTrampoline();
45466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (flag == CALL_FUNCTION) {
45473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor));
45483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Call(adaptor);
4549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
45503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
45513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Branch(done);
45523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
45536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
455444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Jump(adaptor, RelocInfo::CODE_TARGET);
45556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
45566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&regular_invoke);
45576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
45586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
45596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
456062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::CheckDebugHook(Register fun, Register new_target,
456162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                    const ParameterCount& expected,
456262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                    const ParameterCount& actual) {
456362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label skip_hook;
456462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ExternalReference debug_hook_active =
456562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ExternalReference::debug_hook_on_function_call_address(isolate());
456662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  li(t0, Operand(debug_hook_active));
4567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lb(t0, MemOperand(t0));
456862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Branch(&skip_hook, eq, t0, Operand(zero_reg));
4569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
4570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(this,
4571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
4572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
4573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(expected.reg());
4574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(expected.reg());
4575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
4577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiTag(actual.reg());
4578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(actual.reg());
4579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
4581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(new_target);
4582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
4584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
458562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CallRuntime(Runtime::kDebugOnFunctionCall);
4586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(fun);
4587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
4588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(new_target);
4589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
4591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(actual.reg());
4592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(actual.reg());
4593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
4595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(expected.reg());
4596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiUntag(expected.reg());
4597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
459962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bind(&skip_hook);
4600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
4604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& expected,
4605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& actual,
4606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        InvokeFlag flag,
4607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const CallWrapper& call_wrapper) {
46083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
4609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
4610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(a1));
4611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_IMPLIES(new_target.is_valid(), new_target.is(a3));
46123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
461362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (call_wrapper.NeedsDebugHookCheck()) {
461462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CheckDebugHook(function, new_target, expected, actual);
4615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear the new.target register if not given.
4618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!new_target.is_valid()) {
4619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadRoot(a3, Heap::kUndefinedValueRootIndex);
4620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
46216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done;
46233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
4624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
4625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 call_wrapper);
46263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
4627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We call indirectly through the code field in the function to
4628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // allow recompilation to take effect without changing any of the
4629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // call sites.
4630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register code = t0;
4631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(code, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
46323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
46333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
46343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Call(code);
46353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
46363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(flag == JUMP_FUNCTION);
46383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jump(code);
46393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
46403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Continue here if InvokePrologue does handle the invocation due to
46413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // mismatched parameter counts.
46423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
46436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
46446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
46456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46476ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InvokeFunction(Register function,
4648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Register new_target,
46496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    const ParameterCount& actual,
465044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    InvokeFlag flag,
4651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
46523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
4653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
46543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Contract with called JS functions requires that function is passed in a1.
4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(function.is(a1));
46576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register expected_reg = a2;
4658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register temp_reg = t0;
46596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(temp_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
46616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
46626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(expected_reg,
4663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch     FieldMemOperand(temp_reg,
4664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     SharedFunctionInfo::kFormalParameterCountOffset));
466544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sra(expected_reg, expected_reg, kSmiTagSize);
46666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ParameterCount expected(expected_reg);
4668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(function, new_target, expected, actual, flag,
4669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     call_wrapper);
467044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
467144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
467244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Register function,
4674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
467544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    const ParameterCount& actual,
46763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                    InvokeFlag flag,
4677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
46783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
4679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
4680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Contract with called JS functions requires that function is passed in a1.
4682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(function.is(a1));
468344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
468444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the function and setup the context.
468544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
468644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(a1, no_reg, expected, actual, flag, call_wrapper);
4688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
4692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& expected,
4693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const ParameterCount& actual,
4694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    InvokeFlag flag,
4695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
4696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  li(a1, function);
4697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InvokeFunction(a1, expected, actual, flag, call_wrapper);
469844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
469944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
470044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
470144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::IsObjectJSStringType(Register object,
470244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Register scratch,
470344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Label* fail) {
4704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kNotStringTag != 0);
470544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
470644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
470744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
470844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch, scratch, Operand(kIsNotStringMask));
470944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(fail, ne, scratch, Operand(zero_reg));
47106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
47116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
47126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::IsObjectNameType(Register object,
4714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Register scratch,
4715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Label* fail) {
4716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
4717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
4718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(fail, hi, scratch, Operand(LAST_NAME_TYPE));
4719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
47226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// ---------------------------------------------------------------------------
47236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Support functions.
47246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
47256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetMapConstructor(Register result, Register map,
4727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register temp, Register temp2) {
4728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done, loop;
4729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
4730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&loop);
4731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(result, &done);
4732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GetObjectType(result, temp, temp2);
4733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(&done, ne, temp2, Operand(MAP_TYPE));
4734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
4735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(&loop);
4736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
4737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
47386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
473944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::GetObjectType(Register object,
474044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register map,
474144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register type_reg) {
474244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(map, FieldMemOperand(object, HeapObject::kMapOffset));
474344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
474444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
47456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
47466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
47476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// -----------------------------------------------------------------------------
4748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Runtime calls.
47496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
47503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub,
4751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              TypeFeedbackId ast_id,
47523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Condition cond,
47533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register r1,
47543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              const Operand& r2,
47553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              BranchDelaySlot bd) {
4756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(stub));  // Stub calls are not allowed in some stubs.
4757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id,
4758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       cond, r1, r2, bd);
47593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
47603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
47613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TailCallStub(CodeStub* stub,
4763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Condition cond,
4764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Register r1,
4765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  const Operand& r2,
4766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  BranchDelaySlot bd) {
4767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2, bd);
47683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
47693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
47703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return has_frame_ || !stub->SometimesSetsUpAFrame();
47736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
47746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
477544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::ObjectToDoubleFPURegister(Register object,
477644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               FPURegister result,
477744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register scratch1,
477844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register scratch2,
477944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register heap_number_map,
478044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Label* not_number,
478144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               ObjectToDoubleFlags flags) {
478244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done;
478344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & OBJECT_NOT_SMI) == 0) {
478444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label not_smi;
478544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    JumpIfNotSmi(object, &not_smi);
478644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Remove smi tag and convert to double.
478744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sra(scratch1, object, kSmiTagSize);
478844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mtc1(scratch1, result);
478944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cvt_d_w(result, result);
479044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&done);
479144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&not_smi);
479244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
479344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check for heap number and load double value from it.
479444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
479544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(not_number, ne, scratch1, Operand(heap_number_map));
479644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
479744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & AVOID_NANS_AND_INFINITIES) != 0) {
479844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // If exponent is all ones the number is either a NaN or +/-Infinity.
479944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register exponent = scratch1;
480044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register mask_reg = scratch2;
480144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(exponent, FieldMemOperand(object, HeapNumber::kExponentOffset));
480244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(mask_reg, HeapNumber::kExponentMask);
480344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
480444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    And(exponent, exponent, mask_reg);
480544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(not_number, eq, exponent, Operand(mask_reg));
480644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
480744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ldc1(result, FieldMemOperand(object, HeapNumber::kValueOffset));
480844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
480944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
481044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
481144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
481244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::SmiToDoubleFPURegister(Register smi,
481344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            FPURegister value,
481444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Register scratch1) {
481544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sra(scratch1, smi, kSmiTagSize);
481644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mtc1(scratch1, value);
481744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cvt_d_w(value, value);
481844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
481944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
482044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic inline void BranchOvfHelper(MacroAssembler* masm, Register overflow_dst,
4822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* overflow_label,
4823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* no_overflow_label) {
4824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(overflow_label || no_overflow_label);
4825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!overflow_label) {
4826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(no_overflow_label);
4827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    masm->Branch(no_overflow_label, ge, overflow_dst, Operand(zero_reg));
4828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
4829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    masm->Branch(overflow_label, lt, overflow_dst, Operand(zero_reg));
4830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (no_overflow_label) masm->Branch(no_overflow_label);
4831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AddBranchOvf(Register dst, Register left,
4836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  const Operand& right, Label* overflow_label,
4837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* no_overflow_label, Register scratch) {
4838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (right.is_reg()) {
4839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    AddBranchOvf(dst, left, right.rm(), overflow_label, no_overflow_label,
4840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 scratch);
4841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
4842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsMipsArchVariant(kMips32r6)) {
4843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register right_reg = t9;
4844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!left.is(right_reg));
4845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      li(right_reg, Operand(right));
4846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      AddBranchOvf(dst, left, right_reg, overflow_label, no_overflow_label);
4847958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
4848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register overflow_dst = t9;
4849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!dst.is(scratch));
4850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!dst.is(overflow_dst));
4851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!scratch.is(overflow_dst));
4852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!left.is(overflow_dst));
4853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (dst.is(left)) {
4854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        mov(scratch, left);                  // Preserve left.
4855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Addu(dst, left, right.immediate());  // Left is overwritten.
4856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        xor_(scratch, dst, scratch);         // Original left.
4857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Load right since xori takes uint16 as immediate.
4858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Addu(overflow_dst, zero_reg, right);
4859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        xor_(overflow_dst, dst, overflow_dst);
4860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        and_(overflow_dst, overflow_dst, scratch);
4861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
4862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Addu(dst, left, right.immediate());
4863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        xor_(overflow_dst, dst, left);
4864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Load right since xori takes uint16 as immediate.
4865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Addu(scratch, zero_reg, right);
4866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        xor_(scratch, dst, scratch);
4867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        and_(overflow_dst, scratch, overflow_dst);
4868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
4869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
4870958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
4871958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
4872958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
4873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AddBranchOvf(Register dst, Register left, Register right,
4876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* overflow_label,
4877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* no_overflow_label, Register scratch) {
4878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
4879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!overflow_label) {
4880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(no_overflow_label);
4881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!dst.is(scratch));
4882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register left_reg = left.is(dst) ? scratch : left;
4883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register right_reg = right.is(dst) ? t9 : right;
4884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!dst.is(left_reg));
4885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!dst.is(right_reg));
4886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(left_reg, left);
4887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(right_reg, right);
4888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(dst, left, right);
4889f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Bnvc(left_reg, right_reg, no_overflow_label);
4890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
4891f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Bovc(left, right, overflow_label);
4892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(dst, left, right);
4893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (no_overflow_label) bc(no_overflow_label);
4894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register overflow_dst = t9;
4897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!dst.is(scratch));
4898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!dst.is(overflow_dst));
4899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!scratch.is(overflow_dst));
4900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!left.is(overflow_dst));
4901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!right.is(overflow_dst));
4902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!left.is(scratch));
4903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!right.is(scratch));
4904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (left.is(right) && dst.is(left)) {
4906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(overflow_dst, right);
4907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      right = overflow_dst;
4908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (dst.is(left)) {
4911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(scratch, left);           // Preserve left.
4912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(dst, left, right);       // Left is overwritten.
4913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(scratch, dst, scratch);  // Original left.
4914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(overflow_dst, dst, right);
4915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      and_(overflow_dst, overflow_dst, scratch);
4916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (dst.is(right)) {
4917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      mov(scratch, right);          // Preserve right.
4918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(dst, left, right);       // Right is overwritten.
4919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(scratch, dst, scratch);  // Original right.
4920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(overflow_dst, dst, left);
4921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      and_(overflow_dst, overflow_dst, scratch);
4922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
4923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(dst, left, right);
4924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(overflow_dst, dst, left);
4925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(scratch, dst, right);
4926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      and_(overflow_dst, scratch, overflow_dst);
4927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
4929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::SubBranchOvf(Register dst, Register left,
4934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  const Operand& right, Label* overflow_label,
4935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* no_overflow_label, Register scratch) {
4936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(overflow_label || no_overflow_label);
4937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (right.is_reg()) {
4938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SubBranchOvf(dst, left, right.rm(), overflow_label, no_overflow_label,
4939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 scratch);
4940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
4941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register overflow_dst = t9;
4942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!dst.is(scratch));
4943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!dst.is(overflow_dst));
4944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!scratch.is(overflow_dst));
4945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!left.is(overflow_dst));
4946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!left.is(scratch));
4947958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (dst.is(left)) {
4948958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mov(scratch, left);                      // Preserve left.
4949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Subu(dst, left, right.immediate());      // Left is overwritten.
4950958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Load right since xori takes uint16 as immediate.
4951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Addu(overflow_dst, zero_reg, right);
4952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(overflow_dst, scratch, overflow_dst);  // scratch is original left.
4953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(scratch, dst, scratch);                // scratch is original left.
4954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      and_(overflow_dst, scratch, overflow_dst);
4955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
4956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Subu(dst, left, right);
4957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      xor_(overflow_dst, dst, left);
4958958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Load right since xori takes uint16 as immediate.
4959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Addu(scratch, zero_reg, right);
4960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      xor_(scratch, left, scratch);
4961958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      and_(overflow_dst, scratch, overflow_dst);
4962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
4963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
4964958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
4965958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
4966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4967958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::SubBranchOvf(Register dst, Register left, Register right,
4969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* overflow_label,
4970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Label* no_overflow_label, Register scratch) {
4971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(overflow_label || no_overflow_label);
4972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register overflow_dst = t9;
4973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(scratch));
4974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!dst.is(overflow_dst));
4975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!scratch.is(overflow_dst));
4976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!overflow_dst.is(left));
4977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!overflow_dst.is(right));
4978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch.is(left));
4979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch.is(right));
4980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
49813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This happens with some crankshaft code. Since Subu works fine if
49823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // left == right, let's not make that restriction here.
49833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (left.is(right)) {
49843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(dst, zero_reg);
4985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (no_overflow_label) {
4986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Branch(no_overflow_label);
4987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
49883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
49893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(left)) {
49913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(scratch, left);  // Preserve left.
49923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subu(dst, left, right);  // Left is overwritten.
49933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(overflow_dst, dst, scratch);  // scratch is original left.
49943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(scratch, scratch, right);  // scratch is original left.
49953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(overflow_dst, scratch, overflow_dst);
4996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(right)) {
49973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(scratch, right);  // Preserve right.
49983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subu(dst, left, right);  // Right is overwritten.
49993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(overflow_dst, dst, left);
50003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(scratch, left, scratch);  // Original right.
50013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(overflow_dst, scratch, overflow_dst);
5002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
5003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subu(dst, left, right);
5004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(overflow_dst, dst, left);
5005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(scratch, left, right);
5006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    and_(overflow_dst, scratch, overflow_dst);
5007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
5008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BranchOvfHelper(this, overflow_dst, overflow_label, no_overflow_label);
5009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
5010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5011f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochstatic inline void BranchOvfHelperMult(MacroAssembler* masm,
5012f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register overflow_dst,
5013f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Label* overflow_label,
5014f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Label* no_overflow_label) {
5015f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(overflow_label || no_overflow_label);
5016f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!overflow_label) {
5017f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(no_overflow_label);
5018f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    masm->Branch(no_overflow_label, eq, overflow_dst, Operand(zero_reg));
5019f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
5020f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    masm->Branch(overflow_label, ne, overflow_dst, Operand(zero_reg));
5021f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (no_overflow_label) masm->Branch(no_overflow_label);
5022f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
5023f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
5024f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5025f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::MulBranchOvf(Register dst, Register left,
5026f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  const Operand& right, Label* overflow_label,
5027f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  Label* no_overflow_label, Register scratch) {
5028f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(overflow_label || no_overflow_label);
5029f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (right.is_reg()) {
5030f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    MulBranchOvf(dst, left, right.rm(), overflow_label, no_overflow_label,
5031f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 scratch);
5032f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
5033f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Register overflow_dst = t9;
5034f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!dst.is(scratch));
5035f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!dst.is(overflow_dst));
5036f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!scratch.is(overflow_dst));
5037f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!left.is(overflow_dst));
5038f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!left.is(scratch));
5039f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5040f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Mul(overflow_dst, dst, left, right.immediate());
5041f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sra(scratch, dst, 31);
5042f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    xor_(overflow_dst, overflow_dst, scratch);
5043f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5044f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    BranchOvfHelperMult(this, overflow_dst, overflow_label, no_overflow_label);
5045f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
5046f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
5047f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5048f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::MulBranchOvf(Register dst, Register left, Register right,
5049f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  Label* overflow_label,
5050f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  Label* no_overflow_label, Register scratch) {
5051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(overflow_label || no_overflow_label);
5052f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Register overflow_dst = t9;
5053f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!dst.is(scratch));
5054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!dst.is(overflow_dst));
5055f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!scratch.is(overflow_dst));
5056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!overflow_dst.is(left));
5057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!overflow_dst.is(right));
5058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!scratch.is(left));
5059f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!scratch.is(right));
5060f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5061f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (IsMipsArchVariant(kMips32r6) && dst.is(right)) {
5062f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    mov(scratch, right);
5063f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Mul(overflow_dst, dst, left, scratch);
5064f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sra(scratch, dst, 31);
5065f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    xor_(overflow_dst, overflow_dst, scratch);
5066f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
5067f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Mul(overflow_dst, dst, left, right);
5068f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sra(scratch, dst, 31);
5069f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    xor_(overflow_dst, overflow_dst, scratch);
5070f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
5071f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5072f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BranchOvfHelperMult(this, overflow_dst, overflow_label, no_overflow_label);
5073f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
5074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
5076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 SaveFPRegsMode save_doubles,
5077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 BranchDelaySlot bd) {
50786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // All parameters are on the stack. v0 has the return value after call.
50796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
50806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If the expected number of arguments of the runtime function is
50816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // constant, we check that the actual number of arguments match the
50826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // expectation.
5083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->nargs < 0 || f->nargs == num_arguments);
50846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
50856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(1236192): Most runtime routines don't need the number of
50866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // arguments passed in because it is constant. At some point we
50876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // should remove this need and make the runtime routine entry code
50886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // smarter.
50893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryArgs(num_arguments);
50903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(ExternalReference(f, isolate()));
5091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1, save_doubles);
5092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallStub(&stub, TypeFeedbackId::None(), al, zero_reg, Operand(zero_reg), bd);
509344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
509444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
509544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
509644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
50973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           int num_arguments,
50983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           BranchDelaySlot bd) {
50993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryArgs(num_arguments);
51003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(ext);
510144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1);
5103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub, TypeFeedbackId::None(), al, zero_reg, Operand(zero_reg), bd);
510444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
510544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
510644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
5108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const Runtime::Function* function = Runtime::FunctionForId(fid);
5109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, function->result_size);
5110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (function->nargs >= 0) {
5111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PrepareCEntryArgs(function->nargs);
5112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
5113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpToExternalReference(ExternalReference(fid, isolate()));
51143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
51153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
5117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             BranchDelaySlot bd,
5118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             bool builtin_exit_frame) {
51193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(builtin);
5120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CEntryStub stub(isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
5121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                  builtin_exit_frame);
51223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Jump(stub.GetCode(),
51233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       RelocInfo::CODE_TARGET,
51243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       al,
51253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       zero_reg,
51263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Operand(zero_reg),
51273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       bd);
51283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
51293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::SetCounter(StatsCounter* counter, int value,
51313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                Register scratch1, Register scratch2) {
513244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
513344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch1, Operand(value));
513444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch2, Operand(ExternalReference(counter)));
513544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch1, MemOperand(scratch2));
513644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
51373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
51383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
51413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Register scratch1, Register scratch2) {
5142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
514344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
514444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch2, Operand(ExternalReference(counter)));
514544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(scratch1, MemOperand(scratch2));
514644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(scratch1, scratch1, Operand(value));
514744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch1, MemOperand(scratch2));
514844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
51493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
51503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
51533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Register scratch1, Register scratch2) {
5154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
515544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
515644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch2, Operand(ExternalReference(counter)));
515744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(scratch1, MemOperand(scratch2));
515844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(scratch1, scratch1, Operand(value));
515944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch1, MemOperand(scratch2));
516044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
51613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
51623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// -----------------------------------------------------------------------------
5165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Debugging.
51663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Assert(Condition cc, BailoutReason reason,
51683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                            Register rs, Operand rt) {
5169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code())
5170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(cc, reason, rs, rt);
517144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
517244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
517344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
517444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AssertFastElements(Register elements) {
5175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
5176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!elements.is(at));
517744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label ok;
5178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    push(elements);
517944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
518044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadRoot(at, Heap::kFixedArrayMapRootIndex);
518144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&ok, eq, elements, Operand(at));
51823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex);
51833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Branch(&ok, eq, elements, Operand(at));
518444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);
518544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&ok, eq, elements, Operand(at));
5186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kJSObjectWithFastElementsMapHasSlowElements);
518744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&ok);
5188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    pop(elements);
518944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
51903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
51913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
51923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Check(Condition cc, BailoutReason reason,
51943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                           Register rs, Operand rt) {
519544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label L;
519644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&L, cc, rs, rt);
5197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(reason);
5198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Will not return here.
519944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&L);
52003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
52013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
52023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Abort(BailoutReason reason) {
520444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label abort_start;
520544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&abort_start);
520644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
5207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* msg = GetBailoutReason(reason);
520844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (msg != NULL) {
520944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RecordComment("Abort message: ");
521044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RecordComment(msg);
521144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trap_on_abort) {
5214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stop(msg);
5215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
5216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
521744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
521844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if Abort() has already been initialized.
5220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(isolate()->builtins()->Abort()->IsHeapObject());
5221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Move(a0, Smi::FromInt(static_cast<int>(reason)));
5223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
52243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable stub call restrictions to always allow calls to abort.
52253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
52263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
52273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
52283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
5229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
52303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
52323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Will not return here.
523444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_trampoline_pool_blocked()) {
523544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // If the calling code cares about the exact number of
523644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // instructions generated, we insert padding here to keep the size
523744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // of the Abort macro constant.
523844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Currently in debug mode with debug_code enabled the number of
5239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // generated instructions is 10, so we use this as a maximum value.
5240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const int kExpectedAbortInstructions = 10;
524144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int abort_instructions = InstructionsGeneratedSince(&abort_start);
5242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(abort_instructions <= kExpectedAbortInstructions);
524344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    while (abort_instructions++ < kExpectedAbortInstructions) {
524444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      nop();
524544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
524644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
524744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
524844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
524944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
525044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
525144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (context_chain_length > 0) {
525244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Move up the chain of contexts to the context containing the slot.
52533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lw(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
525444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 1; i < context_chain_length; i++) {
52553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      lw(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
525644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
5257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
5258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Slot is in the current function context.  Move it into the
5259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // destination register in case we store into it (the write barrier
5260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // cannot be allowed to destroy the context in esi).
5261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(dst, cp);
5262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
526344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
526444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadNativeContextSlot(int index, Register dst) {
5266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(dst, NativeContextMemOperand());
5267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(dst, ContextMemOperand(dst, index));
526844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
526944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
527044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
527144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
527244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  Register map,
527344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  Register scratch) {
527444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the initial map. The global functions all have initial maps.
527544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
5276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
527744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label ok, fail;
5278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
527944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&ok);
528044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&fail);
5281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kGlobalFunctionsMustHaveInitialMap);
528244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&ok);
528344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
52843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
52853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
52863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::StubPrologue(StackFrame::Type type) {
528762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  li(at, Operand(StackFrame::TypeToMarker(type)));
52883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  PushCommonFrame(at);
5289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Prologue(bool code_pre_aging) {
5293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictible_code_size_scope(
5294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      this, kNoCodeAgeSequenceLength);
5295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The following three instructions must remain together and unmodified
5296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for code aging to work properly.
5297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_pre_aging) {
5298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Pre-age the code.
5299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
5300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop(Assembler::CODE_AGE_MARKER_NOP);
5301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the stub address to t9 and call it,
530262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // GetCodeAge() extracts the stub address from this instruction.
5303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(t9,
5304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Operand(reinterpret_cast<uint32_t>(stub->instruction_start())),
5305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       CONSTANT_SIZE);
5306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop();  // Prevent jalr to jal optimization.
5307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jalr(t9, a0);
5308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop();  // Branch delay slot nop.
5309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop();  // Pad the empty space.
5310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
53113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    PushStandardFrame(a1);
5312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop(Assembler::CODE_AGE_SEQUENCE_NOP);
5313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
531662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::EmitLoadFeedbackVector(Register vector) {
5317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
531862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  lw(vector, FieldMemOperand(vector, JSFunction::kFeedbackVectorOffset));
531962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  lw(vector, FieldMemOperand(vector, Cell::kValueOffset));
5320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
5321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::EnterFrame(StackFrame::Type type,
5324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                bool load_constant_pool_pointer_reg) {
5325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Out-of-line constant pool not implemented on mips.
5326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  UNREACHABLE();
5327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
5328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
53306ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
53313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int stack_offset, fp_offset;
53323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (type == StackFrame::INTERNAL) {
53333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    stack_offset = -4 * kPointerSize;
53343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    fp_offset = 2 * kPointerSize;
53353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
53363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    stack_offset = -3 * kPointerSize;
53373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    fp_offset = 1 * kPointerSize;
53383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
53393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  addiu(sp, sp, stack_offset);
53403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  stack_offset = -stack_offset - kPointerSize;
53413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(ra, MemOperand(sp, stack_offset));
53423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  stack_offset -= kPointerSize;
53433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(fp, MemOperand(sp, stack_offset));
53443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  stack_offset -= kPointerSize;
534562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  li(t9, Operand(StackFrame::TypeToMarker(type)));
53463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(t9, MemOperand(sp, stack_offset));
53473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (type == StackFrame::INTERNAL) {
53483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_EQ(stack_offset, kPointerSize);
53493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    li(t9, Operand(CodeObject()));
53503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    sw(t9, MemOperand(sp, 0));
53513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
53523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_EQ(stack_offset, 0);
53533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
5354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Adjust FP to point to saved FP.
53553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Addu(fp, sp, Operand(fp_offset));
53566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
53576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
53586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
53596ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
53603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  addiu(sp, fp, 2 * kPointerSize);
53613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(ra, MemOperand(fp, 1 * kPointerSize));
53623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(fp, MemOperand(fp, 0 * kPointerSize));
53636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
53646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterBuiltinFrame(Register context, Register target,
5366f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register argc) {
5367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(ra, fp);
5368f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Move(fp, sp);
5369f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Push(context, target, argc);
5370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
5371f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5372f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
5373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Register argc) {
5374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(context, target, argc);
5375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Pop(ra, fp);
5376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
5377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
5379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                    StackFrame::Type frame_type) {
5380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(frame_type == StackFrame::EXIT ||
5381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch         frame_type == StackFrame::BUILTIN_EXIT);
5382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
53833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
5384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement);
5385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset);
5386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset);
53876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This is how the stack will look:
5389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // fp + 2 (==kCallerSPDisplacement) - old stack's end
5390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // [fp + 1 (==kCallerPCOffset)] - saved old ra
5391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // [fp + 0 (==kCallerFPOffset)] - saved old fp
53923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // [fp - 1 StackFrame::EXIT Smi
53933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // [fp - 2 (==kSPOffset)] - sp of the called function
53943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // [fp - 3 (==kCodeOffset)] - CodeObject
5395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the
5396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //   new stack (will contain saved ra)
53976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
53983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Save registers and reserve room for saved entry sp and code object.
53993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  addiu(sp, sp, -2 * kPointerSize - ExitFrameConstants::kFixedFrameSizeFromFp);
54003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(ra, MemOperand(sp, 4 * kPointerSize));
54013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(fp, MemOperand(sp, 3 * kPointerSize));
540262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  li(at, Operand(StackFrame::TypeToMarker(frame_type)));
54033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  sw(at, MemOperand(sp, 2 * kPointerSize));
54043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Set up new frame pointer.
54053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  addiu(fp, sp, ExitFrameConstants::kFixedFrameSizeFromFp);
54066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
5408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    sw(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset));
5409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
5410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
54113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Accessed from ExitFrame::code_slot.
54123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(CodeObject()), CONSTANT_SIZE);
5413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
54146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
54156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Save the frame pointer and the context in top.
5416589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
541744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(fp, MemOperand(t8));
5418589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
541944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(cp, MemOperand(t8));
54206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
542244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (save_doubles) {
5423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The stack  must be allign to 0 modulo 8 for stores with sdc1.
5424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kDoubleSize == frame_alignment);
5425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (frame_alignment > 0) {
5426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
5427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      And(sp, sp, Operand(-frame_alignment));  // Align stack.
5428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
5429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int space = FPURegister::kMaxNumRegisters * kDoubleSize;
543044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(sp, sp, Operand(space));
543144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Remember: we only need to save every 2nd double FPU value.
5432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
543344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FPURegister reg = FPURegister::from_code(i);
5434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      sdc1(reg, MemOperand(sp, i * kDoubleSize));
543544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
543644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Reserve place for the return address, stack space and an optional slot
5439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (used by the DirectCEntryStub to hold the return value if a struct is
5440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // returned) and align the frame preparing for calling the runtime function.
5441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(stack_space >= 0);
5442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(sp, sp, Operand((stack_space + 2) * kPointerSize));
5443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (frame_alignment > 0) {
5444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
5445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    And(sp, sp, Operand(-frame_alignment));  // Align stack.
5446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
5447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Set the exit frame sp value to point just before the return address
5449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // location.
5450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  addiu(at, sp, kPointerSize);
5451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(at, MemOperand(fp, ExitFrameConstants::kSPOffset));
54526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
54536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
54546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
5456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    bool restore_context, bool do_return,
5457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    bool argument_count_is_length) {
545844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Optionally restore all double registers.
545944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (save_doubles) {
546044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Remember: we only need to restore every 2nd double FPU value.
5461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    lw(t8, MemOperand(fp, ExitFrameConstants::kSPOffset));
5462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
546344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FPURegister reg = FPURegister::from_code(i);
5464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ldc1(reg, MemOperand(t8, i * kDoubleSize + kPointerSize));
546544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
546644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
546744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
54686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Clear top frame.
5469589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
547044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(zero_reg, MemOperand(t8));
54716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
54726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Restore current context from top and clear it in debug mode.
5473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (restore_context) {
5474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
5475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lw(cp, MemOperand(t8));
5476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
54776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
5478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
547944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(a3, MemOperand(t8));
54806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
54816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
54826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pop the arguments, restore registers, and return.
54836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(sp, fp);  // Respect ABI stack constraint.
5484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(fp, MemOperand(sp, ExitFrameConstants::kCallerFPOffset));
5485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset));
54863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (argument_count.is_valid()) {
5488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (argument_count_is_length) {
5489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      addu(sp, sp, argument_count);
5490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
5491109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Lsa(sp, sp, argument_count, kPointerSizeLog2, t8);
5492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
5493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
54943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (do_return) {
54963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Ret(USE_DELAY_SLOT);
54973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If returning, the instruction in the delay slot will be the addiu below.
54983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
54993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addiu(sp, sp, 8);
55006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
55016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
550244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::ActivationFrameAlignment() {
5503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_HOST_ARCH_MIPS
550444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Running on the real platform. Use the alignment as mandated by the local
550544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // environment.
550644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Note: This will break if we ever start generating snapshots on one Mips
550744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // platform for another Mips platform with a different alignment.
5508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return base::OS::ActivationFrameAlignment();
5509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else  // V8_HOST_ARCH_MIPS
551044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If we are using the simulator then we should always align to the expected
551144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // alignment. As the simulator is used to generate snapshots we do not know
551244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // if the target platform will need alignment, so this is controlled from a
551344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // flag.
551444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return FLAG_sim_stack_alignment;
5515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_HOST_ARCH_MIPS
551644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
551744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
55183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::AssertStackIsAligned() {
5520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
5521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      const int frame_alignment = ActivationFrameAlignment();
5522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      const int frame_alignment_mask = frame_alignment - 1;
5523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (frame_alignment > kPointerSize) {
5525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label alignment_as_expected;
5526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
5527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        andi(at, sp, frame_alignment_mask);
5528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
5529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Don't use Check here, as it will call Runtime_Abort re-entering here.
5530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        stop("Unexpected stack alignment");
5531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        bind(&alignment_as_expected);
5532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
553344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
553444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
553544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
553644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
553744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotPowerOfTwoOrZero(
553844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register reg,
553944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register scratch,
554044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* not_power_of_two_or_zero) {
554144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Subu(scratch, reg, Operand(1));
554244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt,
554344f0eee88ff00398ff7f715fab053374d808c90dSteve Block         scratch, Operand(zero_reg));
554444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  and_(at, scratch, reg);  // In the delay slot.
554544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg));
554644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
554744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
554844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
55493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) {
5550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!reg.is(overflow));
55513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(overflow, reg);  // Save original value.
55523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiTag(reg);
55533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(overflow, overflow, reg);  // Overflow if (value ^ 2 * value) < 0.
55543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
55553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::SmiTagCheckOverflow(Register dst,
55583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register src,
55593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register overflow) {
55603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (dst.is(src)) {
55613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Fall back to slower case.
55623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiTagCheckOverflow(dst, overflow);
55633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(src));
5565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(overflow));
5566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src.is(overflow));
55673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiTag(dst, src);
55683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(overflow, dst, src);  // Overflow if (value ^ 2 * value) < 0.
55693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
55703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
55713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::UntagAndJumpIfSmi(Register dst,
55743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register src,
55753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* smi_case) {
55763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT);
55773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(dst, src);
55783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
55793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfSmi(Register value,
55813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Label* smi_label,
55823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register scratch,
55833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               BranchDelaySlot bd) {
5584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kSmiTag);
55853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  andi(scratch, value, kSmiTagMask);
55863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(bd, smi_label, eq, scratch, Operand(zero_reg));
55873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
55883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfNotSmi(Register value,
55903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Label* not_smi_label,
55913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register scratch,
55923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  BranchDelaySlot bd) {
5593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kSmiTag);
55943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  andi(scratch, value, kSmiTagMask);
55953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg));
55963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
55973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
559944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotBothSmi(Register reg1,
560044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      Register reg2,
560144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      Label* on_not_both_smi) {
560244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
5603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(1, kSmiTagMask);
560444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  or_(at, reg1, reg2);
56053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfNotSmi(at, on_not_both_smi);
560644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
560744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
560844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
560944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfEitherSmi(Register reg1,
561044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                     Register reg2,
561144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                     Label* on_either_smi) {
561244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
5613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(1, kSmiTagMask);
561444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Both Smi tags must be 1 (not Smi).
561544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  and_(at, reg1, reg2);
56163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(at, on_either_smi);
561744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
561844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
56193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::AssertNotNumber(Register object) {
56203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (emit_debug_code()) {
56213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
56223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    andi(at, object, kSmiTagMask);
56233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(ne, kOperandIsANumber, at, Operand(zero_reg));
56243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    GetObjectType(object, t8, t8);
56253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(ne, kOperandIsNotANumber, t8, Operand(HEAP_NUMBER_TYPE));
56263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
56273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
562844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNotSmi(Register object) {
5630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
5631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
5632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andi(at, object, kSmiTagMask);
5633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(ne, kOperandIsASmi, at, Operand(zero_reg));
5634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
563544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
563644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
563744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(Register object) {
5639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
5640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
5641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andi(at, object, kSmiTagMask);
5642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(eq, kOperandIsASmi, at, Operand(zero_reg));
5643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
564444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
564544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
564644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertString(Register object) {
5648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
5649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
5650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SmiTst(object, t8);
5651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(ne, kOperandIsASmiAndNotAString, t8, Operand(zero_reg));
5652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GetObjectType(object, t8, t8);
5653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(lo, kOperandIsNotAString, t8, Operand(FIRST_NONSTRING_TYPE));
5654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
5656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertName(Register object) {
5659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
5660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
5661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SmiTst(object, t8);
5662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(ne, kOperandIsASmiAndNotAName, t8, Operand(zero_reg));
5663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GetObjectType(object, t8, t8);
5664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(le, kOperandIsNotAName, t8, Operand(LAST_NAME_TYPE));
5665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
5666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
5667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertFunction(Register object) {
5670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
5671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
5672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SmiTst(object, t8);
5673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(ne, kOperandIsASmiAndNotAFunction, t8, Operand(zero_reg));
5674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GetObjectType(object, t8, t8);
5675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(eq, kOperandIsNotAFunction, t8, Operand(JS_FUNCTION_TYPE));
5676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
5677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
5678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertBoundFunction(Register object) {
5681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
5682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
5683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SmiTst(object, t8);
5684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(ne, kOperandIsASmiAndNotABoundFunction, t8, Operand(zero_reg));
5685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GetObjectType(object, t8, t8);
5686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(eq, kOperandIsNotABoundFunction, t8, Operand(JS_BOUND_FUNCTION_TYPE));
5687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5690bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::AssertGeneratorObject(Register object) {
5691bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (emit_debug_code()) {
5692bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
5693bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    SmiTst(object, t8);
5694bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(ne, kOperandIsASmiAndNotAGeneratorObject, t8, Operand(zero_reg));
5695bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    GetObjectType(object, t8, t8);
5696bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(eq, kOperandIsNotAGeneratorObject, t8,
5697bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          Operand(JS_GENERATOR_OBJECT_TYPE));
5698bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
5699bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
5700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::AssertReceiver(Register object) {
5702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
5703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
5704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    SmiTst(object, t8);
5705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(ne, kOperandIsASmiAndNotAReceiver, t8, Operand(zero_reg));
5706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    GetObjectType(object, t8, t8);
5707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(ge, kOperandIsNotAReceiver, t8, Operand(FIRST_JS_RECEIVER_TYPE));
5708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
5709109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
5710109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
5711109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
5712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
5713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Register scratch) {
5714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
5715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done_checking;
5716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AssertNotSmi(object);
5717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
5718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Branch(&done_checking, eq, object, Operand(scratch));
5719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lw(t8, FieldMemOperand(object, HeapObject::kMapOffset));
5720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex);
5721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assert(eq, kExpectedUndefinedOrCell, t8, Operand(scratch));
5722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done_checking);
5723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
5728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
5729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!reg.is(at));
5730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadRoot(at, index);
5731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at));
5732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
573344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
573444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
573544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
573644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotHeapNumber(Register object,
573744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register heap_number_map,
573844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch,
573944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Label* on_not_heap_number) {
574044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
5741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
574244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map));
574344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
574444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
574544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNonSmisNotBothSequentialOneByteStrings(
5747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register first, Register second, Register scratch1, Register scratch2,
574844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* failure) {
5749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test that both first and second are sequential one-byte strings.
575044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Assume that they are non-smis.
575144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
575244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
575344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
575444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
575544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfBothInstanceTypesAreNotSequentialOneByte(scratch1, scratch2, scratch1,
5757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 scratch2, failure);
575844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
575944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
576044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register first,
5762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register second,
5763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch1,
5764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Register scratch2,
5765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           Label* failure) {
576644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that neither is a smi.
576744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
576844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch1, first, Operand(second));
57693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(scratch1, failure);
5770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNonSmisNotBothSequentialOneByteStrings(first, second, scratch1,
5771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               scratch2, failure);
577244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
577344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
577462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Float32Max(FPURegister dst, FPURegister src1,
577562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                FPURegister src2, Label* out_of_line) {
577662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (src1.is(src2)) {
577762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Move_s(dst, src1);
577862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
577962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
578062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
578162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check if one of operands is NaN.
578262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BranchF32(nullptr, out_of_line, eq, src1, src2);
578362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
578462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (IsMipsArchVariant(kMips32r6)) {
578562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    max_s(dst, src1, src2);
578662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
578762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label return_left, return_right, done;
578862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
578962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BranchF32(&return_right, nullptr, lt, src1, src2);
579062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BranchF32(&return_left, nullptr, lt, src2, src1);
579162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
579262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Operands are equal, but check for +/-0.
579362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    mfc1(t8, src1);
579462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&return_left, eq, t8, Operand(zero_reg));
579562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&return_right);
579662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
579762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&return_right);
579862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!src2.is(dst)) {
579962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Move_s(dst, src2);
580062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
580162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&done);
580262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
580362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&return_left);
580462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!src1.is(dst)) {
580562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Move_s(dst, src1);
580662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
580762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
580862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&done);
580962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
581062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
581162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
581262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Float32MaxOutOfLine(FPURegister dst, FPURegister src1,
581362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                         FPURegister src2) {
581462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  add_s(dst, src1, src2);
581562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
581662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
581762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Float32Min(FPURegister dst, FPURegister src1,
581862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                FPURegister src2, Label* out_of_line) {
581962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (src1.is(src2)) {
582062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Move_s(dst, src1);
582162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
582262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
582362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
582462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check if one of operands is NaN.
582562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BranchF32(nullptr, out_of_line, eq, src1, src2);
582662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
582762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (IsMipsArchVariant(kMips32r6)) {
582862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    min_s(dst, src1, src2);
582962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
583062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label return_left, return_right, done;
583162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
583262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BranchF32(&return_left, nullptr, lt, src1, src2);
583362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BranchF32(&return_right, nullptr, lt, src2, src1);
583462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
583562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Left equals right => check for -0.
583662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    mfc1(t8, src1);
583762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&return_right, eq, t8, Operand(zero_reg));
583862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&return_left);
583962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
584062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&return_right);
584162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!src2.is(dst)) {
584262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Move_s(dst, src2);
584362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
584462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&done);
584562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
584662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&return_left);
584762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!src1.is(dst)) {
584862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Move_s(dst, src1);
584962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
585062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
585162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&done);
585262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
585362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
585462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
585562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Float32MinOutOfLine(FPURegister dst, FPURegister src1,
585662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                         FPURegister src2) {
585762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  add_s(dst, src1, src2);
585862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
585962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
586062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Float64Max(DoubleRegister dst, DoubleRegister src1,
586162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                DoubleRegister src2, Label* out_of_line) {
586262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (src1.is(src2)) {
586362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Move_d(dst, src1);
586462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
586562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
586662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
586762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check if one of operands is NaN.
586862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BranchF64(nullptr, out_of_line, eq, src1, src2);
586962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
587062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (IsMipsArchVariant(kMips32r6)) {
587162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    max_d(dst, src1, src2);
587262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
587362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label return_left, return_right, done;
587462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
587562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BranchF64(&return_right, nullptr, lt, src1, src2);
587662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BranchF64(&return_left, nullptr, lt, src2, src1);
587762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
587862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Left equals right => check for -0.
587962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Mfhc1(t8, src1);
588062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&return_left, eq, t8, Operand(zero_reg));
588162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&return_right);
588262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
588362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&return_right);
588462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!src2.is(dst)) {
588562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Move_d(dst, src2);
588662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
588762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&done);
588862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
588962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&return_left);
589062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!src1.is(dst)) {
589162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Move_d(dst, src1);
589262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
589362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
589462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&done);
589562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
589662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
589762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
589862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Float64MaxOutOfLine(DoubleRegister dst,
589962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                         DoubleRegister src1,
590062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                         DoubleRegister src2) {
590162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  add_d(dst, src1, src2);
590262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
590362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
590462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Float64Min(DoubleRegister dst, DoubleRegister src1,
590562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                DoubleRegister src2, Label* out_of_line) {
590662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (src1.is(src2)) {
590762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Move_d(dst, src1);
590862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
590962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
591062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
591162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check if one of operands is NaN.
591262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BranchF64(nullptr, out_of_line, eq, src1, src2);
591362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
591462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (IsMipsArchVariant(kMips32r6)) {
591562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    min_d(dst, src1, src2);
591662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
591762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label return_left, return_right, done;
591862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
591962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BranchF64(&return_left, nullptr, lt, src1, src2);
592062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BranchF64(&return_right, nullptr, lt, src2, src1);
592162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
592262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Left equals right => check for -0.
592362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Mfhc1(t8, src1);
592462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&return_right, eq, t8, Operand(zero_reg));
592562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&return_left);
592662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
592762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&return_right);
592862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!src2.is(dst)) {
592962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Move_d(dst, src2);
593062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
593162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(&done);
593262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
593362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&return_left);
593462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!src1.is(dst)) {
593562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Move_d(dst, src1);
593662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
593762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
593862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bind(&done);
593962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
594062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
594162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
594262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid MacroAssembler::Float64MinOutOfLine(DoubleRegister dst,
594362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                         DoubleRegister src1,
594462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                         DoubleRegister src2) {
594562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  add_d(dst, src1, src2);
594662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
594744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
5949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register first, Register second, Register scratch1, Register scratch2,
595044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* failure) {
5951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
595244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
5953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
5954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
5955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kFlatOneByteStringTag <= 0xffff);  // Ensure this fits 16-bit immed.
5956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andi(scratch1, first, kFlatOneByteStringMask);
5957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(failure, ne, scratch1, Operand(kFlatOneByteStringTag));
5958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andi(scratch2, second, kFlatOneByteStringMask);
5959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(failure, ne, scratch2, Operand(kFlatOneByteStringTag));
596044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
596144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
596244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 4;
596344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
59643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
59653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              int num_double_arguments) {
59663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int stack_passed_words = 0;
59673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  num_reg_arguments += 2 * num_double_arguments;
59683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Up to four simple arguments are passed in registers a0..a3.
59703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (num_reg_arguments > kRegisterPassedArguments) {
59713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
59723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
59733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  stack_passed_words += kCArgSlotCount;
59743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return stack_passed_words;
59753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
59763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
5979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register index,
5980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register value,
5981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch,
5982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               uint32_t encoding_mask) {
5983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_object;
5984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTst(string, at);
5985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(ne, kNonObject, at, Operand(zero_reg));
5986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
5988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
5989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andi(at, at, kStringRepresentationMask | kStringEncodingMask);
5991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  li(scratch, Operand(encoding_mask));
5992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(eq, kUnexpectedStringType, at, Operand(scratch));
5993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The index is assumed to be untagged coming in, tag it to compare with the
5995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // string length without using a temp register, it is restored at the end of
5996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this function.
5997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label index_tag_ok, index_tag_bad;
5998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TrySmiTag(index, scratch, &index_tag_bad);
5999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(&index_tag_ok);
6000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&index_tag_bad);
6001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(kIndexIsTooLarge);
6002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&index_tag_ok);
6003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(at, FieldMemOperand(string, String::kLengthOffset));
6005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(lt, kIndexIsTooLarge, index, Operand(at));
6006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6007c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK(Smi::kZero == 0);
6008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(ge, kIndexIsNegative, index, Operand(zero_reg));
6009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiUntag(index, index);
6011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
60143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
60153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          int num_double_arguments,
60163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Register scratch) {
601744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int frame_alignment = ActivationFrameAlignment();
601844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
601944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Up to four simple arguments are passed in registers a0..a3.
602044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Those four arguments must have reserved argument slots on the stack for
602144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // mips, even though those argument slots are not normally used.
602244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Remaining arguments are pushed on the stack, above (higher address than)
602344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the argument slots.
60243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int stack_passed_arguments = CalculateStackPassedWords(
60253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      num_reg_arguments, num_double_arguments);
602644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (frame_alignment > kPointerSize) {
602744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Make stack end at alignment and make room for num_arguments - 4 words
602844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // and the original value of sp.
602944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(scratch, sp);
603044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
6031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
603244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    And(sp, sp, Operand(-frame_alignment));
603344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
603444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
603544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
603644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
603744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
603844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
603944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
60403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
60413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Register scratch) {
60423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCallCFunction(num_reg_arguments, 0, scratch);
60433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
60443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallCFunction(ExternalReference function,
60473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_reg_arguments,
60483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_double_arguments) {
60493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(function));
60503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunctionHelper(t8, num_reg_arguments, num_double_arguments);
60513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
60523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallCFunction(Register function,
60553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_reg_arguments,
60563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_double_arguments) {
60573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
60583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
60593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
606144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunction(ExternalReference function,
606244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   int num_arguments) {
60633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunction(function, num_arguments, 0);
606444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
606544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
606644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
606744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunction(Register function,
606844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   int num_arguments) {
60693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunction(function, num_arguments, 0);
607044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
607144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
607244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
607344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunctionHelper(Register function,
60743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         int num_reg_arguments,
60753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         int num_double_arguments) {
6076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(has_frame());
607744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make sure that the stack is aligned before calling a C function unless
607844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // running in the simulator. The simulator has its own alignment check which
607944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // provides more information.
608044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The argument stots are presumed to have been set up by
608144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // PrepareCallCFunction. The C function must be called via t9, for mips ABI.
608244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_HOST_ARCH_MIPS
608444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
6085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int frame_alignment = base::OS::ActivationFrameAlignment();
608644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int frame_alignment_mask = frame_alignment - 1;
608744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (frame_alignment > kPointerSize) {
6088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
608944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Label alignment_as_expected;
609044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      And(at, sp, Operand(frame_alignment_mask));
609144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
609244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Don't use Check here, as it will call Runtime_Abort possibly
609344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // re-entering here.
609444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      stop("Unexpected alignment in CallCFunction");
609544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bind(&alignment_as_expected);
60966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
60976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
609844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif  // V8_HOST_ARCH_MIPS
609944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
610044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Just call directly. The function called cannot cause a GC, or
610144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // allow preemption, so the return address in the link register
610244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // stays correct.
610344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
61043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!function.is(t9)) {
6105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    mov(t9, function);
610644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    function = t9;
610744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
610844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
610944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Call(function);
611044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
61113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int stack_passed_arguments = CalculateStackPassedWords(
61123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      num_reg_arguments, num_double_arguments);
611344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (base::OS::ActivationFrameAlignment() > kPointerSize) {
611544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
611644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
6117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Addu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
611844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
61196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
61206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
612144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
612244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef BRANCH_ARGS_CHECK
612344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
612444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
61253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
61263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
61273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
61283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
61293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
61303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met) {
61313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(scratch, object, Operand(~Page::kPageAlignmentMask));
61323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
61333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(scratch, scratch, Operand(mask));
61343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(condition_met, cc, scratch, Operand(zero_reg));
61353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
61363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
61393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch0,
61403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch1,
61413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black) {
6142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HasColor(object, scratch0, scratch1, on_black, 1, 1);  // kBlackBitPattern.
6143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
61443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
61453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::HasColor(Register object,
61483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register bitmap_scratch,
61493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register mask_scratch,
61503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label* has_color,
61513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int first_bit,
61523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int second_bit) {
6153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t8));
6154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t9));
61553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
61573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label other_color, word_boundary;
61593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
61603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, t9, Operand(mask_scratch));
61613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg));
61623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Shift left 1 by adding.
61633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(mask_scratch, mask_scratch, Operand(mask_scratch));
61643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&word_boundary, eq, mask_scratch, Operand(zero_reg));
61653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, t9, Operand(mask_scratch));
61663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg));
61673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&other_color);
61683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&word_boundary);
61703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize));
61713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t9, t9, Operand(1));
61723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(has_color, second_bit == 1 ? ne : eq, t9, Operand(zero_reg));
61733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&other_color);
61743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
61753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
61783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
61793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
6180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
61813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask));
61823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2);
61833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
61843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits);
6185109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Lsa(bitmap_reg, bitmap_reg, t8, kPointerSizeLog2, t8);
61863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(1));
61873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sllv(mask_reg, t8, mask_reg);
61883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
61893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
6192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Register mask_scratch, Register load_scratch,
6193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Label* value_is_white) {
6194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, t8));
61953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
61963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
6198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
6199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
6200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
6201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
62023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
62043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
62053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
62063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, mask_scratch, load_scratch);
6207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Branch(value_is_white, eq, t8, Operand(zero_reg));
62083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
62093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
6212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
6213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
6214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
6218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(dst, FieldMemOperand(map, Map::kBitField3Offset));
6219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
6220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnumLength(Register dst, Register map) {
6224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
6225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(dst, FieldMemOperand(map, Map::kBitField3Offset));
6226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  And(dst, dst, Operand(Map::EnumLengthBits::kMask));
6227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiTag(dst);
6228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadAccessor(Register dst, Register holder,
6232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int accessor_index,
6233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  AccessorComponent accessor) {
6234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(dst, FieldMemOperand(holder, HeapObject::kMapOffset));
6235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadInstanceDescriptors(dst, dst);
6236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(dst,
6237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch     FieldMemOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
6238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
6239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           : AccessorPair::kSetterOffset;
6240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  lw(dst, FieldMemOperand(dst, offset));
6241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
6242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6244109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) {
6245109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Register null_value = t1;
62463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register  empty_fixed_array_value = t2;
62473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
6248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label next, start;
6249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mov(a2, a0);
62503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the enum length field is properly initialized, indicating that
6252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // there is an enum cache.
6253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset));
62543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(a3, a1);
6256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(
6257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      call_runtime, eq, a3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel)));
62583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6259109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  LoadRoot(null_value, Heap::kNullValueRootIndex);
6260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&start);
6261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&next);
6263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset));
62643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For all objects but the receiver, check that the cache is empty.
6266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(a3, a1);
6267c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(call_runtime, ne, a3, Operand(Smi::kZero));
6268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&start);
6270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that there are no elements. Register a2 contains the current JS
6272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object we've reached through the prototype chain.
6273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_elements;
6274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(a2, FieldMemOperand(a2, JSObject::kElementsOffset));
6275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(&no_elements, eq, a2, Operand(empty_fixed_array_value));
6276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Second chance, the object may be using the empty slow element dictionary.
6278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex);
6279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(call_runtime, ne, a2, Operand(at));
62803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&no_elements);
6282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset));
6283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Branch(&next, ne, a2, Operand(null_value));
62843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
62853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
62873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
6288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!output_reg.is(input_reg));
62893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
62903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(output_reg, Operand(255));
62913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Normal branch: nop in delay slot.
62923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done, gt, input_reg, Operand(output_reg));
62933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use delay slot in this branch.
62943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(USE_DELAY_SLOT, &done, lt, input_reg, Operand(zero_reg));
62953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(output_reg, zero_reg);  // In delay slot.
62963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(output_reg, input_reg);  // Value is in range 0..255.
62973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
62983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
62993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ClampDoubleToUint8(Register result_reg,
63023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        DoubleRegister input_reg,
63033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        DoubleRegister temp_double_reg) {
63043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label above_zero;
63053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
63063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label in_bounds;
63073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Move(temp_double_reg, 0.0);
63093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BranchF(&above_zero, NULL, gt, input_reg, temp_double_reg);
63103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Double value is less than zero, NaN or Inf, return 0.
63123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(result_reg, zero_reg);
63133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done);
63143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Double value is >= 255, return 255.
63163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&above_zero);
63173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Move(temp_double_reg, 255.0);
63183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BranchF(&in_bounds, NULL, le, input_reg, temp_double_reg);
63193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(result_reg, Operand(255));
63203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done);
63213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // In 0-255 range, round and truncate.
63233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&in_bounds);
6324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cvt_w_d(temp_double_reg, input_reg);
63253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mfc1(result_reg, temp_double_reg);
63263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
63273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
63283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
63293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::TestJSArrayForAllocationMemento(Register receiver_reg,
63303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                                     Register scratch_reg,
63313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                                     Label* no_memento_found) {
63323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label map_check;
63333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label top_check;
6334bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ExternalReference new_space_allocation_top_adr =
6335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::new_space_allocation_top_address(isolate());
63363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
6337c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int kMementoLastWordOffset =
6338c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      kMementoMapOffset + AllocationMemento::kSize - kPointerSize;
63393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
63403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Bail out if the object is not in new space.
63413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
63423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If the object is in new space, we need to check whether it is on the same
63433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // page as the current top.
6344c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Addu(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
6345bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(at, Operand(new_space_allocation_top_adr));
6346bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  lw(at, MemOperand(at));
6347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Xor(scratch_reg, scratch_reg, Operand(at));
63483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  And(scratch_reg, scratch_reg, Operand(~Page::kPageAlignmentMask));
63493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Branch(&top_check, eq, scratch_reg, Operand(zero_reg));
63503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // The object is on a different page than allocation top. Bail out if the
63513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // object sits on the page boundary as no memento can follow and we cannot
63523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // touch the memory following it.
6353c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Addu(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
63543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Xor(scratch_reg, scratch_reg, Operand(receiver_reg));
63553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  And(scratch_reg, scratch_reg, Operand(~Page::kPageAlignmentMask));
63563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Branch(no_memento_found, ne, scratch_reg, Operand(zero_reg));
63573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Continue with the actual map check.
63583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&map_check);
63593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If top is on the same page as the current object, we need to check whether
63603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // we are below top.
63613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&top_check);
6362c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Addu(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
6363bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  li(at, Operand(new_space_allocation_top_adr));
6364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lw(at, MemOperand(at));
6365c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(no_memento_found, ge, scratch_reg, Operand(at));
63663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Memento map check.
63673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&map_check);
63683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lw(scratch_reg, MemOperand(receiver_reg, kMementoMapOffset));
63693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Branch(no_memento_found, ne, scratch_reg,
63703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Operand(isolate()->factory()->allocation_memento_map()));
6371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister GetRegisterThatIsNotOneOf(Register reg1,
6375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg2,
6376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg3,
6377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg4,
6378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg5,
6379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg6) {
6380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
6381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
6382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
6383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
6384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
6385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
6386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
6387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
638813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
6389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
6390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int code = config->GetAllocatableGeneralCode(i);
6391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register candidate = Register::from_code(code);
6392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (regs & candidate.bit()) continue;
6393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return candidate;
6394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UNREACHABLE();
6396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return no_reg;
63973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
63983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool AreAliased(Register reg1, Register reg2, Register reg3, Register reg4,
6400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register reg5, Register reg6, Register reg7, Register reg8,
6401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register reg9, Register reg10) {
6402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() + reg3.is_valid() +
6403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
6404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        reg7.is_valid() + reg8.is_valid() + reg9.is_valid() +
6405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        reg10.is_valid();
6406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
6408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
6409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
6410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
6411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
6412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
6413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
6414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg7.is_valid()) regs |= reg7.bit();
6415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg8.is_valid()) regs |= reg8.bit();
6416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (reg9.is_valid()) regs |= reg9.bit();
6417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (reg10.is_valid()) regs |= reg10.bit();
6418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_non_aliasing_regs = NumRegs(regs);
6419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return n_of_valid_regs != n_of_non_aliasing_regs;
6421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodePatcher::CodePatcher(Isolate* isolate, byte* address, int instructions,
6425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         FlushICache flush_cache)
642644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : address_(address),
642744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      size_(instructions * Assembler::kInstrSize),
6428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      masm_(isolate, address, size_ + Assembler::kGap, CodeObjectRequired::kNo),
6429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      flush_cache_(flush_cache) {
643044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
643144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
643244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // bytes of instructions without failing with buffer size constraints.
6433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
643444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
643544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
643644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
643744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockCodePatcher::~CodePatcher() {
643844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Indicate that code has changed.
6439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (flush_cache_ == FLUSH) {
6440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler::FlushICache(masm_.isolate(), address_, size_);
6441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
644244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
644344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the code was patched as expected.
6444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.pc_ == address_ + size_);
6445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
644644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
644744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
644844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid CodePatcher::Emit(Instr instr) {
6450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  masm()->emit(instr);
645144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
645244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
645344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
645444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid CodePatcher::Emit(Address addr) {
645544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  masm()->emit(reinterpret_cast<Instr>(addr));
645644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
645744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
645844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CodePatcher::ChangeBranchCondition(Instr current_instr,
6460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        uint32_t new_opcode) {
6461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  current_instr = (current_instr & ~kOpcodeMask) | new_opcode;
6462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  masm_.emit(current_instr);
6463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
646444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
646544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncatingDiv(Register result,
6467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register dividend,
6468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   int32_t divisor) {
6469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(result));
6470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(at));
6471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(at));
6472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::MagicNumbersForDivision<uint32_t> mag =
6473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
6474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  li(at, Operand(mag.multiplier));
6475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Mulh(result, dividend, Operand(at));
6476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
6477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 0 && neg) {
6478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Addu(result, result, Operand(dividend));
6479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0 && !neg && mag.multiplier > 0) {
6481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Subu(result, result, Operand(dividend));
6482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mag.shift > 0) sra(result, result, mag.shift);
6484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  srl(at, dividend, 31);
6485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Addu(result, result, Operand(at));
6486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
6490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
64913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_MIPS
6493