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 283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifndef V8_MIPS_MACRO_ASSEMBLER_MIPS_H_ 293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define V8_MIPS_MACRO_ASSEMBLER_MIPS_H_ 303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "assembler.h" 323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "mips/assembler-mips.h" 33257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "v8globals.h" 343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 { 363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal { 373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Forward declaration. 393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass JumpTarget; 403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Reserved Register Usage Summary. 4244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// 4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Registers t8, t9, and at are reserved for use by the MacroAssembler. 4444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// 4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The programmer should know that the MacroAssembler may clobber these three, 4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// but won't touch other registers except in special cases. 4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// 4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Per the MIPS ABI, register t9 must be used for indirect function call 4944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when 5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// trying to update gp register for position-independent-code. Whenever 5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// MIPS generated code calls C code, it must be via t9 register. 523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 53592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Flags used for the AllocateInNewSpace functions. 5544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockenum AllocationFlags { 5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // No special flags. 5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block NO_ALLOCATION_FLAGS = 0, 5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return the pointer to the allocated already tagged as a heap object. 5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block TAG_OBJECT = 1 << 0, 6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The content of the result register already contains the allocation top in 6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // new space. 6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block RESULT_CONTAINS_TOP = 1 << 1, 6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Specify that the requested size of the space to allocate is specified in 6444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // words instead of bytes. 6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block SIZE_IN_WORDS = 1 << 2 6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Flags used for the ObjectToDoubleFPURegister function. 6944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockenum ObjectToDoubleFlags { 7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // No special flags. 7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block NO_OBJECT_TO_DOUBLE_FLAGS = 0, 7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Object is known to be a non smi. 7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block OBJECT_NOT_SMI = 1 << 0, 7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Don't load NaNs or infinities, branch to the non number case instead. 7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AVOID_NANS_AND_INFINITIES = 1 << 1 7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Allow programmer to use Branch Delay Slot of Branches, Jumps, Calls. 7944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockenum BranchDelaySlot { 8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block USE_DELAY_SLOT, 8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block PROTECT 8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Flags used for the li macro-assembler function. 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum LiFlags { 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the constant value can be represented in just 16 bits, then 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // optimize the li to use a single instruction, rather than lui/ori pair. 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OPTIMIZE_SIZE = 0, 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Always use 2 instructions (lui/ori pair), even if the constant could 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // be loaded with just one, so that this value is patchable later. 913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CONSTANT_SIZE = 1 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}; 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum RAStatus { kRAHasNotBeenSaved, kRAHasBeenSaved }; 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool AreAliased(Register r1, Register r2, Register r3, Register r4); 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// ----------------------------------------------------------------------------- 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Static helper functions. 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand ContextOperand(Register context, int index) { 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return MemOperand(context, Context::SlotOffset(index)); 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand GlobalObjectOperand() { 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ContextOperand(cp, Context::GLOBAL_INDEX); 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Generate a MemOperand for loading a field from an object. 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand FieldMemOperand(Register object, int offset) { 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return MemOperand(object, offset - kHeapObjectTag); 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Generate a MemOperand for storing arguments 5..N on the stack 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// when calling CallCFunction(). 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand CFunctionArgumentOperand(int index) { 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(index > kCArgSlotCount); 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Argument 5 takes the slot just past the four Arg-slots. 1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset = (index - 5) * kPointerSize + kCArgsSlotsSize; 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return MemOperand(sp, offset); 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// MacroAssembler implements a collection of frequently used macros. 1323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass MacroAssembler: public Assembler { 1333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public: 134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The isolate parameter can be NULL if the macro assembler should 135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // not use isolate-dependent functionality. In this case, it's the 136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // responsibility of the caller to never invoke such function on the 137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // macro assembler. 138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler(Isolate* isolate, void* buffer, int size); 1393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Arguments macros. 14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2 14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define COND_ARGS cond, r1, r2 14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Cases when relocation is not needed. 14544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DECLARE_NORELOC_PROTOTYPE(Name, target_type) \ 14644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Name(target_type target, BranchDelaySlot bd = PROTECT); \ 14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block inline void Name(BranchDelaySlot bd, target_type target) { \ 14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Name(target, bd); \ 14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } \ 15044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Name(target_type target, \ 15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block COND_TYPED_ARGS, \ 15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block BranchDelaySlot bd = PROTECT); \ 15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block inline void Name(BranchDelaySlot bd, \ 15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block target_type target, \ 15544f0eee88ff00398ff7f715fab053374d808c90dSteve Block COND_TYPED_ARGS) { \ 15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Name(target, COND_ARGS, bd); \ 15744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 15844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 15944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DECLARE_BRANCH_PROTOTYPES(Name) \ 16044f0eee88ff00398ff7f715fab053374d808c90dSteve Block DECLARE_NORELOC_PROTOTYPE(Name, Label*) \ 16144f0eee88ff00398ff7f715fab053374d808c90dSteve Block DECLARE_NORELOC_PROTOTYPE(Name, int16_t) 16244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DECLARE_BRANCH_PROTOTYPES(Branch) 1643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DECLARE_BRANCH_PROTOTYPES(BranchAndLink) 16544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef DECLARE_BRANCH_PROTOTYPES 16744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef COND_TYPED_ARGS 16844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef COND_ARGS 1693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Jump, Call, and Ret pseudo instructions implementing inter-working. 1723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define COND_ARGS Condition cond = al, Register rs = zero_reg, \ 1733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT 1743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Jump(Register target, COND_ARGS); 1763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Jump(intptr_t target, RelocInfo::Mode rmode, COND_ARGS); 1773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Jump(Address target, RelocInfo::Mode rmode, COND_ARGS); 1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Jump(Handle<Code> code, RelocInfo::Mode rmode, COND_ARGS); 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static int CallSize(Register target, COND_ARGS); 1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Call(Register target, COND_ARGS); 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static int CallSize(Address target, RelocInfo::Mode rmode, COND_ARGS); 1823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Call(Address target, RelocInfo::Mode rmode, COND_ARGS); 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static int CallSize(Handle<Code> code, 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned ast_id = kNoASTId, 1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch COND_ARGS); 1873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Call(Handle<Code> code, 1883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 1893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unsigned ast_id = kNoASTId, 1903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch COND_ARGS); 1913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Ret(COND_ARGS); 1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void Ret(BranchDelaySlot bd, Condition cond = al, 1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register rs = zero_reg, const Operand& rt = Operand(zero_reg)) { 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Ret(cond, rs, rt, bd); 1953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Branch(Label* L, 1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond, 1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register rs, 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::RootListIndex index, 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BranchDelaySlot bdslot = PROTECT); 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef COND_ARGS 204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Emit code to discard a non-negative number of pointer-sized elements 2063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // from the stack, clobbering only the sp register. 20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Drop(int count, 20844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Condition cond = cc_always, 20944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register reg = no_reg, 21044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Operand& op = Operand(no_reg)); 21144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Trivial case of DropAndRet that utilizes the delay slot and only emits 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 2 instructions. 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void DropAndRet(int drop); 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void DropAndRet(int drop, 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond, 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg, 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Operand& op); 22044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 22144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Swap two registers. If the scratch register is omitted then a slightly 22244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // less efficient form using xor instead of mov is emitted. 22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Swap(Register reg1, Register reg2, Register scratch = no_reg); 2243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Call(Label* target); 22644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inline void Move(Register dst, Register src) { 228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!dst.is(src)) { 229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch mov(dst, src); 230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inline void Move(FPURegister dst, FPURegister src) { 234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!dst.is(src)) { 235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch mov_d(dst, src); 236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inline void Move(Register dst_low, Register dst_high, FPURegister src) { 240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch mfc1(dst_low, src); 241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch mfc1(dst_high, FPURegister::from_code(src.code() + 1)); 242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inline void Move(FPURegister dst, Register src_low, Register src_high) { 245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch mtc1(src_low, dst); 246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch mtc1(src_high, FPURegister::from_code(dst.code() + 1)); 247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Conditional move. 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Move(FPURegister dst, double imm); 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Movz(Register rd, Register rs, Register rt); 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Movn(Register rd, Register rs, Register rt); 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Movt(Register rd, Register rs, uint16_t cc = 0); 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Movf(Register rd, Register rs, uint16_t cc = 0); 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Clz(Register rd, Register rs); 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Jump unconditionally to given label. 2593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // We NEED a nop in the branch delay slot, as it used by v8, for example in 2603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // CodeGenerator::ProcessDeferred(). 2616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Currently the branch delay slot is filled by the MacroAssembler. 2623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Use rather b(Label) for code generation. 2633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void jmp(Label* L) { 26444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Branch(L); 2653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Load an object from the root table. 2683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void LoadRoot(Register destination, 2693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Heap::RootListIndex index); 2703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void LoadRoot(Register destination, 2713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Heap::RootListIndex index, 2723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Condition cond, Register src1, const Operand& src2); 2733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Store an object to the root table. 27544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void StoreRoot(Register source, 27644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::RootListIndex index); 27744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void StoreRoot(Register source, 27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::RootListIndex index, 27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Condition cond, Register src1, const Operand& src2); 28044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadHeapObject(Register dst, Handle<HeapObject> object); 28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadObject(Register result, Handle<Object> object) { 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsHeapObject()) { 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LoadHeapObject(result, Handle<HeapObject>::cast(object)); 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch li(result, object); 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 290592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // --------------------------------------------------------------------------- 2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // GC Support 2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void IncrementalMarkingRecordWriteHelper(Register object, 2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address); 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch enum RememberedSetFinalAction { 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kReturnAtEnd, 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kFallThroughAtEnd 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 302592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 303592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Record in the remembered set the fact that we have a pointer to new space 3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // at the address pointed to by the addr register. Only works if addr is not 3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in new space. 3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RememberedSetHelper(Register object, // Used for debug code. 3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register addr, 3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetFinalAction and_then); 3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckPageFlag(Register object, 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mask, 3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* condition_met); 3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is in new space. Jumps if the object is not in new space. 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The register scratch can be object itself, but it will be clobbered. 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfNotInNewSpace(Register object, 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch) { 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InNewSpace(object, scratch, ne, branch); 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is in new space. Jumps if the object is in new space. 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The register scratch can be object itself, but scratch will be clobbered. 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfInNewSpace(Register object, 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch) { 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InNewSpace(object, scratch, eq, branch); 3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if an object has a given incremental marking color. 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void HasColor(Register object, 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0, 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* has_color, 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int first_bit, 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int second_bit); 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfBlack(Register object, 34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch0, 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* on_black); 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Checks the color of an object. If the object is already grey or black 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // then we just fall through, since it is already live. If it is white and 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // we can determine that it doesn't need to be scanned, then we just mark it 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // black and fall through. For the rest we jump to the label so the 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // incremental marker can fix its assumptions. 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void EnsureNotWhite(Register object, 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* object_is_white_and_not_data); 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Detects conservatively whether an object is data-only, i.e. it does need to 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // be scanned by the garbage collector. 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfDataObject(Register value, 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* not_data_object); 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Notify the garbage collector that we wrote a pointer into an object. 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // |object| is the object being stored into, |value| is the object being 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // stored. value and scratch registers are clobbered by the operation. 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The offset is the offset from the start of the object, not the offset from 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the tagged HeapObject pointer. For use with FieldOperand(reg, off). 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWriteField( 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RAStatus ra_status, 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK); 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // As above, but the offset has the tag presubtracted. For use with 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MemOperand(reg, off). 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void RecordWriteContextSlot( 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register context, 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset, 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RAStatus ra_status, 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK) { 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordWriteField(context, 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset + kHeapObjectTag, 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ra_status, 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch save_fp, 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch remembered_set_action, 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch smi_check); 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 400592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For a given |object| notify the garbage collector that the slot |address| 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // has been written. |value| is the object being stored. The value and 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // address registers are clobbered by the operation. 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void RecordWrite( 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object, 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register address, 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RAStatus ra_status, 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SaveFPRegsMode save_fp, 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck smi_check = INLINE_SMI_CHECK); 41244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 41344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 41444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // --------------------------------------------------------------------------- 415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Inline caching support. 41644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 41744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Generate code for checking access rights - used for security checks 41844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // on access to global objects across environments. The holder register 41944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // is left untouched, whereas both scratch registers are clobbered. 42044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CheckAccessGlobalProxy(Register holder_reg, 42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* miss); 42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 424c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch void GetNumberHash(Register reg0, Register scratch); 4253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void LoadFromNumberDictionary(Label* miss, 4273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register elements, 4283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key, 4293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result, 4303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register reg0, 4313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register reg1, 4323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register reg2); 4333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block inline void MarkCode(NopMarkerTypes type) { 43644f0eee88ff00398ff7f715fab053374d808c90dSteve Block nop(type); 43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 43844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 43944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check if the given instruction is a 'type' marker. 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // i.e. check if it is a sll zero_reg, zero_reg, <type> (referenced as 44144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // nop(type)). These instructions are generated to mark special location in 44244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // the code, like some special IC code. 44344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static inline bool IsMarkedCode(Instr instr, int type) { 44444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)); 44544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return IsNop(instr, type); 44644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 44744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 44844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 44944f0eee88ff00398ff7f715fab053374d808c90dSteve Block static inline int GetCodeMarker(Instr instr) { 45044f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t opcode = ((instr & kOpcodeMask)); 45144f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t rt = ((instr & kRtFieldMask) >> kRtShift); 45244f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t rs = ((instr & kRsFieldMask) >> kRsShift); 45344f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t sa = ((instr & kSaFieldMask) >> kSaShift); 45444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 45544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return <n> if we have a sll zero_reg, zero_reg, n 45644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // else return -1. 45744f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool sllzz = (opcode == SLL && 45844f0eee88ff00398ff7f715fab053374d808c90dSteve Block rt == static_cast<uint32_t>(ToNumber(zero_reg)) && 45944f0eee88ff00398ff7f715fab053374d808c90dSteve Block rs == static_cast<uint32_t>(ToNumber(zero_reg))); 46044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int type = 46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block (sllzz && FIRST_IC_MARKER <= sa && sa < LAST_CODE_MARKER) ? sa : -1; 46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((type == -1) || 46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); 46444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return type; 4656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // --------------------------------------------------------------------------- 470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocation support. 47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 47244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Allocate an object in new space. The object_size is specified 47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // either in bytes or in words if the allocation flag SIZE_IN_WORDS 47444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // is passed. If the new space is exhausted control continues at the 47544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // gc_required label. The allocated object is returned in result. If 47644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // the flag tag_allocated_object is true the result is tagged as as 47744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // a heap object. All registers are clobbered also when control 47844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // continues at the gc_required label. 47944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AllocateInNewSpace(int object_size, 48044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result, 48144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 48244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 48344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* gc_required, 48444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AllocationFlags flags); 48544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AllocateInNewSpace(Register object_size, 48644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result, 48744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 48844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 48944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* gc_required, 49044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AllocationFlags flags); 49144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 49244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Undo allocation in new space. The object passed and objects allocated after 49344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // it will no longer be allocated. The caller must make sure that no pointers 49444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // are left to the object(s) no longer allocated as they would be invalid when 49544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // allocation is undone. 49644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void UndoAllocationInNewSpace(Register object, Register scratch); 49744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 49844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 49944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AllocateTwoByteString(Register result, 50044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register length, 50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 50344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch3, 50444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* gc_required); 50544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AllocateAsciiString(Register result, 50644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register length, 50744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 50844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 50944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch3, 51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* gc_required); 51144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AllocateTwoByteConsString(Register result, 51244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register length, 51344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 51444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* gc_required); 51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AllocateAsciiConsString(Register result, 51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register length, 51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 51944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 52044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* gc_required); 521589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void AllocateTwoByteSlicedString(Register result, 522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register length, 523589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1, 524589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch2, 525589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* gc_required); 526589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void AllocateAsciiSlicedString(Register result, 527589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register length, 528589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1, 529589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch2, 530589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* gc_required); 53144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 53244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Allocates a heap number or jumps to the gc_required label if the young 53344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // space is full and a scavenge is needed. All registers are clobbered also 53444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // when control continues at the gc_required label. 53544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AllocateHeapNumber(Register result, 53644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 53744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 53844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register heap_number_map, 53944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* gc_required); 54044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AllocateHeapNumberWithValue(Register result, 54144f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegister value, 54244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 54344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 54444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* gc_required); 54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 54644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // --------------------------------------------------------------------------- 547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Instruction macros. 5483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 54944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DEFINE_INSTRUCTION(instr) \ 5503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void instr(Register rd, Register rs, const Operand& rt); \ 5513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void instr(Register rd, Register rs, Register rt) { \ 5523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu instr(rd, rs, Operand(rt)); \ 5533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } \ 5543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void instr(Register rs, Register rt, int32_t j) { \ 5553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu instr(rs, rt, Operand(j)); \ 5563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 55844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DEFINE_INSTRUCTION2(instr) \ 5593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void instr(Register rs, const Operand& rt); \ 5603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void instr(Register rs, Register rt) { \ 5613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu instr(rs, Operand(rt)); \ 5623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } \ 5633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void instr(Register rs, int32_t j) { \ 5643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu instr(rs, Operand(j)); \ 5653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION(Addu); 56844f0eee88ff00398ff7f715fab053374d808c90dSteve Block DEFINE_INSTRUCTION(Subu); 5693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION(Mul); 5703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION2(Mult); 5713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION2(Multu); 5723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION2(Div); 5733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION2(Divu); 5743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION(And); 5763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION(Or); 5773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION(Xor); 5783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION(Nor); 579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFINE_INSTRUCTION2(Neg); 5803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION(Slt); 5823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DEFINE_INSTRUCTION(Sltu); 5833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 58444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // MIPS32 R2 instruction macro. 58544f0eee88ff00398ff7f715fab053374d808c90dSteve Block DEFINE_INSTRUCTION(Ror); 58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef DEFINE_INSTRUCTION 5883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef DEFINE_INSTRUCTION2 5893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // --------------------------------------------------------------------------- 592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Pseudo-instructions. 5933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); } 5953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load int32 in the rd register. 5973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void li(Register rd, Operand j, LiFlags mode = OPTIMIZE_SIZE); 5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void li(Register rd, int32_t j, LiFlags mode = OPTIMIZE_SIZE) { 5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch li(rd, Operand(j), mode); 6003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void li(Register dst, Handle<Object> value, 6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LiFlags mode = OPTIMIZE_SIZE) { 6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch li(dst, Operand(value), mode); 60444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 6053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Push multiple registers on the stack. 6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Registers are saved in numerical order, with higher numbered registers 608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // saved in higher memory addresses. 6093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void MultiPush(RegList regs); 6103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void MultiPushReversed(RegList regs); 61144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 612589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void MultiPushFPU(RegList regs); 613589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void MultiPushReversedFPU(RegList regs); 614589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Lower case push() for compatibility with arch-independent code. 616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void push(Register src) { 6173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Addu(sp, sp, Operand(-kPointerSize)); 6183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sw(src, MemOperand(sp, 0)); 6193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 62044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Push a handle. 6223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Push(Handle<Object> handle); 6233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Push two registers. Pushes leftmost register first (to highest address). 625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Push(Register src1, Register src2) { 62644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Subu(sp, sp, Operand(2 * kPointerSize)); 62744f0eee88ff00398ff7f715fab053374d808c90dSteve Block sw(src1, MemOperand(sp, 1 * kPointerSize)); 62844f0eee88ff00398ff7f715fab053374d808c90dSteve Block sw(src2, MemOperand(sp, 0 * kPointerSize)); 62944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 63044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Push three registers. Pushes leftmost register first (to highest address). 632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Push(Register src1, Register src2, Register src3) { 633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Subu(sp, sp, Operand(3 * kPointerSize)); 63444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sw(src1, MemOperand(sp, 2 * kPointerSize)); 63544f0eee88ff00398ff7f715fab053374d808c90dSteve Block sw(src2, MemOperand(sp, 1 * kPointerSize)); 63644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sw(src3, MemOperand(sp, 0 * kPointerSize)); 63744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 63844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Push four registers. Pushes leftmost register first (to highest address). 640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Push(Register src1, Register src2, Register src3, Register src4) { 641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Subu(sp, sp, Operand(4 * kPointerSize)); 64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block sw(src1, MemOperand(sp, 3 * kPointerSize)); 64344f0eee88ff00398ff7f715fab053374d808c90dSteve Block sw(src2, MemOperand(sp, 2 * kPointerSize)); 64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sw(src3, MemOperand(sp, 1 * kPointerSize)); 64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block sw(src4, MemOperand(sp, 0 * kPointerSize)); 64644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 64744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Push(Register src, Condition cond, Register tst1, Register tst2) { 649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Since we don't have conditional execution we use a Branch. 65044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Branch(3, cond, tst1, Operand(tst2)); 651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Subu(sp, sp, Operand(kPointerSize)); 6523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sw(src, MemOperand(sp, 0)); 6533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 6543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Pops multiple values from the stack and load them in the 6563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // registers specified in regs. Pop order is the opposite as in MultiPush. 6573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void MultiPop(RegList regs); 6583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void MultiPopReversed(RegList regs); 659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 660589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void MultiPopFPU(RegList regs); 661589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void MultiPopReversedFPU(RegList regs); 662589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Lower case pop() for compatibility with arch-independent code. 664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void pop(Register dst) { 6653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu lw(dst, MemOperand(sp, 0)); 6663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Addu(sp, sp, Operand(kPointerSize)); 6673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Pop two registers. Pops rightmost register first (from lower address). 670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Pop(Register src1, Register src2) { 671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!src1.is(src2)); 672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lw(src2, MemOperand(sp, 0 * kPointerSize)); 673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lw(src1, MemOperand(sp, 1 * kPointerSize)); 674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Addu(sp, sp, 2 * kPointerSize); 675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pop three registers. Pops rightmost register first (from lower address). 6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Pop(Register src1, Register src2, Register src3) { 6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lw(src3, MemOperand(sp, 0 * kPointerSize)); 6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lw(src2, MemOperand(sp, 1 * kPointerSize)); 6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lw(src1, MemOperand(sp, 2 * kPointerSize)); 6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Addu(sp, sp, 3 * kPointerSize); 6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Pop(uint32_t count = 1) { 68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Addu(sp, sp, Operand(count * kPointerSize)); 68744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 68844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Push and pop the registers that can hold pointers, as defined by the 69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // RegList constant kSafepointSavedRegisters. 691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void PushSafepointRegisters(); 692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void PopSafepointRegisters(); 693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void PushSafepointRegistersAndDoubles(); 694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void PopSafepointRegistersAndDoubles(); 695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Store value in register src in the safepoint stack slot for 696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // register dst. 697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void StoreToSafepointRegisterSlot(Register src, Register dst); 698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst); 699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the value of the src register from its safepoint stack slot 700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // into register dst. 701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void LoadFromSafepointRegisterSlot(Register dst, Register src); 70244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Flush the I-cache from asm code. You should use CPU::FlushICache from C. 7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Does not handle errors. 7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void FlushICache(Register address, unsigned instructions); 7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // MIPS32 R2 instruction macro. 70844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Ins(Register rt, Register rs, uint16_t pos, uint16_t size); 70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Ext(Register rt, Register rs, uint16_t pos, uint16_t size); 71044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // --------------------------------------------------------------------------- 7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FPU macros. These do not handle special cases like NaN or +- inf. 7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 71444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert unsigned word to double. 71569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void Cvt_d_uw(FPURegister fd, FPURegister fs, FPURegister scratch); 71669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void Cvt_d_uw(FPURegister fd, Register rs, FPURegister scratch); 71744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 71844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert double to unsigned word. 71969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void Trunc_uw_d(FPURegister fd, FPURegister fs, FPURegister scratch); 72069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void Trunc_uw_d(FPURegister fd, Register rs, FPURegister scratch); 72144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Trunc_w_d(FPURegister fd, FPURegister fs); 7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Round_w_d(FPURegister fd, FPURegister fs); 7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Floor_w_d(FPURegister fd, FPURegister fs); 7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Ceil_w_d(FPURegister fd, FPURegister fs); 7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Wrapper function for the different cmp/branch types. 7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void BranchF(Label* target, 7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* nan, 7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FPURegister cmp1, 7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FPURegister cmp2, 7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BranchDelaySlot bd = PROTECT); 7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Alternate (inline) version for better readability with USE_DELAY_SLOT. 7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void BranchF(BranchDelaySlot bd, 7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* target, 7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* nan, 7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc, 7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FPURegister cmp1, 7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FPURegister cmp2) { 7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BranchF(target, nan, cc, cmp1, cmp2, bd); 7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert the HeapNumber pointed to by source to a 32bits signed integer 74544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // dest. If the HeapNumber does not fit into a 32bits signed integer branch 74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // to not_int32 label. If FPU is available double_scratch is used but not 74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scratch2. 74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ConvertToInt32(Register source, 74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register dest, 75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegister double_scratch, 75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label *not_int32); 75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Truncates a double using a specific rounding mode. 7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The except_flag will contain any exceptions caused by the instruction. 7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If check_inexact is kDontCheckForInexactConversion, then the inexacat 7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // exception is masked. 7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void EmitFPUTruncate(FPURoundingMode rounding_mode, 7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FPURegister result, 7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoubleRegister double_input, 7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register except_flag, 7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckForInexactConversion check_inexact 7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch = kDontCheckForInexactConversion); 7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Helper for EmitECMATruncate. 768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This will truncate a floating-point value outside of the singed 32bit 769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // integer range to a 32bit signed integer. 770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Expects the double value loaded in input_high and input_low. 771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Exits with the answer in 'result'. 772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Note that this code does not work for values in the 32bit range! 773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EmitOutOfInt32RangeTruncate(Register result, 774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register input_high, 775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register input_low, 776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch); 777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Performs a truncating conversion of a floating point number as used by 7793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 7803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Exits with 'result' holding the answer and all other registers clobbered. 7813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void EmitECMATruncate(Register result, 7823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FPURegister double_input, 7833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FPURegister single_scratch, 7843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch, 7853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch2, 7863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch3); 7873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Enter exit frame. 789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // argc - argument count to be dropped by LeaveExitFrame. 790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // save_doubles - saves FPU registers on stack, currently disabled. 791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // stack_space - extra stack space. 792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EnterExitFrame(bool save_doubles, 793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int stack_space = 0); 7946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Leave the current exit frame. 7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LeaveExitFrame(bool save_doubles, 7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register arg_count, 7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool do_return = false); 7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get the actual activation frame alignment for target environment. 80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block static int ActivationFrameAlignment(); 8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure the stack is aligned. Only emits code in debug mode. 804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void AssertStackIsAligned(); 805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void LoadContext(Register dst, int context_chain_length); 8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Conditionally load the cached Array transitioned map of type 8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // transitioned_kind from the global context if the map in register 8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // map_in_out is the cached Array map in the global context of 8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // expected_kind. 8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadTransitionedArrayMapConditional( 8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind expected_kind, 8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind transitioned_kind, 8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map_in_out, 8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* no_map_match); 8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the initial map for new Arrays from a JSFunction. 8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LoadInitialArrayMap(Register function_in, 8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map_out); 8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void LoadGlobalFunction(int index, Register function); 82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 82644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Load the initial map from the global function. The registers 82744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // function and map can be the same, function is then overwritten. 82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void LoadGlobalFunctionInitialMap(Register function, 82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register map, 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch); 83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InitializeRootRegister() { 8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference roots_array_start = 8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::roots_array_start(isolate()); 8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch li(kRootRegister, Operand(roots_array_start)); 8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 83844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ------------------------------------------------------------------------- 839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // JavaScript invokes. 840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up call kind marking in t1. The method takes t1 as an 842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // explicit first parameter to make the code more readable at the 843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // call sites. 844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void SetCallKind(Register dst, CallKind kind); 8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Invoke the JavaScript function code by either calling or jumping. 8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void InvokeCode(Register code, 8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& expected, 8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& actual, 85044f0eee88ff00398ff7f715fab053374d808c90dSteve Block InvokeFlag flag, 8513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const CallWrapper& call_wrapper, 8523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallKind call_kind); 8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void InvokeCode(Handle<Code> code, 8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& expected, 8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& actual, 8576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block RelocInfo::Mode rmode, 858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InvokeFlag flag, 8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallKind call_kind); 8606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Invoke the JavaScript function in the given register. Changes the 8626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // current context to the context in the function before invoking. 8636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void InvokeFunction(Register function, 8646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& actual, 86544f0eee88ff00398ff7f715fab053374d808c90dSteve Block InvokeFlag flag, 8663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const CallWrapper& call_wrapper, 8673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallKind call_kind); 86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InvokeFunction(Handle<JSFunction> function, 87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const ParameterCount& actual, 8713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch InvokeFlag flag, 8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const CallWrapper& call_wrapper, 8733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallKind call_kind); 8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void IsObjectJSObjectType(Register heap_object, 87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register map, 87844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* fail); 88044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void IsInstanceJSObjectType(Register map, 88244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 88344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* fail); 88444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 88544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void IsObjectJSStringType(Register object, 88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 88744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* fail); 88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT 89044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ------------------------------------------------------------------------- 891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Debugger Support. 8926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void DebugBreak(); 8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 8956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ------------------------------------------------------------------------- 898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Exception handling. 8993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Push a new try handler and link into try handler chain. 9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PushTryHandler(StackHandler::Kind kind, int handler_index); 9023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unlink the stack handler on top of the stack from the try handler chain. 9043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Must preserve the result register. 9053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void PopTryHandler(); 9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Passes thrown value to the handler of top of the try handler chain. 908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Throw(Register value); 909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Propagates an uncatchable exception to the top of the current JS stack's 911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // handler chain. 9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void ThrowUncatchable(Register value); 913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 91444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Copies a fixed number of fields of heap objects from src to dst. 91544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CopyFields(Register dst, Register src, RegList temps, int field_count); 9163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Copies a number of bytes from src to dst. All registers are clobbered. On 918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // exit src and dst will point to the place just after where the last byte was 919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // read or written and length will be zero. 920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void CopyBytes(Register src, 921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst, 922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register length, 923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch); 924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize fields with filler values. Fields starting at |start_offset| 9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // not including end_offset are overwritten with the value in |filler|. At 9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the end the loop, |start_offset| takes the value of |end_offset|. 9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InitializeFieldsWithFiller(Register start_offset, 9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register end_offset, 9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register filler); 9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 93244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ------------------------------------------------------------------------- 9333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Support functions. 9343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 93544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Try to get function prototype of a function and puts the value in 93644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // the result register. Checks that the function really is a 93744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // function and jumps to the miss label if the fast checks fail. The 93844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // function register will be untouched; the other registers may be 93944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // clobbered. 94044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void TryGetFunctionPrototype(Register function, 94144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result, 94244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss, 9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool miss_on_bound_function = false); 94544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void GetObjectType(Register function, 9476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register map, 9486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register type_reg); 9496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if a map for a JSObject indicates that the object has fast elements. 9513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Jump to the specified label if it does not. 9523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void CheckFastElements(Register map, 9533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch, 9543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* fail); 9553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if a map for a JSObject indicates that the object can have both smi 9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and HeapObject elements. Jump to the specified label if it does not. 9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckFastObjectElements(Register map, 9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail); 9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if a map for a JSObject indicates that the object has fast smi only 9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements. Jump to the specified label if it does not. 9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckFastSmiOnlyElements(Register map, 9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 9663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail); 9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check to see if maybe_number can be stored as a double in 9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FastDoubleElements. If it can, store it at the index specified by key in 9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the FastDoubleElements array elements. Otherwise jump to fail, in which 9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // case scratch2, scratch3 and scratch4 are unmodified. 9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void StoreNumberToDoubleElements(Register value_reg, 9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register key_reg, 9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver_reg, 9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements_reg, 9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch4, 9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fail); 9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compare an object's map with the specified map and its transitioned 9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Jumps to 9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // "branch_to" if the result of the comparison is "cond". If multiple map 9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compares are required, the compare sequences branches to early_success. 9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CompareMapAndBranch(Register obj, 9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map, 9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* early_success, 9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond, 9913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch_to, 9923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode = REQUIRE_EXACT_MAP); 9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the map of an object is equal to a specified map and branch to 9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // label if not. Skip the smi check if not required (object is known to be a 9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match 9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // against maps that are ElementsKind transition maps of the specificed map. 99844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CheckMap(Register obj, 99944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Map> map, 100144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* fail, 10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheckType smi_check_type, 10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode = REQUIRE_EXACT_MAP); 10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 100544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 100644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CheckMap(Register obj, 100744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 100844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::RootListIndex index, 100944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* fail, 1010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCheckType smi_check_type); 1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the map of an object is equal to a specified map and branch to a 1013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // specified target if equal. Skip the smi check if not required (object is 1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // known to be a heap object) 1015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void DispatchMap(Register obj, 1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch, 1017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Map> map, 1018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> success, 1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiCheckType smi_check_type); 10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Generates code for reporting that an illegal operation has 10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // occurred. 10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void IllegalOperation(int num_arguments); 10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load and check the instance type of an object for being a string. 10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Loads the type into the second argument register. 10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Returns a condition that will be enabled if the object was a string. 10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition IsObjectStringType(Register obj, 10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register type, 10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result) { 10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lw(type, FieldMemOperand(obj, HeapObject::kMapOffset)); 10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lbu(type, FieldMemOperand(type, Map::kInstanceTypeOffset)); 10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch And(type, type, Operand(kIsNotStringMask)); 10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(0, kStringTag); 10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return eq; 10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 104044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Picks out an array index from the hash field. 104144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Register use: 104244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // hash - holds the index's hash. Clobbered. 104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index - holds the overwritten index on exit. 104444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void IndexFromHash(Register hash, Register index); 104544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the number of least significant bits from a register. 1047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); 1048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); 1049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 105044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Load the value of a number object into a FPU double register. If the 105144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // object is not a number a jump to the label not_number is performed 105244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // and the FPU double register is unchanged. 105344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ObjectToDoubleFPURegister( 105444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register object, 105544f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegister value, 105644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 105744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 105844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register heap_number_map, 105944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* not_number, 106044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS); 106144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 106244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Load the value of a smi object into a FPU double register. The register 106344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scratch1 can be the same register as smi in which case smi will hold the 106444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // untagged value afterwards. 106544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SmiToDoubleFPURegister(Register smi, 106644f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegister value, 106744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1); 106844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 106944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ------------------------------------------------------------------------- 1070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Overflow handling functions. 1071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Usage: first call the appropriate arithmetic function, then call one of the 1072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // jump functions with the overflow_dst register as the second parameter. 1073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void AdduAndCheckForOverflow(Register dst, 1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left, 1076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right, 1077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register overflow_dst, 1078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch = at); 1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void SubuAndCheckForOverflow(Register dst, 1081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left, 1082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right, 1083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register overflow_dst, 1084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch = at); 1085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void BranchOnOverflow(Label* label, 1087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register overflow_check, 1088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BranchDelaySlot bd = PROTECT) { 1089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Branch(label, lt, overflow_check, Operand(zero_reg), bd); 1090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void BranchOnNoOverflow(Label* label, 1093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register overflow_check, 1094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BranchDelaySlot bd = PROTECT) { 1095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Branch(label, ge, overflow_check, Operand(zero_reg), bd); 1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void RetOnOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) { 1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Ret(lt, overflow_check, Operand(zero_reg), bd); 1100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void RetOnNoOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) { 1103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Ret(ge, overflow_check, Operand(zero_reg), bd); 1104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ------------------------------------------------------------------------- 1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Runtime calls. 11083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // See comments at the beginning of CEntryStub::Generate. 11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void PrepareCEntryArgs(int num_args) { 11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch li(s0, num_args); 11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch li(s1, (num_args - 1) * kPointerSize); 11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void PrepareCEntryFunction(const ExternalReference& ref) { 11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch li(s2, Operand(ref)); 11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Call a code stub. 11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallStub(CodeStub* stub, 11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond = cc_always, 11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register r1 = zero_reg, 11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const Operand& r2 = Operand(zero_reg), 11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BranchDelaySlot bd = PROTECT); 11253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 112644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Tail call a code stub (jump). 112744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void TailCallStub(CodeStub* stub); 112844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 112944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallJSExitStub(CodeStub* stub); 11303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Call a runtime routine. 113244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallRuntime(const Runtime::Function* f, int num_arguments); 113344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallRuntimeSaveDoubles(Runtime::FunctionId id); 11343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Convenience function: Same as above, but takes the fid instead. 11363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void CallRuntime(Runtime::FunctionId fid, int num_arguments); 11373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 113844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convenience function: call an external reference. 113944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallExternalReference(const ExternalReference& ext, 11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int num_arguments, 11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BranchDelaySlot bd = PROTECT); 114244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Tail call of a runtime routine (jump). 11446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Like JumpToExternalReference, but also takes care of passing the number 11453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // of parameters. 11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void TailCallExternalReference(const ExternalReference& ext, 11476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 11486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size); 11496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Convenience function: tail call a runtime routine (jump). 11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void TailCallRuntime(Runtime::FunctionId fid, 11523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int num_arguments, 11533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int result_size); 11543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int CalculateStackPassedWords(int num_reg_arguments, 11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int num_double_arguments); 11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 115844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Before calling a C-function from generated code, align arguments on stack 115944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // and add space for the four mips argument slots. 116044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // After aligning the frame, non-register arguments must be stored on the 116144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // stack, after the argument-slots using helper: CFunctionArgumentOperand(). 116244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The argument count assumes all arguments are word sized. 116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Some compilers/platforms require the stack to be aligned when calling 116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // C++ code. 116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Needs a scratch register to do some arithmetic. This register will be 116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // trashed. 11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PrepareCallCFunction(int num_reg_arguments, 11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int num_double_registers, 11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch); 11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PrepareCallCFunction(int num_reg_arguments, 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch); 117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 117344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Arguments 1-4 are placed in registers a0 thru a3 respectively. 117444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Arguments 5..n are stored to stack using following: 117544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // sw(t0, CFunctionArgumentOperand(5)); 117644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 117744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Calls a C function and cleans up the space for arguments allocated 117844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // by PrepareCallCFunction. The called function is not allowed to trigger a 117944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // garbage collection, since that might move the code and invalidate the 118044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // return address (unless this is somehow accounted for by the called 118144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // function). 118244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallCFunction(ExternalReference function, int num_arguments); 11833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallCFunction(Register function, int num_arguments); 11843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallCFunction(ExternalReference function, 11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int num_reg_arguments, 11863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int num_double_arguments); 11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallCFunction(Register function, 11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int num_reg_arguments, 11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int num_double_arguments); 1190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void GetCFunctionDoubleResult(const DoubleRegister dst); 1191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // There are two ways of passing double arguments on MIPS, depending on 1193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // whether soft or hard floating point ABI is used. These functions 1194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // abstract parameter passing for the three different ways we call 1195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // C functions from generated code. 1196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void SetCallCDoubleArguments(DoubleRegister dreg); 1197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2); 1198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void SetCallCDoubleArguments(DoubleRegister dreg, Register reg); 1199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calls an API function. Allocates HandleScope, extracts returned value 12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // from handle and propagates exceptions. Restores context. stack_space 12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // - space to be unwound on exit (includes the call JS arguments space and 12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the additional space allocated for the fast call). 12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CallApiFunctionAndReturn(ExternalReference function, int stack_space); 120544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Jump to the builtin routine. 12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpToExternalReference(const ExternalReference& builtin, 12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BranchDelaySlot bd = PROTECT); 12093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Invoke specified builtin JavaScript function. Adds an entry to 12113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // the unresolved list if the name does not resolve. 121244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void InvokeBuiltin(Builtins::JavaScript id, 1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InvokeFlag flag, 1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallWrapper& call_wrapper = NullCallWrapper()); 12153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Store the code object for the given builtin in the target register and 121744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // setup the function in a1. 12183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GetBuiltinEntry(Register target, Builtins::JavaScript id); 12193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 122044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Store the function for the given builtin in the target register. 122144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void GetBuiltinFunction(Register target, Builtins::JavaScript id); 122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu struct Unresolved { 12243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int pc; 1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t flags; // See Bootstrapper::FixupFlags decoders/encoders. 12263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu const char* name; 12273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 12283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Object> CodeObject() { 1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!code_object_.is_null()); 1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return code_object_; 1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 12333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 123444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ------------------------------------------------------------------------- 1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // StatsCounter support. 12363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void SetCounter(StatsCounter* counter, int value, 12383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, Register scratch2); 12393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void IncrementCounter(StatsCounter* counter, int value, 12403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, Register scratch2); 12413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void DecrementCounter(StatsCounter* counter, int value, 12423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, Register scratch2); 12433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 124544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ------------------------------------------------------------------------- 1246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Debugging. 12473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Calls Abort(msg) if the condition cc is not satisfied. 12493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Use --debug_code to enable. 12503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Assert(Condition cc, const char* msg, Register rs, Operand rt); 125144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index); 125244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AssertFastElements(Register elements); 12533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Like Assert(), but always enabled. 12553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Check(Condition cc, const char* msg, Register rs, Operand rt); 12563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Print a message to stdout and abort execution. 12583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Abort(const char* msg); 12593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Verify restrictions about code generated in stubs. 12613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void set_generating_stub(bool value) { generating_stub_ = value; } 12623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool generating_stub() { return generating_stub_; } 12633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } 12643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool allow_stub_calls() { return allow_stub_calls_; } 12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void set_has_frame(bool value) { has_frame_ = value; } 12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_frame() { return has_frame_; } 12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline bool AllowThisStubCall(CodeStub* stub); 12683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 126944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // --------------------------------------------------------------------------- 1270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Number utilities. 127144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 127244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check whether the value of reg is a power of two and not zero. If not 127344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // control continues at the label not_power_of_two. If reg is a power of two 127444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // the register scratch contains the value of (reg - 1) when control falls 127544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // through. 127644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void JumpIfNotPowerOfTwoOrZero(Register reg, 127744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 127844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* not_power_of_two_or_zero); 127944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 128044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ------------------------------------------------------------------------- 1281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Smi utilities. 128244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 128344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SmiTag(Register reg) { 128444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Addu(reg, reg, reg); 128544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 128644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow(). 12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void SmiTagCheckOverflow(Register reg, Register overflow); 12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void SmiTagCheckOverflow(Register dst, Register src, Register overflow); 12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 129144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SmiTag(Register dst, Register src) { 129244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Addu(dst, src, src); 129344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 129444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 129544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SmiUntag(Register reg) { 129644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sra(reg, reg, kSmiTagSize); 129744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 129844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 129944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SmiUntag(Register dst, Register src) { 130044f0eee88ff00398ff7f715fab053374d808c90dSteve Block sra(dst, src, kSmiTagSize); 130144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 130244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Untag the source value into destination and jump if source is a smi. 13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Souce and destination can be the same register. 13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case); 13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Untag the source value into destination and jump if source is not a smi. 13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Souce and destination can be the same register. 13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case); 13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 131144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Jump the register contains a smi. 13123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfSmi(Register value, 13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* smi_label, 13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = at, 13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BranchDelaySlot bd = PROTECT); 131644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 131744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Jump if the register contains a non-smi. 13183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpIfNotSmi(Register value, 13193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* not_smi_label, 13203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = at, 13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BranchDelaySlot bd = PROTECT); 132244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 132344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Jump if either of the registers contain a non-smi. 132444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); 132544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Jump if either of the registers contain a smi. 132644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); 132744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 132844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Abort execution if argument is a smi. Used in debug code. 132944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AbortIfSmi(Register object); 133044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AbortIfNotSmi(Register object); 133144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Abort execution if argument is a string. Used in debug code. 1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void AbortIfNotString(Register object); 1334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 133544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Abort execution if argument is not the root value with the given index. 133644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void AbortIfNotRootValue(Register src, 133744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::RootListIndex root_value_index, 133844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const char* message); 133944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 134044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // --------------------------------------------------------------------------- 1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // HeapNumber utilities. 134244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 134344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void JumpIfNotHeapNumber(Register object, 134444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register heap_number_map, 134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 134644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* on_not_heap_number); 134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 134844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ------------------------------------------------------------------------- 1349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // String utilities. 135044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Checks if both instance types are sequential ASCII strings and jumps to 135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // label if either is not. 135344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void JumpIfBothInstanceTypesAreNotSequentialAscii( 135444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register first_object_instance_type, 135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register second_object_instance_type, 135644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* failure); 135944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 136044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check if instance type is sequential ASCII string and jump to label if 136144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // it is not. 136244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void JumpIfInstanceTypeIsNotSequentialAscii(Register type, 136344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 136444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* failure); 136544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 136644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Test that both first and second are sequential ASCII strings. 136744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Assume that they are non-smis. 136844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void JumpIfNonSmisNotBothSequentialAsciiStrings(Register first, 136944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register second, 137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* failure); 137344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 137444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Test that both first and second are sequential ASCII strings. 137544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that they are non-smis. 137644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void JumpIfNotBothSequentialAsciiStrings(Register first, 137744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register second, 137844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 137944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 138044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* failure); 138144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void ClampUint8(Register output_reg, Register input_reg); 13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void ClampDoubleToUint8(Register result_reg, 13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoubleRegister input_reg, 13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoubleRegister temp_double_reg); 13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void LoadInstanceDescriptors(Register map, Register descriptors); 1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Activation support. 13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void EnterFrame(StackFrame::Type type); 13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void LeaveFrame(StackFrame::Type type); 13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Patch the relocated value (lui/ori pair). 13973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PatchRelocatedValue(Register li_location, 13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register new_value); 14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the relocatad value (loaded data) from the lui/ori pair. 14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void GetRelocatedValue(Register li_location, 14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value, 14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch); 14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Expects object in a0 and returns map with validated enum cache 14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in a0. Assumes that any other register can be used as a scratch. 14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CheckEnumCache(Register null_value, Label* call_runtime); 14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu private: 141044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CallCFunctionHelper(Register function, 14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int num_reg_arguments, 14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int num_double_arguments); 14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void BranchShort(int16_t offset, BranchDelaySlot bdslot = PROTECT); 14153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void BranchShort(int16_t offset, Condition cond, Register rs, 14163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const Operand& rt, 14173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BranchDelaySlot bdslot = PROTECT); 14183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void BranchShort(Label* L, BranchDelaySlot bdslot = PROTECT); 14193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void BranchShort(Label* L, Condition cond, Register rs, 14203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const Operand& rt, 14213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BranchDelaySlot bdslot = PROTECT); 14223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void BranchAndLinkShort(int16_t offset, BranchDelaySlot bdslot = PROTECT); 14233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void BranchAndLinkShort(int16_t offset, Condition cond, Register rs, 14243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const Operand& rt, 14253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BranchDelaySlot bdslot = PROTECT); 14263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void BranchAndLinkShort(Label* L, BranchDelaySlot bdslot = PROTECT); 14273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void BranchAndLinkShort(Label* L, Condition cond, Register rs, 14283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const Operand& rt, 14293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BranchDelaySlot bdslot = PROTECT); 14303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void J(Label* L, BranchDelaySlot bdslot); 14313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Jr(Label* L, BranchDelaySlot bdslot); 14323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Jalr(Label* L, BranchDelaySlot bdslot); 14333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Helper functions for generating invokes. 14356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void InvokePrologue(const ParameterCount& expected, 14366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& actual, 14376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Code> code_constant, 14386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register code_reg, 14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* done, 14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool* definitely_mismatches, 144144f0eee88ff00398ff7f715fab053374d808c90dSteve Block InvokeFlag flag, 14423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const CallWrapper& call_wrapper, 14433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallKind call_kind); 14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Get the code for the given builtin. Returns if able to resolve 14463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // the function in the 'resolved' flag. 14473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved); 14483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 144944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void InitializeNewString(Register string, 145044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register length, 145144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::RootListIndex map_index, 145244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 145344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2); 145444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace. 14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void InNewSpace(Register object, 14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond, // eq for new space, ne otherwise. 14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* branch); 14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for finding the mark bits for an address. Afterwards, the 14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // bitmap register points at the word with the mark bits and the mask 14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the position of the first bit. Leaves addr_reg unchanged. 14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline void GetMarkBits(Register addr_reg, 14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register bitmap_reg, 14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register mask_reg); 14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Helper for throwing exceptions. Compute a handler address and jump to 14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // it. See the implementation for register usage. 14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void JumpToHandlerEntry(); 14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute memory operands for safepoint stack slots. 1473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static int SafepointRegisterStackIndex(int reg_code); 1474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MemOperand SafepointRegisterSlot(Register reg); 1475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MemOperand SafepointRegistersAndDoublesSlot(Register reg); 147644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 147744f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool generating_stub_; 147844f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool allow_stub_calls_; 14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_frame_; 148044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // This handle will be patched with the code object on installation. 148144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Object> code_object_; 1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Needs access to SafepointRegisterStackIndex for optimized frame 1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // traversal. 1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch friend class OptimizedFrame; 148644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 148744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 148844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 148944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for 149044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// debugging and other types of instrumentation. When using the code patcher 149144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// the exact number of bytes specified must be emitted. It is not legal to emit 149244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// relocation information. If any of these constraints are violated it causes 149344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// an assertion to fail. 149444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass CodePatcher { 149544f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 149644f0eee88ff00398ff7f715fab053374d808c90dSteve Block CodePatcher(byte* address, int instructions); 149744f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual ~CodePatcher(); 149844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 149944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Macro assembler to emit code. 150044f0eee88ff00398ff7f715fab053374d808c90dSteve Block MacroAssembler* masm() { return &masm_; } 150144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 150244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Emit an instruction directly. 1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Emit(Instr instr); 150444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 150544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Emit an address directly. 150644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Emit(Address addr); 150744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Change the condition part of an instruction leaving the rest of the current 1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // instruction unchanged. 1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ChangeBranchCondition(Condition cond); 1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 151244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 151344f0eee88ff00398ff7f715fab053374d808c90dSteve Block byte* address_; // The address of the code being patched. 151444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int instructions_; // Number of instructions of the expected patch size. 151544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int size_; // Number of bytes of the expected patch size. 151644f0eee88ff00398ff7f715fab053374d808c90dSteve Block MacroAssembler masm_; // Macro assembler used to generate the code. 151744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 15183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifdef GENERATED_CODE_COVERAGE 15223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define CODE_COVERAGE_STRINGIFY(x) #x 15233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) 15243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) 15253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> 15263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#else 15273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define ACCESS_MASM(masm) masm-> 15283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#endif 15293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} } // namespace v8::internal 15313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#endif // V8_MIPS_MACRO_ASSEMBLER_MIPS_H_ 1533