13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
23100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Redistribution and use in source and binary forms, with or without
33100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// modification, are permitted provided that the following conditions are
43100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// met:
53100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
63100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Redistributions of source code must retain the above copyright
73100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       notice, this list of conditions and the following disclaimer.
83100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Redistributions in binary form must reproduce the above
93100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       copyright notice, this list of conditions and the following
103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       disclaimer in the documentation and/or other materials provided
113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       with the distribution.
123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Neither the name of Google Inc. nor the names of its
133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       contributors may be used to endorse or promote products derived
143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       from this software without specific prior written permission.
153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include <limits.h>  // For LONG_MIN, LONG_MAX.
293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "v8.h"
313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
32f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_MIPS)
33f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "bootstrapper.h"
35257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "codegen.h"
363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "debug.h"
373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "runtime.h"
383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 {
403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal {
413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    : Assembler(arg_isolate, buffer, size),
443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      generating_stub_(false),
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      allow_stub_calls_(true),
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      has_frame_(false) {
47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (isolate() != NULL) {
48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  isolate());
50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::LoadRoot(Register destination,
553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Heap::RootListIndex index) {
566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(destination, MemOperand(s6, index << kPointerSizeLog2));
573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::LoadRoot(Register destination,
613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Heap::RootListIndex index,
623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Condition cond,
633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Register src1, const Operand& src2) {
6444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(2, NegateCondition(cond), src1, src2);
656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(destination, MemOperand(s6, index << kPointerSizeLog2));
663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::StoreRoot(Register source,
7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Heap::RootListIndex index) {
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(source, MemOperand(s6, index << kPointerSizeLog2));
7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::StoreRoot(Register source,
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Heap::RootListIndex index,
7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Condition cond,
7844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register src1, const Operand& src2) {
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(2, NegateCondition(cond), src1, src2);
8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(source, MemOperand(s6, index << kPointerSizeLog2));
8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadHeapObject(Register result,
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Handle<HeapObject> object) {
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell =
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewJSGlobalPropertyCell(object);
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(result, Operand(cell));
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset));
91c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  } else {
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(result, Operand(object));
93c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
94c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
95c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
96c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Push and pop all registers that can hold pointers.
98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::PushSafepointRegisters() {
99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Safepoints expect a block of kNumSafepointRegisters values on the
100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // stack, so adjust the stack for unsaved registers.
101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(num_unsaved >= 0);
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (num_unsaved > 0) {
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Subu(sp, sp, Operand(num_unsaved * kPointerSize));
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  MultiPush(kSafepointSavedRegisters);
107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::PopSafepointRegisters() {
111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  MultiPop(kSafepointSavedRegisters);
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (num_unsaved > 0) {
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Addu(sp, sp, Operand(num_unsaved * kPointerSize));
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::PushSafepointRegistersAndDoubles() {
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  PushSafepointRegisters();
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(sp, sp, Operand(FPURegister::kNumAllocatableRegisters * kDoubleSize));
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < FPURegister::kNumAllocatableRegisters; i+=2) {
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    FPURegister reg = FPURegister::FromAllocationIndex(i);
124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    sdc1(reg, MemOperand(sp, i * kDoubleSize));
125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::PopSafepointRegistersAndDoubles() {
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < FPURegister::kNumAllocatableRegisters; i+=2) {
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    FPURegister reg = FPURegister::FromAllocationIndex(i);
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ldc1(reg, MemOperand(sp, i * kDoubleSize));
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Addu(sp, sp, Operand(FPURegister::kNumAllocatableRegisters * kDoubleSize));
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  PopSafepointRegisters();
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src,
140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                             Register dst) {
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(src, SafepointRegistersAndDoublesSlot(dst));
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(src, SafepointRegisterSlot(dst));
147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(dst, SafepointRegisterSlot(src));
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The registers are pushed starting with the highest encoding,
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // which means that lowest encodings are closest to the stack pointer.
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return kSafepointRegisterStackIndexMap[reg_code];
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochMemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochMemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNIMPLEMENTED_MIPS();
169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // General purpose registers are pushed last on the stack.
170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int doubles_size = FPURegister::kNumAllocatableRegisters * kDoubleSize;
171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return MemOperand(sp, doubles_size + register_offset);
173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
17644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::InNewSpace(Register object,
17744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Register scratch,
17844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Condition cc,
17944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Label* branch) {
18044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(cc == eq || cc == ne);
18144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch, object, Operand(ExternalReference::new_space_mask(isolate())));
18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(branch, cc, scratch,
18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Operand(ExternalReference::new_space_start(isolate())));
18444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
18644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField(
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset,
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register dst,
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RAStatus ra_status,
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RememberedSetAction remembered_set_action,
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiCheck smi_check) {
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(value, dst, t8, object));
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First, check if a write barrier is even needed. The tests below
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
19985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  Label done;
20044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Although the object register is tagged, the offset is relative to the start
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(IsAligned(offset, kPointerSize));
209592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(dst, object, Operand(offset - kHeapObjectTag));
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    And(t8, dst, Operand((1 << kPointerSizeLog2) - 1));
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&ok, eq, t8, Operand(zero_reg));
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    stop("Unaligned cell in write barrier");
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWrite(object,
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              dst,
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              value,
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              ra_status,
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              save_fp,
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              remembered_set_action,
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              OMIT_SMI_CHECK);
22644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
22844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // turned on to provoke errors.
231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(value, Operand(BitCast<int32_t>(kZapValue + 4)));
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(dst, Operand(BitCast<int32_t>(kZapValue + 8)));
23444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
23644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
23744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
23844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Will clobber 4 registers: object, address, scratch, ip.  The
23944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// register 'object' contains a heap object pointer.  The heap object
24044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// tag is shifted away.
24144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::RecordWrite(Register object,
24244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 Register address,
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register value,
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 RAStatus ra_status,
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 SaveFPRegsMode fp_mode,
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 RememberedSetAction remembered_set_action,
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 SmiCheck smi_check) {
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(object, address, value, t8));
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(object, address, value, t9));
25044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The compiled code assumes that record write doesn't change the
25144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // context register, so we check that none of the clobbered
25244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // registers are cp.
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!address.is(cp) && !value.is(cp));
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(at, MemOperand(address));
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Assert(
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        eq, "Wrong address or value passed to RecordWrite", at, Operand(value));
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
260c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
26144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done;
26244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT_EQ(0, kSmiTag);
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(value,
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersToHereAreInterestingMask,
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                eq,
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done);
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(object,
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                eq,
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done);
27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Record the actual write.
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (ra_status == kRAHasNotBeenSaved) {
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(ra);
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode);
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub);
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (ra_status == kRAHasNotBeenSaved) {
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    pop(ra);
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
28844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
29044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
29244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // turned on to provoke errors.
293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(address, Operand(BitCast<int32_t>(kZapValue + 12)));
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(value, Operand(BitCast<int32_t>(kZapValue + 16)));
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register address,
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch,
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         SaveFPRegsMode fp_mode,
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         RememberedSetFinalAction and_then) {
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfNotInNewSpace(object, scratch, &ok);
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    stop("Remembered set pointer is in new space");
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load store buffer top.
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference store_buffer =
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference::store_buffer_top(isolate());
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(store_buffer));
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, MemOperand(t8));
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store pointer to buffer and increment buffer top.
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(address, MemOperand(scratch));
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(scratch, scratch, kPointerSize);
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Write back new top of buffer.
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(scratch, MemOperand(t8));
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call stub on end of buffer.
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for end of buffer.
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit));
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kFallThroughAtEnd) {
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, eq, t8, Operand(zero_reg));
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(and_then == kReturnAtEnd);
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Ret(eq, t8, Operand(zero_reg));
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(ra);
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StoreBufferOverflowStub store_buffer_overflow =
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StoreBufferOverflowStub(fp_mode);
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&store_buffer_overflow);
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(ra);
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Ret();
33944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
34044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
34144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// -----------------------------------------------------------------------------
344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Allocation support.
34544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
34844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Register scratch,
34944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Label* miss) {
35044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label same_contexts;
35144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!holder_reg.is(scratch));
35344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!holder_reg.is(at));
35444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!scratch.is(at));
35544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load current lexical context from the stack frame.
35744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
35844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // In debug mode, make sure the lexical context is set.
35944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
36044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Check(ne, "we should not have an empty lexical context",
36144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      scratch, Operand(zero_reg));
36244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
36344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
36444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the global context of the current context.
36544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
36644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(scratch, offset));
36744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(scratch, GlobalObject::kGlobalContextOffset));
36844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
36944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check the context is a global context.
370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
37144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // TODO(119): Avoid push(holder_reg)/pop(holder_reg).
372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    push(holder_reg);  // Temporarily save holder on the stack.
37344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Read the first word and compare to the global_context_map.
37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
37544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadRoot(at, Heap::kGlobalContextMapRootIndex);
37644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Check(eq, "JSGlobalObject::global_context should be a global context.",
37744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          holder_reg, Operand(at));
378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    pop(holder_reg);  // Restore holder.
37944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check if both contexts are the same.
38244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(at, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset));
38344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&same_contexts, eq, scratch, Operand(at));
38444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check the context is a global context.
386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
38744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // TODO(119): Avoid push(holder_reg)/pop(holder_reg).
388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    push(holder_reg);  // Temporarily save holder on the stack.
38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(holder_reg, at);  // Move at to its holding place.
39044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadRoot(at, Heap::kNullValueRootIndex);
39144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Check(ne, "JSGlobalProxy::context() should not be null.",
39244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          holder_reg, Operand(at));
39344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadRoot(at, Heap::kGlobalContextMapRootIndex);
39644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Check(eq, "JSGlobalObject::global_context should be a global context.",
39744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          holder_reg, Operand(at));
39844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Restore at is not needed. at is reloaded below.
399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    pop(holder_reg);  // Restore holder.
40044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Restore at to holder's context.
40144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(at, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset));
40244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
40344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
40444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the security token in the calling global object is
40544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // compatible with the security token in the receiving global
40644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // object.
40744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int token_offset = Context::kHeaderSize +
40844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
40944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
41044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(scratch, token_offset));
41144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(at, FieldMemOperand(at, token_offset));
41244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(miss, ne, scratch, Operand(at));
41344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
41444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&same_contexts);
4153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
4163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
418c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register reg0, Register scratch) {
419c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // First of all we assign the hash seed to scratch.
420c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  LoadRoot(scratch, Heap::kHashSeedRootIndex);
421c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  SmiUntag(scratch);
422c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
423c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Xor original key with a seed.
424c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xor_(reg0, reg0, scratch);
425c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
426c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Compute the hash code from the untagged key.  This must be kept in sync
427c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // with ComputeIntegerHash in utils.h.
428c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  //
429c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = ~hash + (hash << 15);
430c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  nor(scratch, reg0, zero_reg);
431c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  sll(at, reg0, 15);
432c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  addu(reg0, scratch, at);
433c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
434c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 12);
435c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  srl(at, reg0, 12);
436c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xor_(reg0, reg0, at);
437c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
438c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash + (hash << 2);
439c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  sll(at, reg0, 2);
440c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  addu(reg0, reg0, at);
441c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
442c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 4);
443c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  srl(at, reg0, 4);
444c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xor_(reg0, reg0, at);
445c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
446c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash * 2057;
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sll(scratch, reg0, 11);
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sll(at, reg0, 3);
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addu(reg0, reg0, at);
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addu(reg0, reg0, scratch);
451c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
452c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 16);
453c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  srl(at, reg0, 16);
454c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xor_(reg0, reg0, at);
455c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
456c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
457c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss,
4593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register elements,
4603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register key,
4613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register result,
4623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register reg0,
4633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register reg1,
4643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register reg2) {
4653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Register use:
4663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
4673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // elements - holds the slow-case elements of the receiver on entry.
4683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged unless 'result' is the same register.
4693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
4703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // key      - holds the smi key on entry.
4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged unless 'result' is the same register.
4723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
4733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
4743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // result   - holds the result on exit if the load succeeded.
4753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Allowed to be the same as 'key' or 'result'.
4763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged on bailout so 'key' or 'result' can be used
4773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            in further computation.
4783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
4793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Scratch registers:
4803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
4813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // reg0 - holds the untagged key on entry and holds the hash once computed.
4823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
4833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // reg1 - Used to hold the capacity mask of the dictionary.
4843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
4853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // reg2 - Used for the index into the dictionary.
4863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // at   - Temporary (avoid MacroAssembler instructions also using 'at').
4873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label done;
4883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
489c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GetNumberHash(reg0, reg1);
4903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute the capacity mask.
492c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  lw(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset));
4933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  sra(reg1, reg1, kSmiTagSize);
4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Subu(reg1, reg1, Operand(1));
4953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Generate an unrolled loop that performs a few probes before giving up.
4973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static const int kProbes = 4;
4983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < kProbes; i++) {
4993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Use reg2 for index calculations and keep the hash intact in reg0.
5003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(reg2, reg0);
5013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
5023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i > 0) {
503c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      Addu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i)));
5043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(reg2, reg2, reg1);
5063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Scale the index by multiplying by the element size.
508c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    ASSERT(SeededNumberDictionary::kEntrySize == 3);
5093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    sll(at, reg2, 1);  // 2x.
5103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    addu(reg2, reg2, at);  // reg2 = reg2 * 3.
5113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check if the key is identical to the name.
5133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    sll(at, reg2, kPointerSizeLog2);
5143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    addu(reg2, elements, at);
5153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
516c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    lw(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset));
5173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i != kProbes - 1) {
5183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Branch(&done, eq, key, Operand(at));
5193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
5203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Branch(miss, ne, key, Operand(at));
5213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
5253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the value is a normal property.
5263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // reg2: elements + (index * kPointerSize).
5273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kDetailsOffset =
528c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
5293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  lw(reg1, FieldMemOperand(reg2, kDetailsOffset));
530589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
5313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Branch(miss, ne, at, Operand(zero_reg));
5323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the value at the masked, scaled index and return.
5343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kValueOffset =
535c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
5363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  lw(result, FieldMemOperand(reg2, kValueOffset));
5373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ---------------------------------------------------------------------------
541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Instruction macros.
5423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
54344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) {
5443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    addu(rd, rs, rt.rm());
5463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      addiu(rd, rs, rt.imm32_);
5493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
5503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
5513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ASSERT(!rs.is(at));
5523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
55344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      addu(rd, rs, at);
5543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
5553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
5563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
55944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) {
5603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
56144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    subu(rd, rs, rt.rm());
5623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
56344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
56444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      addiu(rd, rs, -rt.imm32_);  // No subiu instr, use addiu(x, y, -imm).
5653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
5663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
5673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ASSERT(!rs.is(at));
5683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
56944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      subu(rd, rs, at);
5703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
5713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
5723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) {
5763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (kArchVariant == kLoongson) {
5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mult(rs, rt.rm());
5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mflo(rd);
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mul(rd, rs, rt.rm());
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
5843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
5853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ASSERT(!rs.is(at));
5863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (kArchVariant == kLoongson) {
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mult(rs, at);
5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mflo(rd);
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mul(rd, rs, at);
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
5943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Mult(Register rs, const Operand& rt) {
5983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
5993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    mult(rs, rt.rm());
6003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
6013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
6023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ASSERT(!rs.is(at));
6033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
6043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    mult(rs, at);
6053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
6063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
6073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Multu(Register rs, const Operand& rt) {
6103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
6113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    multu(rs, rt.rm());
6123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
6133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
6143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ASSERT(!rs.is(at));
6153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
6163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    multu(rs, at);
6173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
6183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
6193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Div(Register rs, const Operand& rt) {
6223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
6233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    div(rs, rt.rm());
6243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
6253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
6263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ASSERT(!rs.is(at));
6273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
6283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    div(rs, at);
6293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
6303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
6313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Divu(Register rs, const Operand& rt) {
6343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
6353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    divu(rs, rt.rm());
6363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
6373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
6383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ASSERT(!rs.is(at));
6393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
6403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    divu(rs, at);
6413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
6423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
6433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::And(Register rd, Register rs, const Operand& rt) {
6463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
6473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    and_(rd, rs, rt.rm());
6483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
64944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
6503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      andi(rd, rs, rt.imm32_);
6513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
6523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
6533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ASSERT(!rs.is(at));
6543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
6553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      and_(rd, rs, at);
6563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
6573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
6583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
6593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Or(Register rd, Register rs, const Operand& rt) {
6623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
6633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    or_(rd, rs, rt.rm());
6643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
6663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ori(rd, rs, rt.imm32_);
6673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
6683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
6693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ASSERT(!rs.is(at));
6703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
6713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      or_(rd, rs, at);
6723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
6733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
6743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
6753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) {
6783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
6793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    xor_(rd, rs, rt.rm());
6803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
68144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
6823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      xori(rd, rs, rt.imm32_);
6833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
6843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
6853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ASSERT(!rs.is(at));
6863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
6873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      xor_(rd, rs, at);
6883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
6893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
6903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
6913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Nor(Register rd, Register rs, const Operand& rt) {
6943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
6953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    nor(rd, rs, rt.rm());
6963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
6973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // li handles the relocation.
6983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ASSERT(!rs.is(at));
6993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(at, rt);
7003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    nor(rd, rs, at);
7013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
7023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
7033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::Neg(Register rs, const Operand& rt) {
706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(rt.is_reg());
707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!at.is(rs));
708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!at.is(rt.rm()));
709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  li(at, -1);
710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  xor_(rs, rt.rm(), at);
711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) {
7153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
7163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    slt(rd, rs, rt.rm());
7173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
71844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
7193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slti(rd, rs, rt.imm32_);
7203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
7213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
7223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ASSERT(!rs.is(at));
7233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
7243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slt(rd, rs, at);
7253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
7263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
7273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
7283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) {
7313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
7323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    sltu(rd, rs, rt.rm());
7333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
73444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
7353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltiu(rd, rs, rt.imm32_);
7363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
7373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // li handles the relocation.
7383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ASSERT(!rs.is(at));
7393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      li(at, rt);
7403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltu(rd, rs, at);
7413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
7423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
7433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
7443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
74644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) {
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kMips32r2) {
74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (rt.is_reg()) {
74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      rotrv(rd, rs, rt.rm());
75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      rotr(rd, rs, rt.imm32_);
75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (rt.is_reg()) {
75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      subu(at, zero_reg, rt.rm());
75644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sllv(at, rs, at);
75744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      srlv(rd, rs, rt.rm());
75844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      or_(rd, rd, at);
75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
76044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (rt.imm32_ == 0) {
76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        srl(rd, rs, 0);
76244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else {
76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        srl(at, rs, rt.imm32_);
76444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        sll(rd, rs, (0x20 - rt.imm32_) & 0x1f);
76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        or_(rd, rd, at);
76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
76744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
76844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
7693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
7703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block//------------Pseudo-instructions-------------
77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::li(Register rd, Operand j, LiFlags mode) {
7743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(!j.is_reg());
77544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) {
7773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Normal load of an immediate value which does not need Relocation Info.
7783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if (is_int16(j.imm32_)) {
7793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(rd, zero_reg, j.imm32_);
78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (!(j.imm32_ & kHiMask)) {
7813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ori(rd, zero_reg, j.imm32_);
78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (!(j.imm32_ & kImm16Mask)) {
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask);
7843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask);
78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ori(rd, rd, (j.imm32_ & kImm16Mask));
7873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (MustUseReg(j.rmode_)) {
7903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      RecordRelocInfo(j.rmode_, j.imm32_);
7913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We always need the same number of instructions as we may need to patch
7933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // this code to load another value which may need 2 instructions to load.
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask);
795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ori(rd, rd, (j.imm32_ & kImm16Mask));
7963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
7973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
7983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::MultiPush(RegList regs) {
801589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t num_to_push = NumberOfBitsSet(regs);
802589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = num_to_push * kPointerSize;
8033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
804589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Subu(sp, sp, Operand(stack_offset));
8053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
8063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if ((regs & (1 << i)) != 0) {
807589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset -= kPointerSize;
808589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      sw(ToRegister(i), MemOperand(sp, stack_offset));
8093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
8103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
8113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
8123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::MultiPushReversed(RegList regs) {
815589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t num_to_push = NumberOfBitsSet(regs);
816589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = num_to_push * kPointerSize;
8173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
818589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Subu(sp, sp, Operand(stack_offset));
8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int16_t i = 0; i < kNumRegisters; i++) {
8203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if ((regs & (1 << i)) != 0) {
821589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset -= kPointerSize;
822589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      sw(ToRegister(i), MemOperand(sp, stack_offset));
8233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
8243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
8253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
8263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::MultiPop(RegList regs) {
829589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = 0;
8303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int16_t i = 0; i < kNumRegisters; i++) {
8323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if ((regs & (1 << i)) != 0) {
833589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      lw(ToRegister(i), MemOperand(sp, stack_offset));
834589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset += kPointerSize;
8353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
8363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
837589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  addiu(sp, sp, stack_offset);
8383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
8393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::MultiPopReversed(RegList regs) {
842589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = 0;
8433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
8453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if ((regs & (1 << i)) != 0) {
846589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      lw(ToRegister(i), MemOperand(sp, stack_offset));
847589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset += kPointerSize;
8483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
8493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
850589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  addiu(sp, sp, stack_offset);
851589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
852589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
853589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
854589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::MultiPushFPU(RegList regs) {
855589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  CpuFeatures::Scope scope(FPU);
856589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t num_to_push = NumberOfBitsSet(regs);
857589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = num_to_push * kDoubleSize;
858589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
859589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Subu(sp, sp, Operand(stack_offset));
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
861589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if ((regs & (1 << i)) != 0) {
862589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset -= kDoubleSize;
863589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
864589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
865589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
866589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
867589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
868589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
869589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::MultiPushReversedFPU(RegList regs) {
870589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  CpuFeatures::Scope scope(FPU);
871589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t num_to_push = NumberOfBitsSet(regs);
872589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = num_to_push * kDoubleSize;
873589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
874589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Subu(sp, sp, Operand(stack_offset));
875589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (int16_t i = 0; i < kNumRegisters; i++) {
876589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if ((regs & (1 << i)) != 0) {
877589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset -= kDoubleSize;
878589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
879589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
880589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
881589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
882589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
883589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
884589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::MultiPopFPU(RegList regs) {
885589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  CpuFeatures::Scope scope(FPU);
886589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = 0;
887589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
888589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (int16_t i = 0; i < kNumRegisters; i++) {
889589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if ((regs & (1 << i)) != 0) {
890589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
891589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset += kDoubleSize;
892589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
894589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  addiu(sp, sp, stack_offset);
895589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
896589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
897589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
898589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::MultiPopReversedFPU(RegList regs) {
899589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  CpuFeatures::Scope scope(FPU);
900589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int16_t stack_offset = 0;
901589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
903589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if ((regs & (1 << i)) != 0) {
904589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
905589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      stack_offset += kDoubleSize;
906589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
907589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
908589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  addiu(sp, sp, stack_offset);
9093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::FlushICache(Register address, unsigned instructions) {
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegList saved_regs = kJSCallerSaved | ra.bit();
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MultiPush(saved_regs);
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AllowExternalCallThatCantCauseGC scope(this);
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Save to a0 in case address == t0.
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Move(a0, address);
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCallCFunction(2, t0);
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(a1, instructions * kInstrSize);
9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunction(ExternalReference::flush_icache_function(isolate()), 2);
9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MultiPop(saved_regs);
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
92744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Ext(Register rt,
92844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         Register rs,
92944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         uint16_t pos,
93044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         uint16_t size) {
93144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(pos < 32);
93269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ASSERT(pos + size < 33);
9333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kMips32r2) {
93544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ext_(rt, rs, pos, size);
93644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
93744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Move rs to rt and shift it left then right to get the
93844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // desired bitfield on the right side and zeroes on the left.
93969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int shift_left = 32 - (pos + size);
94069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    sll(rt, rs, shift_left);  // Acts as a move if shift_left == 0.
94169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
94269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int shift_right = 32 - size;
94369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (shift_right > 0) {
94469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      srl(rt, rt, shift_right);
94569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
9463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
94744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
9483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
95044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Ins(Register rt,
95144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         Register rs,
95244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         uint16_t pos,
95344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         uint16_t size) {
95444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(pos < 32);
9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(pos + size <= 32);
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(size != 0);
9573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kMips32r2) {
95944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ins_(rt, rs, pos, size);
96044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
96144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(!rt.is(t8) && !rs.is(t8));
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Subu(at, zero_reg, Operand(1));
9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(at, at, 32 - size);
9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(t8, rs, at);
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sll(t8, t8, pos);
9663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sll(at, at, pos);
9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nor(at, at, zero_reg);
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(at, rt, at);
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    or_(rt, t8, at);
97044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
97144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
9723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
97344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
97469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid MacroAssembler::Cvt_d_uw(FPURegister fd,
97569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              FPURegister fs,
97669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              FPURegister scratch) {
97769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Move the data from fs to t8.
97869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mfc1(t8, fs);
97969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Cvt_d_uw(fd, t8, scratch);
98044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
98244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
98369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid MacroAssembler::Cvt_d_uw(FPURegister fd,
98469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              Register rs,
98569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              FPURegister scratch) {
98644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Convert rs to a FP value in fd (and fd + 1).
98744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We do this by converting rs minus the MSB to avoid sign conversion,
98869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // then adding 2^31 to the result (if needed).
98944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
99069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ASSERT(!fd.is(scratch));
99144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!rs.is(t9));
99269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ASSERT(!rs.is(at));
99344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
99469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Save rs's MSB to t9.
99569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Ext(t9, rs, 31, 1);
99644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Remove rs's MSB.
99769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Ext(at, rs, 0, 31);
99869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Move the result to fd.
99969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mtc1(at, fd);
100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
100144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Convert fd to a real FP value.
100244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cvt_d_w(fd, fd);
100344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
100444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label conversion_done;
100544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
100644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If rs's MSB was 0, it's done.
100744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Otherwise we need to add that to the FP register.
100869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Branch(&conversion_done, eq, t9, Operand(zero_reg));
100944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
101069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Load 2^31 into f20 as its float representation.
101169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  li(at, 0x41E00000);
101269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mtc1(at, FPURegister::from_code(scratch.code() + 1));
101369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mtc1(zero_reg, scratch);
101469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Add it to fd.
101569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  add_d(fd, fd, scratch);
101644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
101744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&conversion_done);
101844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
101944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
102044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
102169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid MacroAssembler::Trunc_uw_d(FPURegister fd,
102269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                FPURegister fs,
102369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                FPURegister scratch) {
102469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Trunc_uw_d(fs, t8, scratch);
102569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mtc1(t8, fd);
102644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
102744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Trunc_w_d(FPURegister fd, FPURegister fs) {
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kLoongson && fd.is(fs)) {
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mfc1(t8, FPURegister::from_code(fs.code() + 1));
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    trunc_w_d(fd, fs);
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mtc1(t8, FPURegister::from_code(fs.code() + 1));
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    trunc_w_d(fd, fs);
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Round_w_d(FPURegister fd, FPURegister fs) {
10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kLoongson && fd.is(fs)) {
10403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mfc1(t8, FPURegister::from_code(fs.code() + 1));
10413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    round_w_d(fd, fs);
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mtc1(t8, FPURegister::from_code(fs.code() + 1));
10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    round_w_d(fd, fs);
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Floor_w_d(FPURegister fd, FPURegister fs) {
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kLoongson && fd.is(fs)) {
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mfc1(t8, FPURegister::from_code(fs.code() + 1));
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    floor_w_d(fd, fs);
10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mtc1(t8, FPURegister::from_code(fs.code() + 1));
10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
10553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    floor_w_d(fd, fs);
10563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
10583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) {
10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kLoongson && fd.is(fs)) {
10623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mfc1(t8, FPURegister::from_code(fs.code() + 1));
10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ceil_w_d(fd, fs);
10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mtc1(t8, FPURegister::from_code(fs.code() + 1));
10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ceil_w_d(fd, fs);
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
107044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
107169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid MacroAssembler::Trunc_uw_d(FPURegister fd,
107269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                Register rs,
107369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                FPURegister scratch) {
107469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ASSERT(!fd.is(scratch));
107569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ASSERT(!rs.is(at));
107644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
107769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Load 2^31 into scratch as its float representation.
107869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  li(at, 0x41E00000);
107969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mtc1(at, FPURegister::from_code(scratch.code() + 1));
108069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mtc1(zero_reg, scratch);
108169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Test if scratch > fd.
108285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // If fd < 2^31 we can convert it normally.
10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label simple_convert;
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BranchF(&simple_convert, NULL, lt, fd, scratch);
108544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
108644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // First we subtract 2^31 from fd, then trunc it to rs
108744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // and add 2^31 to rs.
108869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  sub_d(scratch, fd, scratch);
108969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  trunc_w_d(scratch, scratch);
109069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mfc1(rs, scratch);
109169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Or(rs, rs, 1 << 31);
109244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
109344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done;
109444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&done);
109544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Simple conversion.
109644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&simple_convert);
109769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  trunc_w_d(scratch, fd);
109869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mfc1(rs, scratch);
109944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
110044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
110144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
110244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
110344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::BranchF(Label* target,
11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             Label* nan,
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             Condition cc,
11073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             FPURegister cmp1,
11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             FPURegister cmp2,
11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             BranchDelaySlot bd) {
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cc == al) {
11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(bd, target);
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(nan || target);
11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for unordered (NaN) cases.
11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (nan) {
11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    c(UN, D, cmp1, cmp2);
11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bc1t(nan);
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (target) {
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Here NaN cases were either handled by this function or are assumed to
11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // have been handled by the caller.
11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Unsigned conditions are treated as their signed counterpart.
11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (cc) {
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Uless:
11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case less:
11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        c(OLT, D, cmp1, cmp2);
11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bc1t(target);
11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Ugreater:
11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case greater:
11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        c(ULE, D, cmp1, cmp2);
11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bc1f(target);
11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Ugreater_equal:
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case greater_equal:
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        c(ULT, D, cmp1, cmp2);
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bc1f(target);
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Uless_equal:
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case less_equal:
11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        c(OLE, D, cmp1, cmp2);
11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bc1t(target);
11463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case eq:
11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        c(EQ, D, cmp1, cmp2);
11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bc1t(target);
11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case ne:
11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        c(EQ, D, cmp1, cmp2);
11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bc1f(target);
11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CHECK(0);
11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    };
11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (bd == PROTECT) {
11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nop();
11623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Move(FPURegister dst, double imm) {
11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(CpuFeatures::IsEnabled(FPU));
11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const DoubleRepresentation minus_zero(-0.0);
11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const DoubleRepresentation zero(0.0);
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRepresentation value(imm);
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle special values first.
11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool force_load = dst.is(kDoubleRegZero);
11733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (value.bits == zero.bits && !force_load) {
11743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov_d(dst, kDoubleRegZero);
11753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (value.bits == minus_zero.bits && !force_load) {
11763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    neg_d(dst, kDoubleRegZero);
11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t lo, hi;
11793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoubleAsTwoUInt32(imm, &lo, &hi);
11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Move the low part of the double into the lower of the corresponding FPU
11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // register of FPU register pair.
11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (lo != 0) {
11833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      li(at, Operand(lo));
11843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mtc1(at, dst);
11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
11863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mtc1(zero_reg, dst);
11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Move the high part of the double into the higher of the corresponding FPU
11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // register of FPU register pair.
11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (hi != 0) {
11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      li(at, Operand(hi));
11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mtc1(at, dst.high());
11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mtc1(zero_reg, dst.high());
11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movz(Register rd, Register rs, Register rt) {
12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kLoongson) {
12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, ne, rt, Operand(zero_reg));
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movz(rd, rs, rt);
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movn(Register rd, Register rs, Register rt) {
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kLoongson) {
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, eq, rt, Operand(zero_reg));
12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movn(rd, rs, rt);
12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) {
12253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kLoongson) {
12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tests an FP condition code and then conditionally move rs to rd.
12273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We do not currently use any FPU cc bit other than bit 0.
12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cc == 0);
12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!(rs.is(t8) || rd.is(t8)));
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = t8;
12323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For testing purposes we need to fetch content of the FCSR register and
12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // than test its cc (floating point condition code) bit (for cc = 0, it is
12343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 24. bit of the FCSR).
12353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cfc1(scratch, FCSR);
12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For the MIPS I, II and III architectures, the contents of scratch is
12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // UNPREDICTABLE for the instruction immediately following CFC1.
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nop();
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(scratch, scratch, 16);
12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    andi(scratch, scratch, 0x0080);
12413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, eq, scratch, Operand(zero_reg));
12423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
12433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movt(rd, rs, cc);
12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) {
12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kLoongson) {
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tests an FP condition code and then conditionally move rs to rd.
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We do not currently use any FPU cc bit other than bit 0.
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cc == 0);
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!(rs.is(t8) || rd.is(t8)));
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = t8;
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For testing purposes we need to fetch content of the FCSR register and
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // than test its cc (floating point condition code) bit (for cc = 0, it is
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 24. bit of the FCSR).
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cfc1(scratch, FCSR);
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For the MIPS I, II and III architectures, the contents of scratch is
12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // UNPREDICTABLE for the instruction immediately following CFC1.
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    nop();
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(scratch, scratch, 16);
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    andi(scratch, scratch, 0x0080);
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&done, ne, scratch, Operand(zero_reg));
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, rs);
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movf(rd, rs, cc);
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Clz(Register rd, Register rs) {
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kArchVariant == kLoongson) {
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!(rd.is(t8) || rd.is(t9)) && !(rs.is(t8) || rs.is(t9)));
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register mask = t8;
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = t9;
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label loop, end;
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(at, rs);
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(rd, zero_reg);
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lui(mask, 0x8000);
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&loop);
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, at, mask);
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&end, ne, scratch, Operand(zero_reg));
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    addiu(rd, rd, 1);
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&loop, ne, mask, Operand(zero_reg), USE_DELAY_SLOT);
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(mask, mask, 1);
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&end);
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    clz(rd, rs);
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
129844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Tries to get a signed int32 out of a double precision floating point heap
129944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// number. Rounds towards 0. Branch to 'not_int32' if the double is out of the
130044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// 32bits signed integer range.
130144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// This method implementation differs from the ARM version for performance
130244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// reasons.
130344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::ConvertToInt32(Register source,
130444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Register dest,
130544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Register scratch,
130644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Register scratch2,
130744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    FPURegister double_scratch,
130844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Label *not_int32) {
130944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label right_exponent, done;
131044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get exponent word (ENDIAN issues).
131144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset));
131244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get exponent alone in scratch2.
131344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch2, scratch, Operand(HeapNumber::kExponentMask));
131444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load dest with zero.  We use this either for the final shift or
131544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // for the answer.
131644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(dest, zero_reg);
131744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check whether the exponent matches a 32 bit signed int that is not a Smi.
131844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased).  This is
131944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the exponent that we are fastest at and also the highest exponent we can
132044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // handle here.
132144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const uint32_t non_smi_exponent =
132244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
132344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If we have a match of the int32-but-not-Smi exponent then skip some logic.
132444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&right_exponent, eq, scratch2, Operand(non_smi_exponent));
132544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the exponent is higher than that then go to not_int32 case.  This
132644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // catches numbers that don't fit in a signed int32, infinities and NaNs.
132744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(not_int32, gt, scratch2, Operand(non_smi_exponent));
132844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
132944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We know the exponent is smaller than 30 (biased).  If it is less than
13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, i.e.
133144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // it rounds to zero.
133244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const uint32_t zero_exponent =
133344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift;
133444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Subu(scratch2, scratch2, Operand(zero_exponent));
133544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Dest already has a Smi zero.
133644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&done, lt, scratch2, Operand(zero_reg));
1337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!CpuFeatures::IsSupported(FPU)) {
133844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // We have a shifted exponent between 0 and 30 in scratch2.
133944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    srl(dest, scratch2, HeapNumber::kExponentShift);
134044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // We now have the exponent in dest.  Subtract from 30 to get
134144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // how much to shift down.
134244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(at, Operand(30));
134344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    subu(dest, at, dest);
13443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&right_exponent);
1346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (CpuFeatures::IsSupported(FPU)) {
134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CpuFeatures::Scope scope(FPU);
134844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // MIPS FPU instructions implementing double precision to integer
134944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // conversion using round to zero. Since the FP value was qualified
135044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // above, the resulting integer should be a legal int32.
135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The original 'Exponent' word is still in scratch.
135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lwc1(double_scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset));
135344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mtc1(scratch, FPURegister::from_code(double_scratch.code() + 1));
135444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    trunc_w_d(double_scratch, double_scratch);
135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mfc1(dest, double_scratch);
135644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // On entry, dest has final downshift, scratch has original sign/exp/mant.
135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Save sign bit in top bit of dest.
135944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    And(scratch2, scratch, Operand(0x80000000));
136044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Or(dest, dest, Operand(scratch2));
136144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Put back the implicit 1, just above mantissa field.
136244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Or(scratch, scratch, Operand(1 << HeapNumber::kExponentShift));
136344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
136444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Shift up the mantissa bits to take up the space the exponent used to
136544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // take. We just orred in the implicit bit so that took care of one and
136644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // we want to leave the sign bit 0 so we subtract 2 bits from the shift
136744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // distance. But we want to clear the sign-bit so shift one more bit
136844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // left, then shift right one bit.
136944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sll(scratch, scratch, shift_distance + 1);
137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    srl(scratch, scratch, 1);
137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
137344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Get the second half of the double. For some exponents we don't
137444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // actually need this because the bits get shifted out again, but
137544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // it's probably slower to test than just to do it.
137644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(scratch2, FieldMemOperand(source, HeapNumber::kMantissaOffset));
137744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Extract the top 10 bits, and insert those bottom 10 bits of scratch.
137844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The width of the field here is the same as the shift amount above.
137944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const int field_width = shift_distance;
138044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Ext(scratch2, scratch2, 32-shift_distance, field_width);
138144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Ins(scratch, scratch2, 0, field_width);
138244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Move down according to the exponent.
138344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    srlv(scratch, scratch, dest);
138444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Prepare the negative version of our integer.
138544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    subu(scratch2, zero_reg, scratch);
138644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Trick to check sign bit (msb) held in dest, count leading zero.
138744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // 0 indicates negative, save negative version with conditional move.
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Clz(dest, dest);
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Movz(scratch, scratch2, dest);
139044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(dest, scratch);
139144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
139244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
139344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
139444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
139544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
13973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     FPURegister result,
13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     DoubleRegister double_input,
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register scratch1,
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register except_flag,
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     CheckForInexactConversion check_inexact) {
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(CpuFeatures::IsSupported(FPU));
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CpuFeatures::Scope scope(FPU);
14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int32_t except_mask = kFCSRFlagMask;  // Assume interested in all exceptions.
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (check_inexact == kDontCheckForInexactConversion) {
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Ingore inexact exceptions.
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    except_mask &= ~kFCSRInexactFlagMask;
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Save FCSR.
14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cfc1(scratch1, FCSR);
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable FPU exceptions.
14153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctc1(zero_reg, FCSR);
14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do operation based on rounding mode.
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (rounding_mode) {
14193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToNearest:
14203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Round_w_d(result, double_input);
14213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToZero:
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Trunc_w_d(result, double_input);
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToPlusInf:
14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Ceil_w_d(result, double_input);
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kRoundToMinusInf:
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Floor_w_d(result, double_input);
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }  // End of switch-statement.
14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Retrieve FCSR.
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cfc1(except_flag, FCSR);
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore FCSR.
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctc1(scratch1, FCSR);
14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for fpu exceptions.
14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(except_flag, except_flag, Operand(except_mask));
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::EmitOutOfInt32RangeTruncate(Register result,
1444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                 Register input_high,
1445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                 Register input_low,
1446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                 Register scratch) {
1447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done, normal_exponent, restore_sign;
1448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Extract the biased exponent in result.
1449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Ext(result,
1450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      input_high,
1451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HeapNumber::kExponentShift,
1452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HeapNumber::kExponentBits);
1453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for Infinity and NaNs, which should return 0.
1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(scratch, result, HeapNumber::kExponentMask);
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Movz(result, zero_reg, scratch);
1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&done, eq, scratch, Operand(zero_reg));
1458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Express exponent as delta to (number of mantissa bits + 31).
1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(result,
1461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       result,
1462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31));
1463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If the delta is strictly positive, all bits would be shifted away,
1465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // which means that we can return 0.
1466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&normal_exponent, le, result, Operand(zero_reg));
1467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(result, zero_reg);
1468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&done);
1469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&normal_exponent);
1471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Calculate shift.
1473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Addu(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits));
1474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Save the sign.
1476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register sign = result;
1477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  result = no_reg;
1478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  And(sign, input_high, Operand(HeapNumber::kSignMask));
1479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // On ARM shifts > 31 bits are valid and will result in zero. On MIPS we need
1481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // to check for this specific case.
1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label high_shift_needed, high_shift_done;
1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&high_shift_needed, lt, scratch, Operand(32));
1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(input_high, zero_reg);
1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&high_shift_done);
1486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&high_shift_needed);
1487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Set the implicit 1 before the mantissa part in input_high.
1489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Or(input_high,
1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     input_high,
1491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     Operand(1 << HeapNumber::kMantissaBitsInTopWord));
1492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Shift the mantissa bits to the correct position.
1493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We don't need to clear non-mantissa bits as they will be shifted away.
1494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If they weren't, it would mean that the answer is in the 32bit range.
1495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sllv(input_high, input_high, scratch);
1496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&high_shift_done);
1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Replace the shifted bits with bits from the lower mantissa word.
1500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label pos_shift, shift_done;
1501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  li(at, 32);
1502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  subu(scratch, at, scratch);
1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&pos_shift, ge, scratch, Operand(zero_reg));
1504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Negate scratch.
1506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(scratch, zero_reg, scratch);
1507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sllv(input_low, input_low, scratch);
1508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&shift_done);
1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&pos_shift);
1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  srlv(input_low, input_low, scratch);
1512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&shift_done);
1514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Or(input_high, input_high, Operand(input_low));
1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore sign if necessary.
1516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(scratch, sign);
1517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  result = sign;
1518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sign = no_reg;
1519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(result, zero_reg, input_high);
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Movz(result, input_high, scratch);
1521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
1522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
15253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::EmitECMATruncate(Register result,
15263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                      FPURegister double_input,
15273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                      FPURegister single_scratch,
15283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                      Register scratch,
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register scratch2,
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register scratch3) {
15313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CpuFeatures::Scope scope(FPU);
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!scratch2.is(result));
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!scratch3.is(result));
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!scratch3.is(scratch2));
15353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!scratch.is(result) &&
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         !scratch.is(scratch2) &&
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         !scratch.is(scratch3));
15383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!single_scratch.is(double_input));
15393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
15403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label done;
15413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label manual;
15423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
15433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Clear cumulative exception flags and save the FCSR.
15443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cfc1(scratch2, FCSR);
15453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ctc1(zero_reg, FCSR);
15463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Try a conversion to a signed integer.
15473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  trunc_w_d(single_scratch, double_input);
15483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  mfc1(result, single_scratch);
15493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Retrieve and restore the FCSR.
15503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cfc1(scratch, FCSR);
15513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ctc1(scratch2, FCSR);
15523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check for overflow and NaNs.
15533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  And(scratch,
15543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      scratch,
15553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask);
15563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If we had no exceptions we are done.
15573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Branch(&done, eq, scratch, Operand(zero_reg));
15583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
15593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load the double value and perform a manual truncation.
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_high = scratch2;
15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_low = scratch3;
15623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Move(input_low, input_high, double_input);
15633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  EmitOutOfInt32RangeTruncate(result,
15643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              input_high,
15653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              input_low,
15663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              scratch);
15673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
15683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
15693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
15703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::GetLeastBitsFromSmi(Register dst,
1572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                         Register src,
1573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                         int num_least_bits) {
1574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Ext(dst, src, kSmiTagSize, num_least_bits);
1575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::GetLeastBitsFromInt32(Register dst,
1579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           Register src,
1580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           int num_least_bits) {
1581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  And(dst, src, Operand((1 << num_least_bits) - 1));
1582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
158544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Emulated condtional branches do not emit a nop in the branch delay slot.
158644f0eee88ff00398ff7f715fab053374d808c90dSteve Block//
158744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// BRANCH_ARGS_CHECK checks that conditional jump arguments are correct.
158844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT(                                \
158944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) ||          \
159044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg))))
159144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
159244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
159344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) {
15943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BranchShort(offset, bdslot);
15953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
15963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
15973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
15983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Branch(int16_t offset, Condition cond, Register rs,
15993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                            const Operand& rt,
16003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                            BranchDelaySlot bdslot) {
16013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BranchShort(offset, cond, rs, rt, bdslot);
16023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
16033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) {
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_near(L)) {
16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(L, bdslot);
16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jr(L, bdslot);
16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
16123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jr(L, bdslot);
16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(L, bdslot);
16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
16183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
16193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
16203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Branch(Label* L, Condition cond, Register rs,
16233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                            const Operand& rt,
16243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                            BranchDelaySlot bdslot) {
16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_near(L)) {
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(L, cond, rs, rt, bdslot);
16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label skip;
16303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Condition neg_cond = NegateCondition(cond);
16313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(&skip, neg_cond, rs, rt);
16323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jr(L, bdslot);
16333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bind(&skip);
16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
16353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label skip;
16383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Condition neg_cond = NegateCondition(cond);
16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(&skip, neg_cond, rs, rt);
16403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jr(L, bdslot);
16413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bind(&skip);
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(L, cond, rs, rt, bdslot);
16443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
16453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
16463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
16473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Branch(Label* L,
16503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Condition cond,
16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Register rs,
16523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Heap::RootListIndex index,
16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            BranchDelaySlot bdslot) {
16543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(at, index);
16553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(L, cond, rs, Operand(at), bdslot);
16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchShort(int16_t offset, BranchDelaySlot bdslot) {
166044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(offset);
166144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
166244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
166344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
166444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
16653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs,
16693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 const Operand& rt,
16703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 BranchDelaySlot bdslot) {
167144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BRANCH_ARGS_CHECK(cond, rs, rt);
167244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!rs.is(zero_reg));
16736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register r2 = no_reg;
167444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register scratch = at;
167544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
16763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
16773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or
16783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rt.
16793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    r2 = rt.rm_;
168044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    switch (cond) {
168144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case cc_always:
168244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        b(offset);
168344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
168444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case eq:
168544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        beq(rs, r2, offset);
168644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
168744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case ne:
168844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        bne(rs, r2, offset);
168944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
1690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Signed comparison.
169144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater:
169244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
169344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgtz(rs, offset);
169444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
169544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, r2, rs);
169644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
169744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
169844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
169944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater_equal:
170044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
170144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgez(rs, offset);
170244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
170344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, rs, r2);
170444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
170544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
170644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
170744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less:
170844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
170944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bltz(rs, offset);
171044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
171144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, rs, r2);
171244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
171344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
171444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
171544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less_equal:
171644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
171744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          blez(rs, offset);
171844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
171944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, r2, rs);
172044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
172144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
172244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
172344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Unsigned comparison.
172444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater:
172544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
172644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgtz(rs, offset);
172744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
172844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, r2, rs);
172944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
173044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
173144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
173244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater_equal:
173344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
173444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgez(rs, offset);
173544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
173644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, rs, r2);
173744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
173844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
173944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
174044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless:
174144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
17423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          // No code needs to be emitted.
17433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          return;
174444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
174544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, rs, r2);
174644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
174744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
174844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
174944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless_equal:
175044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
175144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          b(offset);
175244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
175344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, r2, rs);
175444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
175544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
175644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
175744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      default:
175844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        UNREACHABLE();
175944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
176044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
176144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Be careful to always use shifted_branch_offset only just before the
176244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // branch instruction, as the location will be remember for patching the
176344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // target.
176444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    switch (cond) {
176544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case cc_always:
176644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        b(offset);
176744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
176844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case eq:
176944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // We don't want any other register but scratch clobbered.
177044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ASSERT(!scratch.is(rs));
177144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        r2 = scratch;
177244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        li(r2, rt);
177344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        beq(rs, r2, offset);
177444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
177544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case ne:
177644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // We don't want any other register but scratch clobbered.
177744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ASSERT(!scratch.is(rs));
177844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        r2 = scratch;
177944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        li(r2, rt);
178044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        bne(rs, r2, offset);
178144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Signed comparison.
178344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater:
178444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
178544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgtz(rs, offset);
178644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
178744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
178844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
178944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, r2, rs);
179044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
179144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
179244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
179344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater_equal:
179444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
179544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgez(rs, offset);
179644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else if (is_int16(rt.imm32_)) {
179744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slti(scratch, rs, rt.imm32_);
179844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
179944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
180044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
180144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
18023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          slt(scratch, rs, r2);
180344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
180444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
180544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
180644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less:
180744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
180844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bltz(rs, offset);
180944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else if (is_int16(rt.imm32_)) {
181044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slti(scratch, rs, rt.imm32_);
181144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
181244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
181344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
181444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
181544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, rs, r2);
181644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
181744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
181844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
181944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less_equal:
182044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
182144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          blez(rs, offset);
182244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
182344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
182444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
182544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, r2, rs);
182644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
182744f0eee88ff00398ff7f715fab053374d808c90dSteve Block       }
182844f0eee88ff00398ff7f715fab053374d808c90dSteve Block       break;
182944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Unsigned comparison.
183044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater:
183144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
183244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgtz(rs, offset);
183344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
183444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
183544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
183644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, r2, rs);
183744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
183844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
183944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
184044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater_equal:
184144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
184244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgez(rs, offset);
184344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else if (is_int16(rt.imm32_)) {
184444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltiu(scratch, rs, rt.imm32_);
184544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
184644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
184744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
184844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
184944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, rs, r2);
185044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
185144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
185244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
185344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless:
185444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
18553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          // No code needs to be emitted.
18563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          return;
185744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else if (is_int16(rt.imm32_)) {
185844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltiu(scratch, rs, rt.imm32_);
185944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
186044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
186144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
186244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
186344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, rs, r2);
186444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
186544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
186644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
186744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless_equal:
186844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
186944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          b(offset);
187044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
187144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
187244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
187344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, r2, rs);
187444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
187544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
187644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
187744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      default:
187844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        UNREACHABLE();
187944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
18803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
188144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
188244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
188344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
188444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
188544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
18863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) {
18883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // We use branch_offset as an argument for the branch instructions to be sure
18893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // it is called just before generating the branch instruction, as needed.
18903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
189144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(shifted_branch_offset(L, false));
18923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
189344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
189444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
189544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
189644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
18973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
19003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 const Operand& rt,
19013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 BranchDelaySlot bdslot) {
190244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BRANCH_ARGS_CHECK(cond, rs, rt);
190344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
190444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int32_t offset;
190544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register r2 = no_reg;
190644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register scratch = at;
190744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (rt.is_reg()) {
190844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    r2 = rt.rm_;
190944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Be careful to always use shifted_branch_offset only just before the
191044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // branch instruction, as the location will be remember for patching the
191144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // target.
191244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    switch (cond) {
191344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case cc_always:
191444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        offset = shifted_branch_offset(L, false);
191544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        b(offset);
191644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
191744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case eq:
191844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        offset = shifted_branch_offset(L, false);
191944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        beq(rs, r2, offset);
192044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
192144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case ne:
192244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        offset = shifted_branch_offset(L, false);
192344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        bne(rs, r2, offset);
192444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
1925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Signed comparison.
192644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater:
192744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
192844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
192944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgtz(rs, offset);
193044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
193144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, r2, rs);
193244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
193344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
193444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
193544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
193644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater_equal:
193744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
193844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
193944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgez(rs, offset);
194044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
194144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, rs, r2);
194244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
194344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
194444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
194544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
194644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less:
194744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
194844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
194944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bltz(rs, offset);
195044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
195144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, rs, r2);
195244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
195344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
195444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
195544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
195644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less_equal:
195744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
195844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
195944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          blez(rs, offset);
196044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
196144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, r2, rs);
196244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
196344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
196444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
196544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
196644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Unsigned comparison.
196744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater:
196844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
196944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
197044f0eee88ff00398ff7f715fab053374d808c90dSteve Block           bgtz(rs, offset);
197144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
197244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, r2, rs);
197344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
197444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
197544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
197644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
197744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater_equal:
197844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
197944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
198044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgez(rs, offset);
198144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
198244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, rs, r2);
198344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
198444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
198544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
198644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
198744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless:
198844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
19893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          // No code needs to be emitted.
19903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          return;
199144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
199244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, rs, r2);
199344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
199444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
199544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
199644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
199744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless_equal:
199844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (r2.is(zero_reg)) {
199944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
200044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          b(offset);
200144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
200244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, r2, rs);
200344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
200444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
200544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
200644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
200744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      default:
200844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        UNREACHABLE();
200944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
201044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
201144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Be careful to always use shifted_branch_offset only just before the
201244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // branch instruction, as the location will be remember for patching the
201344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // target.
201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    switch (cond) {
201544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case cc_always:
201644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        offset = shifted_branch_offset(L, false);
201744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        b(offset);
201844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
201944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case eq:
202069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ASSERT(!scratch.is(rs));
202144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        r2 = scratch;
202244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        li(r2, rt);
202344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        offset = shifted_branch_offset(L, false);
202444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        beq(rs, r2, offset);
202544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
202644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case ne:
202769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ASSERT(!scratch.is(rs));
202844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        r2 = scratch;
202944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        li(r2, rt);
203044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        offset = shifted_branch_offset(L, false);
203144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        bne(rs, r2, offset);
203244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
2033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Signed comparison.
203444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater:
203544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
203644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
203744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgtz(rs, offset);
203844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
203969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ASSERT(!scratch.is(rs));
204044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
204144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
204244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, r2, rs);
204344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
204444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
204544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
204644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
204744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case greater_equal:
204844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
204944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
205044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgez(rs, offset);
205144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else if (is_int16(rt.imm32_)) {
205244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slti(scratch, rs, rt.imm32_);
205344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
205444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
205544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
205669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ASSERT(!scratch.is(rs));
205744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
205844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
20593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          slt(scratch, rs, r2);
206044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
206244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
206344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
206444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less:
206544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
206644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
206744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bltz(rs, offset);
206844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else if (is_int16(rt.imm32_)) {
206944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slti(scratch, rs, rt.imm32_);
207044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
207144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
207244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
207369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ASSERT(!scratch.is(rs));
207444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
207544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
207644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, rs, r2);
207744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
207844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
207944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
208044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
208144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case less_equal:
208244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
208344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
208444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          blez(rs, offset);
208544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
208669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ASSERT(!scratch.is(rs));
208744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
208844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
208944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          slt(scratch, r2, rs);
209044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
209144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
209244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
209344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
209444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Unsigned comparison.
209544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater:
209644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
209744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
209844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgtz(rs, offset);
209944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
210069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ASSERT(!scratch.is(rs));
210144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
210244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
210344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, r2, rs);
210444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
210544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
210644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
210744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
210844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Ugreater_equal:
210944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
211044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
211144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bgez(rs, offset);
211244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else if (is_int16(rt.imm32_)) {
211344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltiu(scratch, rs, rt.imm32_);
211444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
211544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
211644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
211769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ASSERT(!scratch.is(rs));
211844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
211944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
212044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, rs, r2);
212144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
212244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
212344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
212444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
212544f0eee88ff00398ff7f715fab053374d808c90dSteve Block     case Uless:
212644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
21273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          // No code needs to be emitted.
21283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          return;
212944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else if (is_int16(rt.imm32_)) {
213044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltiu(scratch, rs, rt.imm32_);
213144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
213244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
213344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
213469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ASSERT(!scratch.is(rs));
213544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
213644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
213744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, rs, r2);
213844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
213944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          bne(scratch, zero_reg, offset);
214044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
214144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
214244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Uless_equal:
214344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (rt.imm32_ == 0) {
214444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
214544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          b(offset);
214644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
214769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ASSERT(!scratch.is(rs));
214844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          r2 = scratch;
214944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          li(r2, rt);
215044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sltu(scratch, r2, rs);
215144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          offset = shifted_branch_offset(L, false);
215244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          beq(scratch, zero_reg, offset);
215344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
215444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
215544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      default:
215644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        UNREACHABLE();
215744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
21583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
215944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that offset could actually hold on an int16_t.
216044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(is_int16(offset));
216144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
216244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
216344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
21643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
21653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) {
21683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BranchAndLinkShort(offset, bdslot);
21693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
21703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
21713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
21723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs,
21733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   const Operand& rt,
21743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   BranchDelaySlot bdslot) {
21753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BranchAndLinkShort(offset, cond, rs, rt, bdslot);
21763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
21773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
21783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
21793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) {
21803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
21813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_near(L)) {
21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchAndLinkShort(L, bdslot);
21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jalr(L, bdslot);
21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
21863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
21873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
21883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jalr(L, bdslot);
21893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
21903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchAndLinkShort(L, bdslot);
21913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
21923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
21933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
21943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
21953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
21963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs,
21973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   const Operand& rt,
21983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   BranchDelaySlot bdslot) {
21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (L->is_bound()) {
22003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_near(L)) {
22013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchAndLinkShort(L, cond, rs, rt, bdslot);
22023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
22033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label skip;
22043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Condition neg_cond = NegateCondition(cond);
22053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(&skip, neg_cond, rs, rt);
22063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jalr(L, bdslot);
22073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bind(&skip);
22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
22093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_trampoline_emitted()) {
22113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label skip;
22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Condition neg_cond = NegateCondition(cond);
22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchShort(&skip, neg_cond, rs, rt);
22143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jalr(L, bdslot);
22153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bind(&skip);
22163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
22173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BranchAndLinkShort(L, cond, rs, rt, bdslot);
22183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
22193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
22203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
22213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
22223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
22233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// We need to use a bgezal or bltzal, but they can't be used directly with the
22243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// slt instructions. We could use sub or add instead but we would miss overflow
22253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// cases, so we keep slt and add an intermediate third instruction.
22263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLinkShort(int16_t offset,
22273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        BranchDelaySlot bdslot) {
222844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bal(offset);
222944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
223044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
223144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
223244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
223344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
223444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
223544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond,
22373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        Register rs, const Operand& rt,
22383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        BranchDelaySlot bdslot) {
223944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BRANCH_ARGS_CHECK(cond, rs, rt);
22406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register r2 = no_reg;
224144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register scratch = at;
224244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
22443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    r2 = rt.rm_;
22453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else if (cond != cc_always) {
22463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    r2 = scratch;
22473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(r2, rt);
22483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
22493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  switch (cond) {
22513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case cc_always:
22523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bal(offset);
22533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
22543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case eq:
22553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bne(rs, r2, 2);
22563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      nop();
22573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bal(offset);
22583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
22593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case ne:
22603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      beq(rs, r2, 2);
22613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      nop();
22623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bal(offset);
22633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
22643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Signed comparison.
22663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case greater:
22673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slt(scratch, r2, rs);
22683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
22693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bgezal(scratch, offset);
22703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
22713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case greater_equal:
22723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slt(scratch, rs, r2);
22733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
22743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bltzal(scratch, offset);
22753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
22763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case less:
22773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slt(scratch, rs, r2);
22783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
22793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bgezal(scratch, offset);
22803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
22813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case less_equal:
22823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slt(scratch, r2, rs);
22833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
22843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bltzal(scratch, offset);
22853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
22863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Unsigned comparison.
22883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Ugreater:
22893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltu(scratch, r2, rs);
22903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
22913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bgezal(scratch, offset);
22923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
22933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Ugreater_equal:
22943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltu(scratch, rs, r2);
22953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
22963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bltzal(scratch, offset);
22973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
22983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Uless:
22993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltu(scratch, rs, r2);
23003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
23013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bgezal(scratch, offset);
23023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Uless_equal:
23043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltu(scratch, r2, rs);
23053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
23063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bltzal(scratch, offset);
23073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
23093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    default:
23103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      UNREACHABLE();
23113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
231244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
231344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
231444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
231544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
231644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
231744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
23183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) {
231944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bal(shifted_branch_offset(L, false));
232044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
232144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
232244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
232344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
23243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
23253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
23263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
23273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs,
23283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        const Operand& rt,
23293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        BranchDelaySlot bdslot) {
233044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BRANCH_ARGS_CHECK(cond, rs, rt);
233144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
233244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int32_t offset;
23336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register r2 = no_reg;
233444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register scratch = at;
23353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (rt.is_reg()) {
23363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    r2 = rt.rm_;
23373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else if (cond != cc_always) {
23383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    r2 = scratch;
23393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    li(r2, rt);
23403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
23413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
23423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  switch (cond) {
23433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case cc_always:
234444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
234544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bal(offset);
23463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case eq:
23483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      bne(rs, r2, 2);
23493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      nop();
235044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
235144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bal(offset);
23523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case ne:
23543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      beq(rs, r2, 2);
23553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      nop();
235644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
235744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bal(offset);
23583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Signed comparison.
23613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case greater:
23623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slt(scratch, r2, rs);
23633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
236444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
236544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bgezal(scratch, offset);
23663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case greater_equal:
23683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slt(scratch, rs, r2);
23693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
237044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
237144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bltzal(scratch, offset);
23723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case less:
23743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slt(scratch, rs, r2);
23753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
237644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
237744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bgezal(scratch, offset);
23783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case less_equal:
23803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      slt(scratch, r2, rs);
23813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
238244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
238344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bltzal(scratch, offset);
23843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
23863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Unsigned comparison.
23873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Ugreater:
23883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltu(scratch, r2, rs);
23893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
239044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
239144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bgezal(scratch, offset);
23923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Ugreater_equal:
23943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltu(scratch, rs, r2);
23953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
239644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
239744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bltzal(scratch, offset);
23983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
23993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Uless:
24003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltu(scratch, rs, r2);
24013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
240244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
240344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bgezal(scratch, offset);
24043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
24053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Uless_equal:
24063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      sltu(scratch, r2, rs);
24073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      addiu(scratch, scratch, -1);
240844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      offset = shifted_branch_offset(L, false);
240944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bltzal(scratch, offset);
24103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
24113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
24123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    default:
24133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      UNREACHABLE();
24143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
241544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
241644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that offset could actually hold on an int16_t.
241744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(is_int16(offset));
241844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
241944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
242044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (bdslot == PROTECT)
242144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
242244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
242344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
242444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
24253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(Register target,
24263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
24273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
24283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
24293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
243044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
24313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond == cc_always) {
24323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    jr(target);
243344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
24343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    BRANCH_ARGS_CHECK(cond, rs, rt);
24353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Branch(2, NegateCondition(cond), rs, rt);
24363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    jr(target);
243744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
243844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
24393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (bd == PROTECT)
244044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
24413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
24423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
24433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
24443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(intptr_t target,
24453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
24463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
24473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
24483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
24493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
24503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label skip;
24513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cond != cc_always) {
24523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(USE_DELAY_SLOT, &skip, NegateCondition(cond), rs, rt);
24533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
24543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The first instruction of 'li' may be placed in the delay slot.
24553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is not an issue, t9 is expected to be clobbered anyway.
24563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  li(t9, Operand(target, rmode));
24573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Jump(t9, al, zero_reg, Operand(zero_reg), bd);
24583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&skip);
245944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
246044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
246144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
24623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(Address target,
24633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
24643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
24653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
24663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
24673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
24683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!RelocInfo::IsCodeTarget(rmode));
24693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd);
2470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
24733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jump(Handle<Code> code,
24743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
24753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
24763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
24773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
24783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
24793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(RelocInfo::IsCodeTarget(rmode));
24803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd);
2481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
24843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint MacroAssembler::CallSize(Register target,
24853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Condition cond,
24863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Register rs,
24873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             const Operand& rt,
24883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             BranchDelaySlot bd) {
24893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int size = 0;
24903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
24913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond == cc_always) {
24923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    size += 1;
24933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
24943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    size += 3;
249544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
24963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
24973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (bd == PROTECT)
24983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    size += 1;
24993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return size * kInstrSize;
25013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
25023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
25033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
250444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Note: To call gcc-compiled C code on mips, you must call thru t9.
25053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Call(Register target,
25063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
25073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
25083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
25093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
251044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
25113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label start;
25123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&start);
25133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond == cc_always) {
25143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    jalr(target);
25153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
25163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    BRANCH_ARGS_CHECK(cond, rs, rt);
25173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Branch(2, NegateCondition(cond), rs, rt);
25183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    jalr(target);
25193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
252044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit a nop in the branch delay slot if required.
25213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (bd == PROTECT)
252244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
25233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT_EQ(CallSize(target, cond, rs, rt, bd),
25253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            SizeOfCodeGeneratedSince(&start));
25263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
25273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
25293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint MacroAssembler::CallSize(Address target,
25303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             RelocInfo::Mode rmode,
25313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Condition cond,
25323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Register rs,
25333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             const Operand& rt,
25343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             BranchDelaySlot bd) {
25353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int size = CallSize(t9, cond, rs, rt, bd);
25363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return size + 2 * kInstrSize;
2537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
25403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Call(Address target,
25413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
254244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Condition cond,
25433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
25443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
25453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
25463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
25473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label start;
25483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&start);
25493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int32_t target_int = reinterpret_cast<int32_t>(target);
25503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Must record previous source positions before the
25513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // li() generates a new code target.
25523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  positions_recorder()->WriteRecordedPositions();
25533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t9, Operand(target_int, rmode), CONSTANT_SIZE);
25543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Call(t9, cond, rs, rt, bd);
25553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT_EQ(CallSize(target, rmode, cond, rs, rt, bd),
25563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            SizeOfCodeGeneratedSince(&start));
25573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
25583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint MacroAssembler::CallSize(Handle<Code> code,
25613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             RelocInfo::Mode rmode,
25623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             unsigned ast_id,
25633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Condition cond,
25643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             Register rs,
25653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             const Operand& rt,
25663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             BranchDelaySlot bd) {
25673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return CallSize(reinterpret_cast<Address>(code.location()),
25683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      rmode, cond, rs, rt, bd);
25693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
25703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Call(Handle<Code> code,
25733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          RelocInfo::Mode rmode,
25743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          unsigned ast_id,
25753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
25763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register rs,
25773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
25783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bd) {
25793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
25803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label start;
25813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&start);
25823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(RelocInfo::IsCodeTarget(rmode));
25833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (rmode == RelocInfo::CODE_TARGET && ast_id != kNoASTId) {
25843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SetRecordedAstId(ast_id);
25853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    rmode = RelocInfo::CODE_TARGET_WITH_ID;
258644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
25873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd);
25883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(CallSize(code, rmode, ast_id, cond, rs, rt, bd),
25893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            SizeOfCodeGeneratedSince(&start));
25903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
259144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
259244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
25933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Ret(Condition cond,
25943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         Register rs,
25953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         const Operand& rt,
25963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         BranchDelaySlot bd) {
25973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Jump(ra, cond, rs, rt, bd);
25983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
25993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::J(Label* L, BranchDelaySlot bdslot) {
26023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
26033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t imm28;
26053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  imm28 = jump_address(L);
26063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  imm28 &= kImm28Mask;
26073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  { BlockGrowBufferScope block_buf_growth(this);
26083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Buffer growth (and relocation) must be blocked for internal references
26093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // until associated instructions are emitted and available to be patched.
26103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
26113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(imm28);
261244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
26133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Emit a nop in the branch delay slot if required.
26143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (bdslot == PROTECT)
26153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    nop();
26163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
261744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
26183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jr(Label* L, BranchDelaySlot bdslot) {
26203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
26213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t imm32;
26233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  imm32 = jump_address(L);
26243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  { BlockGrowBufferScope block_buf_growth(this);
26253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Buffer growth (and relocation) must be blocked for internal references
26263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // until associated instructions are emitted and available to be patched.
26273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
26283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lui(at, (imm32 & kHiMask) >> kLuiShift);
26293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ori(at, at, (imm32 & kImm16Mask));
263044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
26313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  jr(at);
263244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
26333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Emit a nop in the branch delay slot if required.
26343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (bdslot == PROTECT)
26353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    nop();
26363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
26373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Jalr(Label* L, BranchDelaySlot bdslot) {
26403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
26413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t imm32;
26433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  imm32 = jump_address(L);
26443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  { BlockGrowBufferScope block_buf_growth(this);
26453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Buffer growth (and relocation) must be blocked for internal references
26463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // until associated instructions are emitted and available to be patched.
26473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
26483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lui(at, (imm32 & kHiMask) >> kLuiShift);
26493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ori(at, at, (imm32 & kImm16Mask));
265044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
26513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  jalr(at);
26523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Emit a nop in the branch delay slot if required.
26543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (bdslot == PROTECT)
26553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    nop();
26563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
26573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::DropAndRet(int drop) {
26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ret(USE_DELAY_SLOT);
26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addiu(sp, sp, drop * kPointerSize);
26613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
266344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::DropAndRet(int drop,
266444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Condition cond,
266544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Register r1,
266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                const Operand& r2) {
26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Both Drop and Ret need to be conditional.
266844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label skip;
266944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (cond != cc_always) {
267044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&skip, NegateCondition(cond), r1, r2);
267144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
267244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
267344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Drop(drop);
267444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Ret();
267544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
267644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (cond != cc_always) {
267744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&skip);
267844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
267944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
268044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
268144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
26823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Drop(int count,
26833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Condition cond,
26843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register reg,
26853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& op) {
26863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (count <= 0) {
26873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return;
26883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
26893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label skip;
26913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond != al) {
26933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch     Branch(&skip, NegateCondition(cond), reg, op);
26943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
26953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  addiu(sp, sp, count * kPointerSize);
26973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (cond != al) {
26993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bind(&skip);
27003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
27013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
27023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
270544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Swap(Register reg1,
270644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register reg2,
270744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register scratch) {
270844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (scratch.is(no_reg)) {
270944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Xor(reg1, reg1, Operand(reg2));
271044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Xor(reg2, reg2, Operand(reg1));
271144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Xor(reg1, reg1, Operand(reg2));
271244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
271344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(scratch, reg1);
271444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(reg1, reg2);
271544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(reg2, scratch);
271644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
27173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
27183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Call(Label* target) {
272144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BranchAndLink(target);
272244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
272344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
272444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
27253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::Push(Handle<Object> handle) {
27263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  li(at, Operand(handle));
27273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  push(at);
27283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
27293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
27316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
27326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
273344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::DebugBreak() {
27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryArgs(0);
27353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(ExternalReference(Runtime::kDebugBreak, isolate()));
273644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CEntryStub ces(1);
27373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(AllowThisStubCall(&ces));
273844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
273944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
274044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
274144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif  // ENABLE_DEBUGGER_SUPPORT
27426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ---------------------------------------------------------------------------
2745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Exception handling.
27463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushTryHandler(StackHandler::Kind kind,
27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int handler_index) {
27496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Adjust this code if not the case.
275069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
275169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For the JSEntry handler, we must preserve a0-a3 and s0.
27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // t1-t3 are available. We will build up the handler from the bottom by
27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // pushing on the stack.
27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the code object (t1) and the state (t2) for pushing.
27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned state =
27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StackHandler::IndexField::encode(handler_index) |
27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StackHandler::KindField::encode(kind);
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t1, Operand(CodeObject()), CONSTANT_SIZE);
27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t2, Operand(state));
27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the frame pointer, context, state, and code object.
27683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kind == StackHandler::JS_ENTRY) {
27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT_EQ(Smi::FromInt(0), 0);
27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The second zero_reg indicates no context.
27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The first zero_reg is the NULL frame pointer.
27723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The operands are reversed to match the order of MultiPush/Pop.
27733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Push(zero_reg, zero_reg, t2, t1);
27745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  } else {
27753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MultiPush(t1.bit() | t2.bit() | cp.bit() | fp.bit());
277685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
27793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
27803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t1, MemOperand(t2));
27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(t1);
27823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
27833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(sp, MemOperand(t2));
27843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
27853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::PopTryHandler() {
278869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
278944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pop(a1);
279044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
2791589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(at, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
279244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(a1, MemOperand(at));
279344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
279444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
279544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
27963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpToHandlerEntry() {
27973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compute the handler entry address and jump to it.  The handler table is
27983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a fixed array of (smi-tagged) code offsets.
27993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // v0 = exception, a1 = code object, a2 = state.
28003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(a3, FieldMemOperand(a1, Code::kHandlerTableOffset));  // Handler table.
28013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
28023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  srl(a2, a2, StackHandler::kKindWidth);  // Handler index.
28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sll(a2, a2, kPointerSizeLog2);
28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(a2, a3, a2);
28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(a2, MemOperand(a2));  // Smi-tagged offset.
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));  // Code start.
28073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sra(t9, a2, kSmiTagSize);
28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(t9, t9, a1);
28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Jump(t9);  // Jump.
28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
281285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::Throw(Register value) {
2814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Adjust this code if not the case.
281569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
28163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
28203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
28213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The exception is expected in v0.
28233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Move(v0, value);
2824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
28253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Drop the stack pointer to the top of the top handler.
2826589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(a3, Operand(ExternalReference(Isolate::kHandlerAddress,
282769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   isolate())));
2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(sp, MemOperand(a3));
2829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
283069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Restore the next handler.
2831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  pop(a2);
2832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(a2, MemOperand(a3));
2833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
28343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the code object (a1) and state (a2).  Restore the context and frame
28353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // pointer.
28363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit());
283769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
283869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // If the handler is a JS frame, restore the context to the frame.
28393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
28403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // or cp.
2841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
28423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done, eq, cp, Operand(zero_reg));
284369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
2845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
28463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpToHandlerEntry();
2847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
28503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ThrowUncatchable(Register value) {
2851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Adjust this code if not the case.
285269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
285369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
28543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
28553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
28563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
28573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
28583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The exception is expected in v0.
28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!value.is(v0)) {
28613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(v0, value);
28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Drop the stack pointer to the top of the top stack handler.
2864592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
2865592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  lw(sp, MemOperand(a3));
2866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2867592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Unwind the handlers until the ENTRY handler is found.
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label fetch_next, check_kind;
28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&check_kind);
28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&fetch_next);
28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&check_kind);
28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(a2, MemOperand(sp, StackHandlerConstants::kStateOffset));
28763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(a2, a2, Operand(StackHandler::KindField::kMask));
28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&fetch_next, ne, a2, Operand(zero_reg));
28783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set the top handler address to next handler past the top ENTRY handler.
2880592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  pop(a2);
2881592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  sw(a2, MemOperand(a3));
2882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
28833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the code object (a1) and state (a2).  Clear the context and frame
28843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // pointer (0 was saved in the handler).
28853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit());
2886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpToHandlerEntry();
2888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
289144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size,
289244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register result,
289344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch1,
289444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch2,
289544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Label* gc_required,
289644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        AllocationFlags flags) {
289744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!FLAG_inline_new) {
2898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
289944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Trash the registers to simulate an allocation failure.
290044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(result, 0x7091);
290144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(scratch1, 0x7191);
290244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(scratch2, 0x7291);
290344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
290444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    jmp(gc_required);
290544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return;
290644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
290744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
290844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!result.is(scratch1));
290944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!result.is(scratch2));
291044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!scratch1.is(scratch2));
291144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!scratch1.is(t9));
291244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!scratch2.is(t9));
291344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!result.is(t9));
291444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
291544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make object size into bytes.
291644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & SIZE_IN_WORDS) != 0) {
291744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    object_size *= kPointerSize;
291844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
291944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT_EQ(0, object_size & kObjectAlignmentMask);
292044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
292144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check relative positions of allocation top and limit addresses.
292244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // ARM adds additional checks to make sure the ldm instruction can be
292344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // used. On MIPS we don't have ldm so we don't need additional checks either.
292444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference new_space_allocation_top =
292544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
292644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference new_space_allocation_limit =
292744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
292844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t top   =
292944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      reinterpret_cast<intptr_t>(new_space_allocation_top.address());
293044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t limit =
293144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
293244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT((limit - top) == kPointerSize);
293344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
293444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Set up allocation top address and object size registers.
293544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register topaddr = scratch1;
293644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register obj_size_reg = scratch2;
293744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  li(topaddr, Operand(new_space_allocation_top));
293844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  li(obj_size_reg, Operand(object_size));
293944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
294044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // This code stores a temporary value in t9.
294144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & RESULT_CONTAINS_TOP) == 0) {
294244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Load allocation top into result and allocation limit into t9.
294344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(result, MemOperand(topaddr));
294444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(t9, MemOperand(topaddr, kPointerSize));
294544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
2946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
294744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Assert that result actually contains top on entry. t9 is used
294844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // immediately below so this use of t9 does not cause difference with
294944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // respect to register content between debug and release mode.
295044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      lw(t9, MemOperand(topaddr));
295144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Check(eq, "Unexpected allocation top", result, Operand(t9));
295244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
295344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Load allocation limit into t9. Result already contains allocation top.
295444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(t9, MemOperand(topaddr, limit - top));
295544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
295644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
295744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate new top and bail out if new space is exhausted. Use result
295844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to calculate the new top.
295944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Addu(scratch2, result, Operand(obj_size_reg));
296044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(gc_required, Ugreater, scratch2, Operand(t9));
296144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(scratch2, MemOperand(topaddr));
296244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
296344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Tag object if requested.
296444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & TAG_OBJECT) != 0) {
296544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(result, result, Operand(kHeapObjectTag));
296644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
29673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
29683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
29693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
297044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size,
297144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register result,
297244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch1,
297344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch2,
297444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Label* gc_required,
297544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        AllocationFlags flags) {
297644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!FLAG_inline_new) {
2977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
297844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Trash the registers to simulate an allocation failure.
297944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(result, 0x7091);
298044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(scratch1, 0x7191);
298144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      li(scratch2, 0x7291);
298244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
298344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    jmp(gc_required);
298444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return;
298544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
29863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
298744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!result.is(scratch1));
298844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!result.is(scratch2));
298944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!scratch1.is(scratch2));
29903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object_size.is(t9));
299144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!scratch1.is(t9) && !scratch2.is(t9) && !result.is(t9));
299244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
299344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check relative positions of allocation top and limit addresses.
299444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // ARM adds additional checks to make sure the ldm instruction can be
299544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // used. On MIPS we don't have ldm so we don't need additional checks either.
299644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference new_space_allocation_top =
299744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
299844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference new_space_allocation_limit =
299944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
300044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t top   =
300144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      reinterpret_cast<intptr_t>(new_space_allocation_top.address());
300244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t limit =
300344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
300444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT((limit - top) == kPointerSize);
300544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
300644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Set up allocation top address and object size registers.
300744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register topaddr = scratch1;
300844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  li(topaddr, Operand(new_space_allocation_top));
300944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
301044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // This code stores a temporary value in t9.
301144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & RESULT_CONTAINS_TOP) == 0) {
301244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Load allocation top into result and allocation limit into t9.
301344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(result, MemOperand(topaddr));
301444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(t9, MemOperand(topaddr, kPointerSize));
301544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
3016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
301744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Assert that result actually contains top on entry. t9 is used
301844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // immediately below so this use of t9 does not cause difference with
301944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // respect to register content between debug and release mode.
302044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      lw(t9, MemOperand(topaddr));
302144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Check(eq, "Unexpected allocation top", result, Operand(t9));
302244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
302344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Load allocation limit into t9. Result already contains allocation top.
302444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(t9, MemOperand(topaddr, limit - top));
302544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
30263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
302744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate new top and bail out if new space is exhausted. Use result
302844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to calculate the new top. Object size may be in words so a shift is
302944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // required to get the number of bytes.
303044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & SIZE_IN_WORDS) != 0) {
303144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sll(scratch2, object_size, kPointerSizeLog2);
303244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(scratch2, result, scratch2);
303344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
303444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(scratch2, result, Operand(object_size));
303544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
303644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(gc_required, Ugreater, scratch2, Operand(t9));
303744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
303844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Update allocation top. result temporarily holds the new top.
3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
304044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    And(t9, scratch2, Operand(kObjectAlignmentMask));
304144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Check(eq, "Unaligned allocation in new space", t9, Operand(zero_reg));
304244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
304344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(scratch2, MemOperand(topaddr));
30446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
304544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Tag object if requested.
304644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & TAG_OBJECT) != 0) {
304744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(result, result, Operand(kHeapObjectTag));
304844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
304944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
30506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
305144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
305244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object,
305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register scratch) {
305444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference new_space_allocation_top =
305544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
305644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
305744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make sure the object has no tag before resetting top.
305844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(object, object, Operand(~kHeapObjectTagMask));
305944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
306044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the object un-allocated is below the current top.
306144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  li(scratch, Operand(new_space_allocation_top));
306244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, MemOperand(scratch));
306344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Check(less, "Undo allocation of non allocated memory",
306444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      object, Operand(scratch));
306544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
306644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Write the address of the object to un-allocate as the current top.
306744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  li(scratch, Operand(new_space_allocation_top));
306844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(object, MemOperand(scratch));
306944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
307044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
307144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
307244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateTwoByteString(Register result,
307344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register length,
307444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register scratch1,
307544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register scratch2,
307644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register scratch3,
307744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Label* gc_required) {
307844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate the number of bytes needed for the characters in the string while
307944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // observing object alignment.
308044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
308144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sll(scratch1, length, 1);  // Length in bytes, not chars.
308244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  addiu(scratch1, scratch1,
308344f0eee88ff00398ff7f715fab053374d808c90dSteve Block       kObjectAlignmentMask + SeqTwoByteString::kHeaderSize);
308444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
308544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
308644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate two-byte string in new space.
308744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AllocateInNewSpace(scratch1,
308844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     result,
308944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     scratch2,
309044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     scratch3,
309144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     gc_required,
309244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     TAG_OBJECT);
309344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
309444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Set the map, length and hash field.
309544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeNewString(result,
309644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      length,
309744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Heap::kStringMapRootIndex,
309844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch1,
309944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch2);
310044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
310144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
310244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
310344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateAsciiString(Register result,
310444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register length,
310544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch1,
310644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch2,
310744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch3,
310844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Label* gc_required) {
310944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate the number of bytes needed for the characters in the string
311044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // while observing object alignment.
311144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
311244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(kCharSize == 1);
311344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  addiu(scratch1, length, kObjectAlignmentMask + SeqAsciiString::kHeaderSize);
311444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
311544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
311644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate ASCII string in new space.
311744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AllocateInNewSpace(scratch1,
311844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     result,
311944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     scratch2,
312044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     scratch3,
312144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     gc_required,
312244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     TAG_OBJECT);
312344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
312444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Set the map, length and hash field.
312544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeNewString(result,
312644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      length,
312744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Heap::kAsciiStringMapRootIndex,
312844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch1,
312944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch2);
313044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
313144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
313244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
313344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateTwoByteConsString(Register result,
313444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register length,
313544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register scratch1,
313644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register scratch2,
313744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Label* gc_required) {
313844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AllocateInNewSpace(ConsString::kSize,
313944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     result,
314044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     scratch1,
314144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     scratch2,
314244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     gc_required,
314344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     TAG_OBJECT);
314444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeNewString(result,
314544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      length,
314644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Heap::kConsStringMapRootIndex,
314744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch1,
314844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch2);
314944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
315044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
315144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
315244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateAsciiConsString(Register result,
315344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             Register length,
315444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             Register scratch1,
315544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             Register scratch2,
315644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             Label* gc_required) {
315744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AllocateInNewSpace(ConsString::kSize,
315844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     result,
315944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     scratch1,
316044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     scratch2,
316144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     gc_required,
316244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     TAG_OBJECT);
316344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  InitializeNewString(result,
316444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      length,
316544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Heap::kConsAsciiStringMapRootIndex,
316644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch1,
316744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch2);
316844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
316944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
317044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3171589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
3172589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                 Register length,
3173589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                 Register scratch1,
3174589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                 Register scratch2,
3175589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                 Label* gc_required) {
3176589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  AllocateInNewSpace(SlicedString::kSize,
3177589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     result,
3178589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     scratch1,
3179589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     scratch2,
3180589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     gc_required,
3181589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     TAG_OBJECT);
3182589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3183589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  InitializeNewString(result,
3184589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      length,
3185589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      Heap::kSlicedStringMapRootIndex,
3186589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      scratch1,
3187589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      scratch2);
3188589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
3189589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3190589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3191589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateAsciiSlicedString(Register result,
3192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                               Register length,
3193589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                               Register scratch1,
3194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                               Register scratch2,
3195589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                               Label* gc_required) {
3196589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  AllocateInNewSpace(SlicedString::kSize,
3197589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     result,
3198589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     scratch1,
3199589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     scratch2,
3200589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     gc_required,
3201589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     TAG_OBJECT);
3202589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  InitializeNewString(result,
3204589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      length,
3205589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      Heap::kSlicedAsciiStringMapRootIndex,
3206589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      scratch1,
3207589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      scratch2);
3208589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
3209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
321144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Allocates a heap number or jumps to the label if the young space is full and
321244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// a scavenge is needed.
321344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
321444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch1,
321544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch2,
321644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register heap_number_map,
321744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Label* need_gc) {
321844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate an object in the heap for the heap number and tag it as a heap
321944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // object.
322044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AllocateInNewSpace(HeapNumber::kSize,
322144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     result,
322244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     scratch1,
322344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     scratch2,
322444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     need_gc,
322544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     TAG_OBJECT);
322644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
322744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Store heap number map in the allocated object.
322844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
322944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
323044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
323144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
323244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
323344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AllocateHeapNumberWithValue(Register result,
323444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 FPURegister value,
323544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Register scratch1,
323644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Register scratch2,
323744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Label* gc_required) {
32383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
32393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required);
324044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset));
324144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
324244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
324344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
324444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Copies a fixed number of fields of heap objects from src to dst.
324544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CopyFields(Register dst,
324644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                Register src,
324744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                RegList temps,
324844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                int field_count) {
324944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT((temps & dst.bit()) == 0);
325044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT((temps & src.bit()) == 0);
325144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Primitive implementation using only one temporary register.
325244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
325344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register tmp = no_reg;
325444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Find a temp register in temps list.
325544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < kNumRegisters; i++) {
325644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if ((temps & (1 << i)) != 0) {
325744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      tmp.code_ = i;
325844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
325944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
32606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
326144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!tmp.is(no_reg));
32626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
326344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < field_count; i++) {
326444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(tmp, FieldMemOperand(src, i * kPointerSize));
326544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(tmp, FieldMemOperand(dst, i * kPointerSize));
326644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
326744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
32686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
32696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::CopyBytes(Register src,
3271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register dst,
3272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register length,
3273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register scratch) {
3274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done;
3275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Align src before copying in word size chunks.
3277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&align_loop);
3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&done, eq, length, Operand(zero_reg));
3279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&align_loop_1);
3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  And(scratch, src, kPointerSize - 1);
3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&word_loop, eq, scratch, Operand(zero_reg));
3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lbu(scratch, MemOperand(src));
3283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Addu(src, src, 1);
3284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sb(scratch, MemOperand(dst));
3285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Addu(dst, dst, 1);
3286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(length, length, Operand(1));
3287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&byte_loop_1, ne, length, Operand(zero_reg));
3288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Copy bytes in word size chunks.
3290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&word_loop);
3291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
3292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    And(scratch, src, kPointerSize - 1);
3293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Assert(eq, "Expecting alignment for CopyBytes",
3294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        scratch, Operand(zero_reg));
3295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&byte_loop, lt, length, Operand(kPointerSize));
3297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(scratch, MemOperand(src));
3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Addu(src, src, kPointerSize);
3299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // TODO(kalmard) check if this can be optimized to use sw in most cases.
3301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Can't use unaligned access - copy byte by byte.
3302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sb(scratch, MemOperand(dst, 0));
3303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  srl(scratch, scratch, 8);
3304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sb(scratch, MemOperand(dst, 1));
3305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  srl(scratch, scratch, 8);
3306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sb(scratch, MemOperand(dst, 2));
3307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  srl(scratch, scratch, 8);
3308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sb(scratch, MemOperand(dst, 3));
3309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Addu(dst, dst, 4);
3310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(length, length, Operand(kPointerSize));
3312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&word_loop);
3313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Copy the last bytes if any left.
3315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&byte_loop);
3316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&done, eq, length, Operand(zero_reg));
3317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&byte_loop_1);
3318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lbu(scratch, MemOperand(src));
3319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Addu(src, src, 1);
3320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sb(scratch, MemOperand(dst));
3321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Addu(dst, dst, 1);
3322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(length, length, Operand(1));
3323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&byte_loop_1, ne, length, Operand(zero_reg));
3324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
3325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
33293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register end_offset,
33303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
33313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
33323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&entry);
33333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(filler, MemOperand(start_offset));
33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(start_offset, start_offset, kPointerSize);
33363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
33373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&loop, lt, start_offset, Operand(end_offset));
33383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map,
33423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Register scratch,
33433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label* fail) {
33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 1);
33463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
33473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Branch(fail, hi, scratch, Operand(Map::kMaximumBitField2FastElementValue));
33483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
33493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map,
33523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register scratch,
33533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* fail) {
33543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 1);
33563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
33573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(fail, ls, scratch,
33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Operand(Map::kMaximumBitField2FastSmiOnlyElementValue));
33593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(fail, hi, scratch,
33603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Operand(Map::kMaximumBitField2FastElementValue));
33613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastSmiOnlyElements(Register map,
33653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Register scratch,
33663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Label* fail) {
33673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
33683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
33693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(fail, hi, scratch,
33703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Operand(Map::kMaximumBitField2FastSmiOnlyElementValue));
33713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
33753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register key_reg,
33763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register receiver_reg,
33773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register elements_reg,
33783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register scratch1,
33793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register scratch2,
33803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register scratch3,
33813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Register scratch4,
33823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Label* fail) {
33833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label smi_value, maybe_nan, have_double_value, is_nan, done;
33843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register mantissa_reg = scratch2;
33853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register exponent_reg = scratch3;
33863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle smi values specially.
33883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(value_reg, &smi_value);
33893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Ensure that the object is a heap number
33913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckMap(value_reg,
33923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           scratch1,
33933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Heap::kHeapNumberMapRootIndex,
33943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fail,
33953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           DONT_DO_SMI_CHECK);
33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
33983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in the exponent.
33993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(scratch1, Operand(kNaNOrInfinityLowerBoundUpper32));
34003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
34013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&maybe_nan, ge, exponent_reg, Operand(scratch1));
34023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
34043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&have_double_value);
34063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sll(scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize);
34073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(scratch1, scratch1, elements_reg);
34083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(mantissa_reg, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize));
34093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
34103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(exponent_reg, FieldMemOperand(scratch1, offset));
34113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&done);
34123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&maybe_nan);
34143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
34153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // it's an Infinity, and the non-NaN code path applies.
34163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&is_nan, gt, exponent_reg, Operand(scratch1));
34173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
34183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg));
34193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&is_nan);
34203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load canonical NaN for storing into the double array.
34213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint64_t nan_int64 = BitCast<uint64_t>(
34223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FixedDoubleArray::canonical_not_the_hole_nan_as_double());
34233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64)));
34243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32)));
34253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&have_double_value);
34263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&smi_value);
34283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(scratch1, elements_reg,
34293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
34303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize);
34313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(scratch1, scratch1, scratch2);
34323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // scratch1 is now effective address of the double element
34333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FloatingPointHelper::Destination destination;
34353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (CpuFeatures::IsSupported(FPU)) {
34363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    destination = FloatingPointHelper::kFPURegisters;
34373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
34383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    destination = FloatingPointHelper::kCoreRegisters;
34393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
34403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register untagged_value = receiver_reg;
34423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(untagged_value, value_reg);
34433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FloatingPointHelper::ConvertIntToDouble(this,
34443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          untagged_value,
34453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          destination,
34463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          f0,
34473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          mantissa_reg,
34483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          exponent_reg,
34493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          scratch4,
34503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          f2);
34513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (destination == FloatingPointHelper::kFPURegisters) {
34523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CpuFeatures::Scope scope(FPU);
34533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sdc1(f0, MemOperand(scratch1, 0));
34543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
34553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sw(mantissa_reg, MemOperand(scratch1, 0));
34563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sw(exponent_reg, MemOperand(scratch1, Register::kSizeInBytes));
34573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
34583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
34593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CompareMapAndBranch(Register obj,
34633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch,
34643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Handle<Map> map,
34653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Label* early_success,
34663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Condition cond,
34673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Label* branch_to,
34683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         CompareMapMode mode) {
34693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
34703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Operand right = Operand(map);
34713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
34723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Map* transitioned_fast_element_map(
34733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL));
34743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(transitioned_fast_element_map == NULL ||
34753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           map->elements_kind() != FAST_ELEMENTS);
34763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_fast_element_map != NULL) {
34773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Branch(early_success, eq, scratch, right);
34783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      right = Operand(Handle<Map>(transitioned_fast_element_map));
34793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
34803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Map* transitioned_double_map(
34823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL));
34833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(transitioned_double_map == NULL ||
34843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
34853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_double_map != NULL) {
34863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Branch(early_success, eq, scratch, right);
34873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      right = Operand(Handle<Map>(transitioned_double_map));
34883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
34893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
34903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(branch_to, cond, scratch, right);
34923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
349544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CheckMap(Register obj,
349644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Register scratch,
349744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Handle<Map> map,
349844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Label* fail,
34993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              SmiCheckType smi_check_type,
35003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              CompareMapMode mode) {
3501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
350244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    JumpIfSmi(obj, fail);
350344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
35043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label success;
35053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompareMapAndBranch(obj, scratch, map, &success, ne, fail, mode);
35063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&success);
35076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
35086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
35096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::DispatchMap(Register obj,
3511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register scratch,
3512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Handle<Map> map,
3513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Handle<Code> success,
3514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 SmiCheckType smi_check_type) {
3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
3516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
3517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
3518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
3520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Jump(success, RelocInfo::CODE_TARGET, eq, scratch, Operand(map));
3521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
3522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
352544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CheckMap(Register obj,
352644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Register scratch,
352744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Heap::RootListIndex index,
352844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Label* fail,
3529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                              SmiCheckType smi_check_type) {
3530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
353144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    JumpIfSmi(obj, fail);
353244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
353344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
353444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadRoot(at, index);
353544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(fail, ne, scratch, Operand(at));
35366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
35376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
35386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
3540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CpuFeatures::Scope scope(FPU);
3541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IsMipsSoftFloatABI) {
3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(dst, v0, v1);
3543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(dst, f0);  // Reg f0 is o32 ABI FP return value.
3545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg) {
3550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CpuFeatures::Scope scope(FPU);
3551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!IsMipsSoftFloatABI) {
3552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(f12, dreg);
3553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(a0, a1, dreg);
3555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg1,
3560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             DoubleRegister dreg2) {
3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CpuFeatures::Scope scope(FPU);
3562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!IsMipsSoftFloatABI) {
3563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (dreg2.is(f12)) {
3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(!dreg1.is(f14));
3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Move(f14, dreg2);
3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Move(f12, dreg1);
3567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Move(f12, dreg1);
3569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Move(f14, dreg2);
3570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(a0, a1, dreg1);
3573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(a2, a3, dreg2);
3574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg,
3579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register reg) {
3580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CpuFeatures::Scope scope(FPU);
3581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!IsMipsSoftFloatABI) {
3582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(f12, dreg);
3583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(a2, reg);
3584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(a2, reg);
3586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(a0, a1, dreg);
3587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
3592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This macro takes the dst register to make the code more readable
3593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // at the call sites. However, the dst register has to be t1 to
3594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // follow the calling convention which requires the call type to be
3595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // in t1.
3596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(dst.is(t1));
3597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (call_kind == CALL_AS_FUNCTION) {
3598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    li(dst, Operand(Smi::FromInt(1)));
3599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    li(dst, Operand(Smi::FromInt(0)));
3601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
36056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// -----------------------------------------------------------------------------
3606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// JavaScript invokes.
36076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
36086ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
36096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    const ParameterCount& actual,
36106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    Handle<Code> code_constant,
36116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    Register code_reg,
36126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    Label* done,
36133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
361444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    InvokeFlag flag,
3615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
3616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
36176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool definitely_matches = false;
36183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
36196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label regular_invoke;
36206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
36216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check whether the expected and actual arguments count match. If not,
36226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // setup registers according to contract with ArgumentsAdaptorTrampoline:
36236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  a0: actual arguments count
36246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  a1: function (passed through to callee)
36256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  a2: expected arguments count
36266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  a3: callee code entry
36276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
36286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // The code below is made a lot easier because the calling code already sets
36296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // up actual and expected registers according to the contract if values are
36306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // passed in registers.
36316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(actual.is_immediate() || actual.reg().is(a0));
36326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(expected.is_immediate() || expected.reg().is(a2));
36336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(a3));
36346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
36356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (expected.is_immediate()) {
36366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(actual.is_immediate());
36376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (expected.immediate() == actual.immediate()) {
36386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      definitely_matches = true;
36396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
36406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      li(a0, Operand(actual.immediate()));
36416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
36426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (expected.immediate() == sentinel) {
36436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // Don't worry about adapting arguments for builtins that
36446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // don't want that done. Skip adaption code by making it look
36456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // like we have a match between expected and actual number of
36466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // arguments.
36476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        definitely_matches = true;
36486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
36493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
36506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        li(a2, Operand(expected.immediate()));
36516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
36526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (actual.is_immediate()) {
3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Branch(&regular_invoke, eq, expected.reg(), Operand(actual.immediate()));
3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    li(a0, Operand(actual.immediate()));
36566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Branch(&regular_invoke, eq, expected.reg(), Operand(actual.reg()));
36586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
36596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
36606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!definitely_matches) {
36616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!code_constant.is_null()) {
36626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      li(a3, Operand(code_constant));
36636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      addiu(a3, a3, Code::kHeaderSize - kHeapObjectTag);
36646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
36656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
366644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> adaptor =
366744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->builtins()->ArgumentsAdaptorTrampoline();
36686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (flag == CALL_FUNCTION) {
36693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor));
3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      SetCallKind(t1, call_kind);
36713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Call(adaptor);
3672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Branch(done);
36753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
36766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      SetCallKind(t1, call_kind);
367844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Jump(adaptor, RelocInfo::CODE_TARGET);
36796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
36806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&regular_invoke);
36816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
36826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
36836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
368444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
36856ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InvokeCode(Register code,
36866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                const ParameterCount& expected,
36876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                const ParameterCount& actual,
368844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                InvokeFlag flag,
3689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                const CallWrapper& call_wrapper,
3690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                CallKind call_kind) {
36913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
36923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
36933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label done;
36956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
36963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
36973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InvokePrologue(expected, actual, Handle<Code>::null(), code,
36983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &done, &definitely_mismatches, flag,
3699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 call_wrapper, call_kind);
37003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
37013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
37023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(t1, call_kind);
37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Call(code);
37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
37063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
37073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(flag == JUMP_FUNCTION);
37083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(t1, call_kind);
37093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jump(code);
37103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Continue here if InvokePrologue does handle the invocation due to
37123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // mismatched parameter counts.
37133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
37146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
37156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
37166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
37176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
37186ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code,
37196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                const ParameterCount& expected,
37206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                const ParameterCount& actual,
37216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                RelocInfo::Mode rmode,
3722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                InvokeFlag flag,
3723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                CallKind call_kind) {
37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label done;
37286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InvokePrologue(expected, actual, code, no_reg,
37313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &done, &definitely_mismatches, flag,
3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 NullCallWrapper(), call_kind);
37333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
37353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(t1, call_kind);
37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Call(code, rmode);
37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(t1, call_kind);
37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Jump(code, rmode);
37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
37413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Continue here if InvokePrologue does handle the invocation due to
37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // mismatched parameter counts.
37433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
37446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
37456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
37466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
37476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
37486ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InvokeFunction(Register function,
37496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                    const ParameterCount& actual,
375044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    InvokeFlag flag,
3751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
3752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Contract with called JS functions requires that function is passed in a1.
37576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(function.is(a1));
37586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register expected_reg = a2;
37596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register code_reg = a3;
37606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
37616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(code_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
37626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
37636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(expected_reg,
37646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FieldMemOperand(code_reg,
37656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      SharedFunctionInfo::kFormalParameterCountOffset));
376644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sra(expected_reg, expected_reg, kSmiTagSize);
376744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
37686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
37696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ParameterCount expected(expected_reg);
3770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind);
377144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
377244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
377344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
37743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
377544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    const ParameterCount& actual,
37763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                    InvokeFlag flag,
37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    const CallWrapper& call_wrapper,
37783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                    CallKind call_kind) {
37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
37803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
378144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
378244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the function and setup the context.
37833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadHeapObject(a1, function);
378444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
378544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
378644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ParameterCount expected(function->shared()->formal_parameter_count());
37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We call indirectly through the code field in the function to
37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allow recompilation to take effect without changing any of the
37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // call sites.
37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
37913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InvokeCode(a3, expected, actual, flag, call_wrapper, call_kind);
379244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
379344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
379444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
379544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::IsObjectJSObjectType(Register heap_object,
379644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Register map,
379744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Register scratch,
379844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Label* fail) {
379944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
380044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  IsInstanceJSObjectType(map, scratch, fail);
380144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
380244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
380344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
380444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::IsInstanceJSObjectType(Register map,
380544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Register scratch,
380644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Label* fail) {
380744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
38083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
38093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
381044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
381144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
381244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
381344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::IsObjectJSStringType(Register object,
381444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Register scratch,
381544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Label* fail) {
381644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(kNotStringTag != 0);
381744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
381844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
381944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
382044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch, scratch, Operand(kIsNotStringMask));
382144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(fail, ne, scratch, Operand(zero_reg));
38226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
38236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
38246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
38256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// ---------------------------------------------------------------------------
38266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Support functions.
38276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
38286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
382944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function,
383044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             Register result,
383144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             Register scratch,
38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* miss,
38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             bool miss_on_bound_function) {
383444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the receiver isn't a smi.
383544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  JumpIfSmi(function, miss);
38366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
383744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the function really is a function.  Load map into result reg.
383844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GetObjectType(function, result, scratch);
383944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE));
38406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
38413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (miss_on_bound_function) {
38423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(scratch,
38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(scratch,
38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    And(scratch, scratch,
38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Operand(Smi::FromInt(1 << SharedFunctionInfo::kBoundFunction)));
38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(miss, ne, scratch, Operand(zero_reg));
38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
385144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make sure that the function has an instance prototype.
385244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label non_instance;
385344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
385444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch, scratch, Operand(1 << Map::kHasNonInstancePrototype));
385544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&non_instance, ne, scratch, Operand(zero_reg));
38566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
385744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the prototype or initial map from the function.
385844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(result,
385944f0eee88ff00398ff7f715fab053374d808c90dSteve Block     FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
38606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
386144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the prototype or initial map is the hole, don't return it and
386244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // simply miss the cache instead. This will allow us to allocate a
386344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // prototype object on-demand in the runtime system.
386444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadRoot(t8, Heap::kTheHoleValueRootIndex);
386544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(miss, eq, result, Operand(t8));
38666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
386744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the function does not have an initial map, we're done.
386844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done;
386944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GetObjectType(result, scratch, scratch);
387044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&done, ne, scratch, Operand(MAP_TYPE));
38716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
387244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the prototype from the initial map.
387344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(result, FieldMemOperand(result, Map::kPrototypeOffset));
387444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  jmp(&done);
38756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
387644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Non-instance prototype: Fetch prototype from constructor field
387744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // in initial map.
387844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&non_instance);
387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(result, FieldMemOperand(result, Map::kConstructorOffset));
388044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
388144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // All done.
388244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
388344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
388444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
388544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
388644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::GetObjectType(Register object,
388744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register map,
388844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register type_reg) {
388944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(map, FieldMemOperand(object, HeapObject::kMapOffset));
389044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
389144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
38926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
38936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
38946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// -----------------------------------------------------------------------------
3895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Runtime calls.
38966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub,
38983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Condition cond,
38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register r1,
39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              const Operand& r2,
39013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              BranchDelaySlot bd) {
39023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(AllowThisStubCall(stub));  // Stub calls are not allowed in some stubs.
39033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Call(stub->GetCode(), RelocInfo::CODE_TARGET, kNoASTId, cond, r1, r2, bd);
39043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
39053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
39063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
390744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::TailCallStub(CodeStub* stub) {
39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
390944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
39103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
39113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
39123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
3914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return ref0.address() - ref1.address();
3915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
39183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
39193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              int stack_space) {
3920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference next_address =
3921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference::handle_scope_next_address();
3922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kNextOffset = 0;
3923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kLimitOffset = AddressOffset(
3924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference::handle_scope_limit_address(),
3925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      next_address);
3926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kLevelOffset = AddressOffset(
3927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference::handle_scope_level_address(),
3928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      next_address);
3929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocate HandleScope in callee-save registers.
3931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  li(s3, Operand(next_address));
3932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(s0, MemOperand(s3, kNextOffset));
3933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(s1, MemOperand(s3, kLimitOffset));
3934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(s2, MemOperand(s3, kLevelOffset));
3935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Addu(s2, s2, Operand(1));
3936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(s2, MemOperand(s3, kLevelOffset));
3937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The O32 ABI requires us to pass a pointer in a0 where the returned struct
3939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (4 bytes) will be placed. This is also built into the Simulator.
3940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Set up the pointer to the returned value (a0). It was allocated in
3941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // EnterExitFrame.
3942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  addiu(a0, fp, ExitFrameConstants::kStackSpaceOffset);
3943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Native call returns to the DirectCEntry stub which redirects to the
3945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // return address pushed on stack (could have moved after GC).
3946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // DirectCEntry stub itself is generated early and never moves.
3947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DirectCEntryStub stub;
3948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  stub.GenerateCall(this, function);
3949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // As mentioned above, on MIPS a pointer is returned - we need to dereference
3951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // it to get the actual return value (which is also a pointer).
3952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(v0, MemOperand(v0));
3953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label promote_scheduled_exception;
3955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label delete_allocated_handles;
3956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label leave_exit_frame;
3957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If result is non-zero, dereference to get the result value
3959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // otherwise set it to undefined.
3960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label skip;
3961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LoadRoot(a0, Heap::kUndefinedValueRootIndex);
3962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&skip, eq, v0, Operand(zero_reg));
3963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(a0, MemOperand(v0));
3964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&skip);
3965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(v0, a0);
3966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // No more valid handles (the result handle was the last one). Restore
3968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // previous handle scope.
3969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(s0, MemOperand(s3, kNextOffset));
3970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
3971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    lw(a1, MemOperand(s3, kLevelOffset));
3972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Check(eq, "Unexpected level after return from api call", a1, Operand(s2));
3973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(s2, s2, Operand(1));
3975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(s2, MemOperand(s3, kLevelOffset));
3976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(at, MemOperand(s3, kLimitOffset));
3977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&delete_allocated_handles, ne, s1, Operand(at));
3978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check if the function scheduled an exception.
3980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&leave_exit_frame);
3981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LoadRoot(t0, Heap::kTheHoleValueRootIndex);
3982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  li(at, Operand(ExternalReference::scheduled_exception_address(isolate())));
3983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(t1, MemOperand(at));
3984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Branch(&promote_scheduled_exception, ne, t0, Operand(t1));
3985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  li(s0, Operand(stack_space));
39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LeaveExitFrame(false, s0, true);
3987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&promote_scheduled_exception);
39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TailCallExternalReference(
39903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference(Runtime::kPromoteScheduledException, isolate()),
39913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      0,
39923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      1);
3993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // HandleScope limit has changed. Delete allocated extensions.
3995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&delete_allocated_handles);
3996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(s1, MemOperand(s3, kLimitOffset));
3997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(s0, v0);
3998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(a0, v0);
3999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  PrepareCallCFunction(1, s1);
4000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  li(a0, Operand(ExternalReference::isolate_address()));
4001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate()),
4002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      1);
4003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(v0, s0);
4004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  jmp(&leave_exit_frame);
40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
40063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
40093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
40103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
4011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
40133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
40146ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) {
40156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (num_arguments > 0) {
40166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    addiu(sp, sp, num_arguments * kPointerSize);
40176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
40186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LoadRoot(v0, Heap::kUndefinedValueRootIndex);
40196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
40206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
40216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
402244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::IndexFromHash(Register hash,
402344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register index) {
402444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the hash field contains an array index pick it out. The assert checks
402544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // that the constants for the maximum number of digits for an array index
402644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // cached in the hash field and the number of bits reserved for it does not
402744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // conflict.
402844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
402944f0eee88ff00398ff7f715fab053374d808c90dSteve Block         (1 << String::kArrayIndexValueBits));
403044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We want the smi-tagged index in key.  kArrayIndexValueMask has zeros in
403144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the low kHashShift bits.
403244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
403344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Ext(hash, hash, String::kHashShift, String::kArrayIndexValueBits);
403444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sll(index, hash, kSmiTagSize);
403544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
403644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
403744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
403844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::ObjectToDoubleFPURegister(Register object,
403944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               FPURegister result,
404044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register scratch1,
404144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register scratch2,
404244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Register heap_number_map,
404344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               Label* not_number,
404444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               ObjectToDoubleFlags flags) {
404544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done;
404644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & OBJECT_NOT_SMI) == 0) {
404744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label not_smi;
404844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    JumpIfNotSmi(object, &not_smi);
404944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Remove smi tag and convert to double.
405044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sra(scratch1, object, kSmiTagSize);
405144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mtc1(scratch1, result);
405244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cvt_d_w(result, result);
405344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&done);
405444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&not_smi);
405544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
405644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check for heap number and load double value from it.
405744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
405844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(not_number, ne, scratch1, Operand(heap_number_map));
405944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
406044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((flags & AVOID_NANS_AND_INFINITIES) != 0) {
406144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // If exponent is all ones the number is either a NaN or +/-Infinity.
406244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register exponent = scratch1;
406344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register mask_reg = scratch2;
406444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(exponent, FieldMemOperand(object, HeapNumber::kExponentOffset));
406544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(mask_reg, HeapNumber::kExponentMask);
406644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
406744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    And(exponent, exponent, mask_reg);
406844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(not_number, eq, exponent, Operand(mask_reg));
406944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
407044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ldc1(result, FieldMemOperand(object, HeapNumber::kValueOffset));
407144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
407244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
407344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
407444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
407544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::SmiToDoubleFPURegister(Register smi,
407644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            FPURegister value,
407744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Register scratch1) {
407844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sra(scratch1, smi, kSmiTagSize);
407944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mtc1(scratch1, value);
408044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cvt_d_w(value, value);
408144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
408244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
408344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::AdduAndCheckForOverflow(Register dst,
4085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register left,
4086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register right,
4087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register overflow_dst,
4088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register scratch) {
4089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(overflow_dst));
4090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(scratch));
4091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!overflow_dst.is(scratch));
4092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!overflow_dst.is(left));
4093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!overflow_dst.is(right));
40943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (left.is(right) && dst.is(left)) {
40963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!dst.is(t9));
40973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!scratch.is(t9));
40983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!left.is(t9));
40993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!right.is(t9));
41003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!overflow_dst.is(t9));
41013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(t9, right);
41023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    right = t9;
41033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(left)) {
41063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(scratch, left);  // Preserve left.
41073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    addu(dst, left, right);  // Left is overwritten.
41083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(scratch, dst, scratch);  // Original left.
41093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(overflow_dst, dst, right);
41103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(overflow_dst, overflow_dst, scratch);
4111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(right)) {
41123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(scratch, right);  // Preserve right.
41133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    addu(dst, left, right);  // Right is overwritten.
41143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(scratch, dst, scratch);  // Original right.
41153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(overflow_dst, dst, left);
41163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(overflow_dst, overflow_dst, scratch);
4117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addu(dst, left, right);
4119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(overflow_dst, dst, left);
4120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(scratch, dst, right);
4121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    and_(overflow_dst, scratch, overflow_dst);
4122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SubuAndCheckForOverflow(Register dst,
4127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register left,
4128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register right,
4129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register overflow_dst,
4130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register scratch) {
4131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(overflow_dst));
4132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!dst.is(scratch));
4133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!overflow_dst.is(scratch));
4134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!overflow_dst.is(left));
4135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!overflow_dst.is(right));
4136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!scratch.is(left));
4137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!scratch.is(right));
4138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
41393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This happens with some crankshaft code. Since Subu works fine if
41403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // left == right, let's not make that restriction here.
41413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (left.is(right)) {
41423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(dst, zero_reg);
41433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(overflow_dst, zero_reg);
41443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
41453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
41463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(left)) {
41483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(scratch, left);  // Preserve left.
41493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subu(dst, left, right);  // Left is overwritten.
41503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(overflow_dst, dst, scratch);  // scratch is original left.
41513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(scratch, scratch, right);  // scratch is original left.
41523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(overflow_dst, scratch, overflow_dst);
4153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(right)) {
41543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(scratch, right);  // Preserve right.
41553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subu(dst, left, right);  // Right is overwritten.
41563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(overflow_dst, dst, left);
41573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    xor_(scratch, left, scratch);  // Original right.
41583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    and_(overflow_dst, scratch, overflow_dst);
4159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    subu(dst, left, right);
4161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(overflow_dst, dst, left);
4162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    xor_(scratch, left, right);
4163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    and_(overflow_dst, scratch, overflow_dst);
4164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
416844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
416944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 int num_arguments) {
41706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // All parameters are on the stack. v0 has the return value after call.
41716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
41726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If the expected number of arguments of the runtime function is
41736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // constant, we check that the actual number of arguments match the
41746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // expectation.
41756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (f->nargs >= 0 && f->nargs != num_arguments) {
41766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    IllegalOperation(num_arguments);
41776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return;
41786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
41796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
41806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(1236192): Most runtime routines don't need the number of
41816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // arguments passed in because it is constant. At some point we
41826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // should remove this need and make the runtime routine entry code
41836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // smarter.
41843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryArgs(num_arguments);
41853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(ExternalReference(f, isolate()));
41866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CEntryStub stub(1);
41876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallStub(&stub);
41883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
41893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
41903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
419144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
419244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Runtime::Function* function = Runtime::FunctionForId(id);
41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryArgs(function->nargs);
41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(ExternalReference(function, isolate()));
41953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CEntryStub stub(1, kSaveFPRegs);
419644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CallStub(&stub);
419744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
419844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
419944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
42003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
42016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallRuntime(Runtime::FunctionForId(fid), num_arguments);
42026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
42036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
42046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
420544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           int num_arguments,
42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           BranchDelaySlot bd) {
42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryArgs(num_arguments);
42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(ext);
421044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
421144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CEntryStub stub(1);
42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub, al, zero_reg, Operand(zero_reg), bd);
421344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
421444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
421544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
42166ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
42176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int num_arguments,
42186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int result_size) {
421944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // TODO(1236192): Most runtime routines don't need the number of
422044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // arguments passed in because it is constant. At some point we
422144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // should remove this need and make the runtime routine entry code
422244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // smarter.
42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryArgs(num_arguments);
422444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  JumpToExternalReference(ext);
42253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
42263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
42286ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
42293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                     int num_arguments,
42303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                     int result_size) {
423144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  TailCallExternalReference(ExternalReference(fid, isolate()),
423244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            num_arguments,
423344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            result_size);
42343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
42353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
42383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             BranchDelaySlot bd) {
42393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCEntryFunction(builtin);
424044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CEntryStub stub(1);
42413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Jump(stub.GetCode(),
42423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       RelocInfo::CODE_TARGET,
42433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       al,
42443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       zero_reg,
42453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Operand(zero_reg),
42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       bd);
42473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
42483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
425044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
4251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   InvokeFlag flag,
4252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   const CallWrapper& call_wrapper) {
42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a builtin without a valid frame.
42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
425644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GetBuiltinEntry(t9, id);
4257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (flag == CALL_FUNCTION) {
4258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call_wrapper.BeforeCall(CallSize(t9));
42593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SetCallKind(t1, CALL_AS_METHOD);
426044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Call(t9);
4261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call_wrapper.AfterCall();
426244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
4263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(flag == JUMP_FUNCTION);
42643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SetCallKind(t1, CALL_AS_METHOD);
426544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Jump(t9);
426644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
42673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
42683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
427044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::GetBuiltinFunction(Register target,
427144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Builtins::JavaScript id) {
427244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the builtins object into target register.
427344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
427444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
427544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the JavaScript builtin function from the builtins object.
427644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(target, FieldMemOperand(target,
427744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          JSBuiltinsObject::OffsetOfFunctionWithId(id)));
42783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
42793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
428244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!target.is(a1));
428344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GetBuiltinFunction(a1, id);
428444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the code entry point from the builtins object.
428544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(target, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
42863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
42873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::SetCounter(StatsCounter* counter, int value,
42903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                Register scratch1, Register scratch2) {
429144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
429244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch1, Operand(value));
429344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch2, Operand(ExternalReference(counter)));
429444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch1, MemOperand(scratch2));
429544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
42963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
42973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
43003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Register scratch1, Register scratch2) {
430144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(value > 0);
430244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
430344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch2, Operand(ExternalReference(counter)));
430444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(scratch1, MemOperand(scratch2));
430544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(scratch1, scratch1, Operand(value));
430644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch1, MemOperand(scratch2));
430744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
43083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
43093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
43103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
43113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
43123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Register scratch1, Register scratch2) {
431344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(value > 0);
431444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
431544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    li(scratch2, Operand(ExternalReference(counter)));
431644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(scratch1, MemOperand(scratch2));
431744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(scratch1, scratch1, Operand(value));
431844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch1, MemOperand(scratch2));
431944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
43203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
43213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
43223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
43236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// -----------------------------------------------------------------------------
4324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Debugging.
43253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
43263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Assert(Condition cc, const char* msg,
43273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                            Register rs, Operand rt) {
4328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code())
432944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Check(cc, msg, rs, rt);
433044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
433144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
433244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
433344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AssertRegisterIsRoot(Register reg,
433444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                          Heap::RootListIndex index) {
4335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
433644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadRoot(at, index);
433744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Check(eq, "Register did not match expected root", reg, Operand(at));
433844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
433944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
434044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
434144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
434244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AssertFastElements(Register elements) {
4343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
434444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(!elements.is(at));
434544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label ok;
4346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    push(elements);
434744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
434844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadRoot(at, Heap::kFixedArrayMapRootIndex);
434944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&ok, eq, elements, Operand(at));
43503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex);
43513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Branch(&ok, eq, elements, Operand(at));
435244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);
435344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&ok, eq, elements, Operand(at));
435444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Abort("JSObject with fast elements map has slow elements");
435544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&ok);
4356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    pop(elements);
435744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
43583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
43593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
43603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
43613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Check(Condition cc, const char* msg,
43623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                           Register rs, Operand rt) {
436344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label L;
436444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(&L, cc, rs, rt);
436544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Abort(msg);
4366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Will not return here.
436744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&L);
43683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
43693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
43703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
43713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::Abort(const char* msg) {
437244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label abort_start;
437344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&abort_start);
437444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We want to pass the msg string like a smi to avoid GC
437544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // problems, however msg is not guaranteed to be aligned
437644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // properly. Instead, we pass an aligned pointer that is
437744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // a proper v8 smi, but also pass the alignment difference
437844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // from the real pointer as a smi.
437944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t p1 = reinterpret_cast<intptr_t>(msg);
438044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
438144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
438244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
438344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (msg != NULL) {
438444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RecordComment("Abort message: ");
438544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RecordComment(msg);
438644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
438744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
438844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
438944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  li(a0, Operand(p0));
4390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  push(a0);
439144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  li(a0, Operand(Smi::FromInt(p1 - p0)));
4392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  push(a0);
43933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable stub call restrictions to always allow calls to abort.
43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
43953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kAbort, 2);
43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kAbort, 2);
44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Will not return here.
440344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_trampoline_pool_blocked()) {
440444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // If the calling code cares about the exact number of
440544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // instructions generated, we insert padding here to keep the size
440644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // of the Abort macro constant.
440744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Currently in debug mode with debug_code enabled the number of
440844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // generated instructions is 14, so we use this as a maximum value.
440944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    static const int kExpectedAbortInstructions = 14;
441044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int abort_instructions = InstructionsGeneratedSince(&abort_start);
441144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(abort_instructions <= kExpectedAbortInstructions);
441244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    while (abort_instructions++ < kExpectedAbortInstructions) {
441344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      nop();
441444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
441544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
441644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
441744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
441844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
441944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
442044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (context_chain_length > 0) {
442144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Move up the chain of contexts to the context containing the slot.
44223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lw(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
442344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 1; i < context_chain_length; i++) {
44243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      lw(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
442544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
4426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Slot is in the current function context.  Move it into the
4428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // destination register in case we store into it (the write barrier
4429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // cannot be allowed to destroy the context in esi).
4430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(dst, cp);
4431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
443244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
443344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
443444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional(
44363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind expected_kind,
44373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind transitioned_kind,
44383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register map_in_out,
44393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
44403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* no_map_match) {
44413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the global or builtins object from the current context.
44423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, FieldMemOperand(scratch, GlobalObject::kGlobalContextOffset));
44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function's map is the same as the expected cached map.
44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int expected_index =
44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Context::GetContextMapIndexFromElementsKind(expected_kind);
44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(at, MemOperand(scratch, Context::SlotOffset(expected_index)));
44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(no_map_match, ne, map_in_out, Operand(at));
44503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the transitioned cached map.
44523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int trans_index =
44533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Context::GetContextMapIndexFromElementsKind(transitioned_kind);
44543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(map_in_out, MemOperand(scratch, Context::SlotOffset(trans_index)));
44553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
44563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadInitialArrayMap(
44593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register function_in, Register scratch, Register map_out) {
44603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!function_in.is(map_out));
44613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
44623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(map_out, FieldMemOperand(function_in,
44633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              JSFunction::kPrototypeOrInitialMapOffset));
44643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_smi_only_arrays) {
44653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
44663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        FAST_ELEMENTS,
44673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        map_out,
44683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch,
44693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        &done);
44703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
44713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
44723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
44733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
447544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
447644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the global or builtins object from the current context.
447744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
447844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the global context from the global or builtins object.
447944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(function, FieldMemOperand(function,
448044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               GlobalObject::kGlobalContextOffset));
448144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the function from the global context.
448244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(function, MemOperand(function, Context::SlotOffset(index)));
448344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
448444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
448544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
448644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
448744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  Register map,
448844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  Register scratch) {
448944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the initial map. The global functions all have initial maps.
449044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
4491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
449244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label ok, fail;
4493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
449444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(&ok);
449544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&fail);
449644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Abort("Global functions must have initial map");
449744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&ok);
449844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
44993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
45003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
45016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45026ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
45036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  addiu(sp, sp, -5 * kPointerSize);
450444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  li(t8, Operand(Smi::FromInt(type)));
45053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t9, Operand(CodeObject()), CONSTANT_SIZE);
45066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  sw(ra, MemOperand(sp, 4 * kPointerSize));
45076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  sw(fp, MemOperand(sp, 3 * kPointerSize));
45086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  sw(cp, MemOperand(sp, 2 * kPointerSize));
450944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(t8, MemOperand(sp, 1 * kPointerSize));
451044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(t9, MemOperand(sp, 0 * kPointerSize));
45116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  addiu(fp, sp, 3 * kPointerSize);
45126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
45136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45156ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
45166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(sp, fp);
45176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(fp, MemOperand(sp, 0 * kPointerSize));
45186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lw(ra, MemOperand(sp, 1 * kPointerSize));
45196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  addiu(sp, sp, 2 * kPointerSize);
45206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
45216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::EnterExitFrame(bool save_doubles,
4524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    int stack_space) {
45253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
4526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement);
4527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset);
4528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset);
45296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This is how the stack will look:
4531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // fp + 2 (==kCallerSPDisplacement) - old stack's end
4532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // [fp + 1 (==kCallerPCOffset)] - saved old ra
4533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // [fp + 0 (==kCallerFPOffset)] - saved old fp
4534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // [fp - 1 (==kSPOffset)] - sp of the called function
4535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // [fp - 2 (==kCodeOffset)] - CodeObject
4536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the
4537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //   new stack (will contain saved ra)
45386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Save registers.
4540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  addiu(sp, sp, -4 * kPointerSize);
4541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(ra, MemOperand(sp, 3 * kPointerSize));
4542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(fp, MemOperand(sp, 2 * kPointerSize));
45433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addiu(fp, sp, 2 * kPointerSize);  // Set up new frame pointer.
45446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
4546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    sw(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset));
4547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
45493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Accessed from ExitFrame::code_slot.
45503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(CodeObject()), CONSTANT_SIZE);
4551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
45526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Save the frame pointer and the context in top.
4554589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
455544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(fp, MemOperand(t8));
4556589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
455744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(cp, MemOperand(t8));
45586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
456044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (save_doubles) {
4561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The stack  must be allign to 0 modulo 8 for stores with sdc1.
456244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(kDoubleSize == frame_alignment);
4563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (frame_alignment > 0) {
4564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(IsPowerOf2(frame_alignment));
4565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      And(sp, sp, Operand(-frame_alignment));  // Align stack.
4566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int space = FPURegister::kNumRegisters * kDoubleSize;
456844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(sp, sp, Operand(space));
456944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Remember: we only need to save every 2nd double FPU value.
457044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < FPURegister::kNumRegisters; i+=2) {
457144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FPURegister reg = FPURegister::from_code(i);
4572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      sdc1(reg, MemOperand(sp, i * kDoubleSize));
457344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
457444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
4575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Reserve place for the return address, stack space and an optional slot
4577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (used by the DirectCEntryStub to hold the return value if a struct is
4578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // returned) and align the frame preparing for calling the runtime function.
4579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(stack_space >= 0);
4580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Subu(sp, sp, Operand((stack_space + 2) * kPointerSize));
4581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (frame_alignment > 0) {
4582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(IsPowerOf2(frame_alignment));
4583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    And(sp, sp, Operand(-frame_alignment));  // Align stack.
4584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Set the exit frame sp value to point just before the return address
4587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // location.
4588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  addiu(at, sp, kPointerSize);
4589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sw(at, MemOperand(fp, ExitFrameConstants::kSPOffset));
45906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
45916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
45926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles,
45943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Register argument_count,
45953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool do_return) {
459644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Optionally restore all double registers.
459744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (save_doubles) {
459844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Remember: we only need to restore every 2nd double FPU value.
4599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    lw(t8, MemOperand(fp, ExitFrameConstants::kSPOffset));
460044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < FPURegister::kNumRegisters; i+=2) {
460144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FPURegister reg = FPURegister::from_code(i);
4602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ldc1(reg, MemOperand(t8, i  * kDoubleSize + kPointerSize));
460344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
460444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
460544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
46066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Clear top frame.
4607589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
460844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(zero_reg, MemOperand(t8));
46096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Restore current context from top and clear it in debug mode.
4611589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
461244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(cp, MemOperand(t8));
46136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG
461444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(a3, MemOperand(t8));
46156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
46166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pop the arguments, restore registers, and return.
46186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(sp, fp);  // Respect ABI stack constraint.
4619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(fp, MemOperand(sp, ExitFrameConstants::kCallerFPOffset));
4620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset));
46213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (argument_count.is_valid()) {
4623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    sll(t8, argument_count, kPointerSizeLog2);
4624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    addu(sp, sp, t8);
4625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
46263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (do_return) {
46283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Ret(USE_DELAY_SLOT);
46293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If returning, the instruction in the delay slot will be the addiu below.
46303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
46313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  addiu(sp, sp, 8);
46326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
46336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
463544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::InitializeNewString(Register string,
463644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register length,
463744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Heap::RootListIndex map_index,
463844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch1,
463944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch2) {
464044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sll(scratch1, length, kSmiTagSize);
464144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadRoot(scratch2, map_index);
464244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(scratch1, FieldMemOperand(string, String::kLengthOffset));
464344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  li(scratch1, Operand(String::kEmptyHashField));
464444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(scratch2, FieldMemOperand(string, HeapObject::kMapOffset));
464544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sw(scratch1, FieldMemOperand(string, String::kHashFieldOffset));
464644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
464744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
464844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
464944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::ActivationFrameAlignment() {
465044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#if defined(V8_HOST_ARCH_MIPS)
465144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Running on the real platform. Use the alignment as mandated by the local
465244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // environment.
465344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Note: This will break if we ever start generating snapshots on one Mips
465444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // platform for another Mips platform with a different alignment.
465544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return OS::ActivationFrameAlignment();
465644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else  // defined(V8_HOST_ARCH_MIPS)
465744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If we are using the simulator then we should always align to the expected
465844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // alignment. As the simulator is used to generate snapshots we do not know
465944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // if the target platform will need alignment, so this is controlled from a
466044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // flag.
466144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return FLAG_sim_stack_alignment;
466244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif  // defined(V8_HOST_ARCH_MIPS)
466344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
466444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
46653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::AssertStackIsAligned() {
4667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (emit_debug_code()) {
4668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      const int frame_alignment = ActivationFrameAlignment();
4669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      const int frame_alignment_mask = frame_alignment - 1;
4670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (frame_alignment > kPointerSize) {
4672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label alignment_as_expected;
4673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        ASSERT(IsPowerOf2(frame_alignment));
4674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        andi(at, sp, frame_alignment_mask);
4675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
4676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Don't use Check here, as it will call Runtime_Abort re-entering here.
4677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        stop("Unexpected stack alignment");
4678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        bind(&alignment_as_expected);
4679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
468044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
468144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
468244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
468344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
468444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotPowerOfTwoOrZero(
468544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register reg,
468644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register scratch,
468744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* not_power_of_two_or_zero) {
468844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Subu(scratch, reg, Operand(1));
468944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt,
469044f0eee88ff00398ff7f715fab053374d808c90dSteve Block         scratch, Operand(zero_reg));
469144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  and_(at, scratch, reg);  // In the delay slot.
469244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg));
469344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
469444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
469544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
46963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) {
46973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!reg.is(overflow));
46983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(overflow, reg);  // Save original value.
46993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiTag(reg);
47003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(overflow, overflow, reg);  // Overflow if (value ^ 2 * value) < 0.
47013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
47023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::SmiTagCheckOverflow(Register dst,
47053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register src,
47063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register overflow) {
47073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (dst.is(src)) {
47083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Fall back to slower case.
47093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiTagCheckOverflow(dst, overflow);
47103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
47113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!dst.is(src));
47123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!dst.is(overflow));
47133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!src.is(overflow));
47143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiTag(dst, src);
47153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(overflow, dst, src);  // Overflow if (value ^ 2 * value) < 0.
47163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
47173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
47183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::UntagAndJumpIfSmi(Register dst,
47213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register src,
47223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* smi_case) {
47233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT);
47243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(dst, src);
47253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
47263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::UntagAndJumpIfNotSmi(Register dst,
47293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Register src,
47303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Label* non_smi_case) {
47313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT);
47323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(dst, src);
47333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
47343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfSmi(Register value,
47363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Label* smi_label,
47373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register scratch,
47383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               BranchDelaySlot bd) {
47393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(0, kSmiTag);
47403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  andi(scratch, value, kSmiTagMask);
47413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(bd, smi_label, eq, scratch, Operand(zero_reg));
47423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
47433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfNotSmi(Register value,
47453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Label* not_smi_label,
47463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register scratch,
47473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  BranchDelaySlot bd) {
47483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(0, kSmiTag);
47493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  andi(scratch, value, kSmiTagMask);
47503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg));
47513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
47523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
475444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotBothSmi(Register reg1,
475544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      Register reg2,
475644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      Label* on_not_both_smi) {
475744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
475844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT_EQ(1, kSmiTagMask);
475944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  or_(at, reg1, reg2);
47603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfNotSmi(at, on_not_both_smi);
476144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
476244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
476344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
476444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfEitherSmi(Register reg1,
476544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                     Register reg2,
476644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                     Label* on_either_smi) {
476744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
476844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT_EQ(1, kSmiTagMask);
476944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Both Smi tags must be 1 (not Smi).
477044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  and_(at, reg1, reg2);
47713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(at, on_either_smi);
477244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
477344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
477444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
477544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AbortIfSmi(Register object) {
477644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
477744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  andi(at, object, kSmiTagMask);
477844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Assert(ne, "Operand is a smi", at, Operand(zero_reg));
477944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
478044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
478144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
478244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AbortIfNotSmi(Register object) {
478344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
478444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  andi(at, object, kSmiTagMask);
478544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Assert(eq, "Operand is a smi", at, Operand(zero_reg));
478644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
478744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
478844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::AbortIfNotString(Register object) {
4790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
4791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  And(t0, object, Operand(kSmiTagMask));
4792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Assert(ne, "Operand is not a string", t0, Operand(zero_reg));
4793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  push(object);
4794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(object, FieldMemOperand(object, HeapObject::kMapOffset));
4795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset));
4796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Assert(lo, "Operand is not a string", object, Operand(FIRST_NONSTRING_TYPE));
4797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  pop(object);
4798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
480144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AbortIfNotRootValue(Register src,
480244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Heap::RootListIndex root_value_index,
480344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         const char* message) {
480444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!src.is(at));
480544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadRoot(at, root_value_index);
480644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Assert(eq, message, src, Operand(at));
480744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
480844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
480944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
481044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotHeapNumber(Register object,
481144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register heap_number_map,
481244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch,
481344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Label* on_not_heap_number) {
481444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
481544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
481644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map));
481744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
481844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
481944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
482044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings(
482144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register first,
482244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register second,
482344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register scratch1,
482444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register scratch2,
482544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* failure) {
482644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Test that both first and second are sequential ASCII strings.
482744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Assume that they are non-smis.
482844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
482944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lw(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
483044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
483144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lbu(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
483244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
483344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1,
483444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               scratch2,
483544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               scratch1,
483644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               scratch2,
483744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                               failure);
483844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
483944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
484044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
484144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first,
484244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                         Register second,
484344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                         Register scratch1,
484444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                         Register scratch2,
484544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                         Label* failure) {
484644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that neither is a smi.
484744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  STATIC_ASSERT(kSmiTag == 0);
484844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch1, first, Operand(second));
48493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(scratch1, failure);
485044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  JumpIfNonSmisNotBothSequentialAsciiStrings(first,
485144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             second,
485244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             scratch1,
485344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             scratch2,
485444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             failure);
485544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
485644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
485744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
485844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
485944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register first,
486044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register second,
486144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register scratch1,
486244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register scratch2,
486344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* failure) {
486444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int kFlatAsciiStringMask =
486544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
486644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int kFlatAsciiStringTag = ASCII_STRING_TYPE;
486744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(kFlatAsciiStringTag <= 0xffff);  // Ensure this fits 16-bit immed.
486844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  andi(scratch1, first, kFlatAsciiStringMask);
486944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(failure, ne, scratch1, Operand(kFlatAsciiStringTag));
487044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  andi(scratch2, second, kFlatAsciiStringMask);
487144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(failure, ne, scratch2, Operand(kFlatAsciiStringTag));
487244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
487344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
487444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
487544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type,
487644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                            Register scratch,
487744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                            Label* failure) {
487844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int kFlatAsciiStringMask =
487944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
488044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int kFlatAsciiStringTag = ASCII_STRING_TYPE;
488144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  And(scratch, type, Operand(kFlatAsciiStringMask));
488244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Branch(failure, ne, scratch, Operand(kFlatAsciiStringTag));
488344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
488444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
488544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
488644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 4;
488744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
48883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
48893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              int num_double_arguments) {
48903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int stack_passed_words = 0;
48913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  num_reg_arguments += 2 * num_double_arguments;
48923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Up to four simple arguments are passed in registers a0..a3.
48943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (num_reg_arguments > kRegisterPassedArguments) {
48953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
48963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
48973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  stack_passed_words += kCArgSlotCount;
48983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return stack_passed_words;
48993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
49003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
49033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          int num_double_arguments,
49043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Register scratch) {
490544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int frame_alignment = ActivationFrameAlignment();
490644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
490744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Up to four simple arguments are passed in registers a0..a3.
490844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Those four arguments must have reserved argument slots on the stack for
490944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // mips, even though those argument slots are not normally used.
491044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Remaining arguments are pushed on the stack, above (higher address than)
491144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the argument slots.
49123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int stack_passed_arguments = CalculateStackPassedWords(
49133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      num_reg_arguments, num_double_arguments);
491444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (frame_alignment > kPointerSize) {
491544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Make stack end at alignment and make room for num_arguments - 4 words
491644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // and the original value of sp.
491744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(scratch, sp);
491844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
491944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(IsPowerOf2(frame_alignment));
492044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    And(sp, sp, Operand(-frame_alignment));
492144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
492244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
492344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
492444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
492544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
492644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
492744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
49283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
49293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Register scratch) {
49303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareCallCFunction(num_reg_arguments, 0, scratch);
49313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
49323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallCFunction(ExternalReference function,
49353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_reg_arguments,
49363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_double_arguments) {
49373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(function));
49383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunctionHelper(t8, num_reg_arguments, num_double_arguments);
49393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
49403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallCFunction(Register function,
49433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_reg_arguments,
49443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int num_double_arguments) {
49453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
49463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
49473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
494944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunction(ExternalReference function,
495044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   int num_arguments) {
49513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunction(function, num_arguments, 0);
495244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
495344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
495444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
495544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunction(Register function,
495644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   int num_arguments) {
49573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCFunction(function, num_arguments, 0);
495844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
495944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
496044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
496144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunctionHelper(Register function,
49623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         int num_reg_arguments,
49633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         int num_double_arguments) {
49643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(has_frame());
496544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Make sure that the stack is aligned before calling a C function unless
496644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // running in the simulator. The simulator has its own alignment check which
496744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // provides more information.
496844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The argument stots are presumed to have been set up by
496944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // PrepareCallCFunction. The C function must be called via t9, for mips ABI.
497044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
497144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#if defined(V8_HOST_ARCH_MIPS)
497244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
497344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int frame_alignment = OS::ActivationFrameAlignment();
497444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int frame_alignment_mask = frame_alignment - 1;
497544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (frame_alignment > kPointerSize) {
497644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(IsPowerOf2(frame_alignment));
497744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Label alignment_as_expected;
497844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      And(at, sp, Operand(frame_alignment_mask));
497944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
498044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Don't use Check here, as it will call Runtime_Abort possibly
498144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // re-entering here.
498244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      stop("Unexpected alignment in CallCFunction");
498344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      bind(&alignment_as_expected);
49846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
49856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
498644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif  // V8_HOST_ARCH_MIPS
498744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
498844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Just call directly. The function called cannot cause a GC, or
498944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // allow preemption, so the return address in the link register
499044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // stays correct.
499144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
49923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!function.is(t9)) {
4993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    mov(t9, function);
499444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    function = t9;
499544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
499644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
499744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Call(function);
499844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
49993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int stack_passed_arguments = CalculateStackPassedWords(
50003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      num_reg_arguments, num_double_arguments);
500144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
500244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (OS::ActivationFrameAlignment() > kPointerSize) {
500344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lw(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
500444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
500544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize)));
500644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
50076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
50086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
500944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
501044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef BRANCH_ARGS_CHECK
501144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
501244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
50133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PatchRelocatedValue(Register li_location,
50143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch,
50153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register new_value) {
50163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, MemOperand(li_location));
50173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // At this point scratch is a lui(at, ...) instruction.
50183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
50193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    And(scratch, scratch, kOpcodeMask);
50203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Check(eq, "The instruction to patch should be a lui.",
50213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        scratch, Operand(LUI));
50223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(scratch, MemOperand(li_location));
50233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
50243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  srl(t9, new_value, kImm16Bits);
50253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ins(scratch, t9, 0, kImm16Bits);
50263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(scratch, MemOperand(li_location));
50273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, MemOperand(li_location, kInstrSize));
50293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // scratch is now ori(at, ...).
50303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
50313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    And(scratch, scratch, kOpcodeMask);
50323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Check(eq, "The instruction to patch should be an ori.",
50333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        scratch, Operand(ORI));
50343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(scratch, MemOperand(li_location, kInstrSize));
50353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
50363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ins(scratch, new_value, 0, kImm16Bits);
50373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(scratch, MemOperand(li_location, kInstrSize));
50383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update the I-cache so the new lui and ori can be executed.
50403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FlushICache(li_location, 2);
50413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetRelocatedValue(Register li_location,
50443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register value,
50453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register scratch) {
50463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(value, MemOperand(li_location));
50473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
50483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    And(value, value, kOpcodeMask);
50493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Check(eq, "The instruction should be a lui.",
50503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        value, Operand(LUI));
50513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(value, MemOperand(li_location));
50523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
50533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // value now holds a lui instruction. Extract the immediate.
50553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sll(value, value, kImm16Bits);
50563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, MemOperand(li_location, kInstrSize));
50583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
50593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    And(scratch, scratch, kOpcodeMask);
50603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Check(eq, "The instruction should be an ori.",
50613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        scratch, Operand(ORI));
50623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(scratch, MemOperand(li_location, kInstrSize));
50633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
50643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // "scratch" now holds an ori instruction. Extract the immediate.
50653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  andi(scratch, scratch, kImm16Mask);
50663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Merge the results.
50683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  or_(value, value, scratch);
50693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
50733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
50743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
50753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
50763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
50773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met) {
50783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(scratch, object, Operand(~Page::kPageAlignmentMask));
50793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
50803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(scratch, scratch, Operand(mask));
50813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(condition_met, cc, scratch, Operand(zero_reg));
50823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
50863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch0,
50873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch1,
50883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black) {
50893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HasColor(object, scratch0, scratch1, on_black, 1, 0);  // kBlackBitPattern.
50903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
50913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::HasColor(Register object,
50953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register bitmap_scratch,
50963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register mask_scratch,
50973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label* has_color,
50983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int first_bit,
50993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int second_bit) {
51003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t8));
51013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t9));
51023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
51043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label other_color, word_boundary;
51063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
51073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, t9, Operand(mask_scratch));
51083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg));
51093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Shift left 1 by adding.
51103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(mask_scratch, mask_scratch, Operand(mask_scratch));
51113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&word_boundary, eq, mask_scratch, Operand(zero_reg));
51123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, t9, Operand(mask_scratch));
51133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg));
51143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&other_color);
51153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&word_boundary);
51173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize));
51183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t9, t9, Operand(1));
51193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(has_color, second_bit == 1 ? ne : eq, t9, Operand(zero_reg));
51203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&other_color);
51213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
51223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Detect some, but not all, common pointer-free objects.  This is used by the
51253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// incremental write barrier which doesn't care about oddballs (they are always
51263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// marked black immediately so this code is not hit).
51273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfDataObject(Register value,
51283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register scratch,
51293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Label* not_data_object) {
51303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(value, scratch, t8, no_reg));
51313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label is_data_object;
51323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
51333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
51343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&is_data_object, eq, t8, Operand(scratch));
51353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
51363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
51373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If it's a string and it's not a cons string then it's an object containing
51383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // no GC pointers.
51393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
51403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask));
51413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(not_data_object, ne, t8, Operand(zero_reg));
51423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&is_data_object);
51433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
51443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
51473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
51483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
51493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
51503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask));
51513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2);
51523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
51533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits);
51543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sll(t8, t8, kPointerSizeLog2);
51553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(bitmap_reg, bitmap_reg, t8);
51563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(t8, Operand(1));
51573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sllv(mask_reg, t8, mask_reg);
51583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
51593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::EnsureNotWhite(
51623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
51633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register bitmap_scratch,
51643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register mask_scratch,
51653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register load_scratch,
51663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* value_is_white_and_not_data) {
51673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, t8));
51683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
51693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
51713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0);
51723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
51733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0);
51743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
51753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
51773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
51793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
51803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
51813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, mask_scratch, load_scratch);
51823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done, ne, t8, Operand(zero_reg));
51833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
51853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for impossible bit pattern.
51863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
51873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sll may overflow, making the check conservative.
51883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sll(t8, mask_scratch, 1);
51893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    And(t8, load_scratch, t8);
51903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&ok, eq, t8, Operand(zero_reg));
51913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    stop("Impossible marking bit pattern");
51923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
51933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
51943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is white.  We check whether it is data that doesn't need scanning.
51963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Currently only checks for HeapNumber and non-cons strings.
51973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register map = load_scratch;  // Holds map while checking type.
51983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length = load_scratch;  // Holds length of object after testing type.
51993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label is_data_object;
52003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for heap-number
52023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(map, FieldMemOperand(value, HeapObject::kMapOffset));
52033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
52043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
52053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label skip;
52063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&skip, ne, t8, Operand(map));
52073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(length, HeapNumber::kSize);
52083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&is_data_object);
52093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&skip);
52103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
52113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for strings.
52133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
52143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
52153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If it's a string and it's not a cons string then it's an object containing
52163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // no GC pointers.
52173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register instance_type = load_scratch;
52183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lbu(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset));
52193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask));
52203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(value_is_white_and_not_data, ne, t8, Operand(zero_reg));
52213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // It's a non-indirect (non-cons and non-slice) string.
52223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If it's external, the length is just ExternalString::kSize.
52233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
52243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // External strings are the only ones with the kExternalStringTag bit
52253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // set.
52263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
52273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
52283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, instance_type, Operand(kExternalStringTag));
52293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
52303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label skip;
52313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&skip, eq, t8, Operand(zero_reg));
52323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(length, ExternalString::kSize);
52333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&is_data_object);
52343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&skip);
52353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
52363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sequential string, either ASCII or UC16.
52383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For ASCII (char-size of 1) we shift the smi tag away to get the length.
52393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For UC16 (char-size of 2) we just leave the smi tag in place, thereby
52403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // getting the length multiplied by 2.
52413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kAsciiStringTag == 4 && kStringEncodingMask == 4);
52423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
52433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t9, FieldMemOperand(value, String::kLengthOffset));
52443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(t8, instance_type, Operand(kStringEncodingMask));
52453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
52463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label skip;
52473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Branch(&skip, eq, t8, Operand(zero_reg));
52483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    srl(t9, t9, 1);
52493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&skip);
52503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
52513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask));
52523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(length, length, Operand(~kObjectAlignmentMask));
52533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&is_data_object);
52553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a data object, and it is white.  Mark it black.  Since we know
52563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // that the object is white we can make it black by flipping one bit.
52573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
52583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Or(t8, t8, Operand(mask_scratch));
52593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
52603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask));
52623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
52633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Addu(t8, t8, Operand(length));
52643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
52653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
52673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
52683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
5271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
5272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  lw(descriptors,
5273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     FieldMemOperand(map, Map::kInstanceDescriptorsOrBitField3Offset));
5274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label not_smi;
5275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  JumpIfNotSmi(descriptors, &not_smi);
52763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(descriptors, Heap::kEmptyDescriptorArrayRootIndex);
5277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&not_smi);
5278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
5279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
52813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
52823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label next;
52833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preload a couple of values used in the loop.
52843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register  empty_fixed_array_value = t2;
52853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
52863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register empty_descriptor_array_value = t3;
52873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(empty_descriptor_array_value,
52883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Heap::kEmptyDescriptorArrayRootIndex);
52893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(a1, a0);
52903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&next);
52913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that there are no elements.  Register a1 contains the
52933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // current JS object we've reached through the prototype chain.
52943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset));
52953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(call_runtime, ne, a2, Operand(empty_fixed_array_value));
52963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that instance descriptors are not empty so that we can
52983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // check for an enum cache.  Leave the map in a2 for the subsequent
52993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // prototype load.
53003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset));
53013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(a3, FieldMemOperand(a2, Map::kInstanceDescriptorsOrBitField3Offset));
53023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(a3, call_runtime);
53033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that there is an enum cache in the non-empty instance
53053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // descriptors (a3).  This is the case if the next enumeration
53063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // index field does not contain a smi.
53073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(a3, FieldMemOperand(a3, DescriptorArray::kEnumerationIndexOffset));
53083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(a3, call_runtime);
53093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For all objects but the receiver, check that the cache is empty.
53113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_prototype;
53123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&check_prototype, eq, a1, Operand(a0));
53133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(a3, FieldMemOperand(a3, DescriptorArray::kEnumCacheBridgeCacheOffset));
53143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(call_runtime, ne, a3, Operand(empty_fixed_array_value));
53153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the prototype from the map and loop if non-null.
53173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&check_prototype);
53183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lw(a1, FieldMemOperand(a2, Map::kPrototypeOffset));
53193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&next, ne, a1, Operand(null_value));
53203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
53243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!output_reg.is(input_reg));
53253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
53263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(output_reg, Operand(255));
53273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Normal branch: nop in delay slot.
53283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done, gt, input_reg, Operand(output_reg));
53293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use delay slot in this branch.
53303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(USE_DELAY_SLOT, &done, lt, input_reg, Operand(zero_reg));
53313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(output_reg, zero_reg);  // In delay slot.
53323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(output_reg, input_reg);  // Value is in range 0..255.
53333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
53343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ClampDoubleToUint8(Register result_reg,
53383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        DoubleRegister input_reg,
53393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        DoubleRegister temp_double_reg) {
53403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label above_zero;
53413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
53423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label in_bounds;
53433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Move(temp_double_reg, 0.0);
53453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BranchF(&above_zero, NULL, gt, input_reg, temp_double_reg);
53463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Double value is less than zero, NaN or Inf, return 0.
53483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(result_reg, zero_reg);
53493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done);
53503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Double value is >= 255, return 255.
53523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&above_zero);
53533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Move(temp_double_reg, 255.0);
53543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BranchF(&in_bounds, NULL, le, input_reg, temp_double_reg);
53553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  li(result_reg, Operand(255));
53563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Branch(&done);
53573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // In 0-255 range, round and truncate.
53593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&in_bounds);
53603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  round_w_d(temp_double_reg, input_reg);
53613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mfc1(result_reg, temp_double_reg);
53623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
53633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool AreAliased(Register r1, Register r2, Register r3, Register r4) {
53673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r1.is(r2)) return true;
53683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r1.is(r3)) return true;
53693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r1.is(r4)) return true;
53703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r2.is(r3)) return true;
53713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r2.is(r4)) return true;
53723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r3.is(r4)) return true;
53733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
53743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
537744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockCodePatcher::CodePatcher(byte* address, int instructions)
537844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : address_(address),
537944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      instructions_(instructions),
538044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      size_(instructions * Assembler::kInstrSize),
5381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm_(Isolate::Current(), address, size_ + Assembler::kGap) {
538244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
538344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
538444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // bytes of instructions without failing with buffer size constraints.
538544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
538644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
538744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
538844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
538944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockCodePatcher::~CodePatcher() {
539044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Indicate that code has changed.
539144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CPU::FlushICache(address_, size_);
539244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
539344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the code was patched as expected.
539444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(masm_.pc_ == address_ + size_);
539544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
539644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
539744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
539844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid CodePatcher::Emit(Instr instr) {
5400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  masm()->emit(instr);
540144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
540244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
540344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
540444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid CodePatcher::Emit(Address addr) {
540544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  masm()->emit(reinterpret_cast<Instr>(addr));
540644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
540744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
540844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid CodePatcher::ChangeBranchCondition(Condition cond) {
5410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Instr instr = Assembler::instr_at(masm_.pc_);
5411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(Assembler::IsBranch(instr));
5412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint32_t opcode = Assembler::GetOpcodeField(instr);
5413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Currently only the 'eq' and 'ne' cond values are supported and the simple
5414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // branch instructions (with opcode being the branch type).
5415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // There are some special cases (see Assembler::IsBranch()) so extending this
5416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // would be tricky.
5417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(opcode == BEQ ||
5418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         opcode == BNE ||
5419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        opcode == BLEZ ||
5420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        opcode == BGTZ ||
5421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        opcode == BEQL ||
5422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        opcode == BNEL ||
5423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       opcode == BLEZL ||
5424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       opcode == BGTZL);
5425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  opcode = (cond == eq) ? BEQ : BNE;
5426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  instr = (instr & ~kOpcodeMask) | opcode;
5427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  masm_.emit(instr);
5428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
542944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
543044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
54313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} }  // namespace v8::internal
54323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_MIPS
5434