macro-assembler-arm.h revision 25f6136652d8341ed047e7fc1a450af5bd218ea9
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2009 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_ARM_MACRO_ASSEMBLER_ARM_H_ 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "assembler.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ---------------------------------------------------------------------------- 373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Static helper functions 383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Generate a MemOperand for loading a field from an object. 403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescustatic inline MemOperand FieldMemOperand(Register object, int offset) { 413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return MemOperand(object, offset - kHeapObjectTag); 423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Give alias names to registers 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register cp = { 8 }; // JavaScript context pointer 473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuconst Register roots = { 10 }; // Roots array pointer. 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum InvokeJSFlags { 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CALL_JS, 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JUMP_JS 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen// Flags used for the AllocateInNewSpace functions. 5625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenenum AllocationFlags { 5725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // No special flags. 5825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen NO_ALLOCATION_FLAGS = 0, 5925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Return the pointer to the allocated already tagged as a heap object. 6025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen TAG_OBJECT = 1 << 0, 6125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // The content of the result register already contains the allocation top in 6225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // new space. 6325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen RESULT_CONTAINS_TOP = 1 << 1, 6425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Specify that the requested size of the space to allocate is specified in 6525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // words instead of bytes. 6625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen SIZE_IN_WORDS = 1 << 2 6725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}; 6825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 6925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implements a collection of frequently used macros. 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacroAssembler: public Assembler { 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler(void* buffer, int size); 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Jump, Call, and Ret pseudo instructions implementing inter-working. 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Jump(Register target, Condition cond = al); 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Jump(byte* target, RelocInfo::Mode rmode, Condition cond = al); 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Call(Register target, Condition cond = al); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al); 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Ret(Condition cond = al); 83e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 84e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit code to discard a non-negative number of pointer-sized elements 85e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // from the stack, clobbering only the sp register. 86e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Drop(int count, Condition cond = al); 87e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Swap two registers. If the scratch register is omitted then a slightly 906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // less efficient form using xor instead of mov is emitted. 916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Swap(Register reg1, Register reg2, Register scratch = no_reg); 926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 93e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Call(Label* target); 94e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Move(Register dst, Handle<Object> value); 956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // May do nothing if the registers are identical. 966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Move(Register dst, Register src); 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jumps to the label at the index given by the Smi in "index". 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SmiJumpTable(Register index, Vector<Label*> targets); 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load an object from the root table. 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LoadRoot(Register destination, 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Heap::RootListIndex index, 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond = al); 10325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Store an object to the root table. 10425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen void StoreRoot(Register source, 10525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Heap::RootListIndex index, 10625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Condition cond = al); 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if object is in new space. 1106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // scratch can be object itself, but it will be clobbered. 1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void InNewSpace(Register object, 1126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 1136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Condition cc, // eq for new space, ne otherwise 1146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* branch); 1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set the remebered set bit for an offset into an 1186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // object. RecordWriteHelper only works if the object is not in new 1196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // space. 1206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void RecordWriteHelper(Register object, Register offset, Register scracth); 1216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Sets the remembered set bit for [address+offset], where address is the 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // address of the heap object 'object'. The address must be in the first 8K 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of an allocated page. The 'scratch' register is used in the 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // implementation and all 3 registers are clobbered by the operation, as 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // well as the ip register. 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordWrite(Register object, Register offset, Register scratch); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push two registers. Pushes leftmost register first (to highest address). 1306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Push(Register src1, Register src2, Condition cond = al) { 1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!src1.is(src2)); 1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src1.code() > src2.code()) { 1336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit(), cond); 1346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src1, MemOperand(sp, 4, NegPreIndex), cond); 1366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src2, MemOperand(sp, 4, NegPreIndex), cond); 1376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push three registers. Pushes leftmost register first (to highest address). 1416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Push(Register src1, Register src2, Register src3, Condition cond = al) { 1426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!src1.is(src2)); 1436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!src2.is(src3)); 1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!src1.is(src3)); 1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src1.code() > src2.code()) { 1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src2.code() > src3.code()) { 1476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 1486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit(), cond); 1506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src3, MemOperand(sp, 4, NegPreIndex), cond); 1516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src1, MemOperand(sp, 4, NegPreIndex), cond); 1546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Push(src2, src3, cond); 1556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push four registers. Pushes leftmost register first (to highest address). 1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Push(Register src1, Register src2, 1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register src3, Register src4, Condition cond = al) { 1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!src1.is(src2)); 1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!src2.is(src3)); 1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!src1.is(src3)); 1646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!src1.is(src4)); 1656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!src2.is(src4)); 1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!src3.is(src4)); 1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src1.code() > src2.code()) { 1686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src2.code() > src3.code()) { 1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (src3.code() > src4.code()) { 1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, 1716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block sp, 1726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block src1.bit() | src2.bit() | src3.bit() | src4.bit(), 1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cond); 1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src4, MemOperand(sp, 4, NegPreIndex), cond); 1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block stm(db_w, sp, src1.bit() | src2.bit(), cond); 1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Push(src3, src4, cond); 1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block str(src1, MemOperand(sp, 4, NegPreIndex), cond); 1846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Push(src2, src3, src4, cond); 1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Stack limit support 190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void StackLimitCheck(Label* on_stack_limit_hit); 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // --------------------------------------------------------------------------- 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Activation frames 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); } 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); } 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); } 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); } 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Enter specific kind of exit frame; either normal or debug mode. 203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Expects the number of arguments in register r0 and 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the builtin function to call in register r1. Exits with argc in 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4, argv in r6, and and the builtin function to call in r5. 206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void EnterExitFrame(ExitFrame::Mode mode); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leave the current exit frame. Expects the return value in r0. 209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void LeaveExitFrame(ExitFrame::Mode mode); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the actual activation frame alignment for target environment. 2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static int ActivationFrameAlignment(); 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void LoadContext(Register dst, int context_chain_length); 215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // JavaScript invokes 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function code by either calling or jumping. 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeCode(Register code, 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag); 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeCode(Handle<Code> code, 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& expected, 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode, 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag); 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript function in the given register. Changes the 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // current context to the context in the function before invoking. 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeFunction(Register function, 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 237402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void InvokeFunction(JSFunction* function, 238402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& actual, 239402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InvokeFlag flag); 240402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugger Support 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SaveRegistersToMemory(RegList regs); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RestoreRegistersFromMemory(RegList regs); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CopyRegistersFromMemoryToStack(Register base, RegList regs); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CopyRegistersFromStackToMemory(Register base, 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegList regs); 252402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void DebugBreak(); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exception handling 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push a new try handler and link into try handler chain. 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The return address must be passed in register lr. 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On exit, r0 contains TOS (code slot). 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PushTryHandler(CodeLocation try_location, HandlerType type); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Unlink the stack handler on top of the stack from the try handler chain. 264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Must preserve the result register. 265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void PopTryHandler(); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Inline caching support 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generates code that verifies that the maps of objects in the 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototype chain of object hasn't changed since the code was 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // generated and branches to the miss label if any map has. If 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary the function also generates code for security check 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in case of global object holders. The scratch and holder 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // registers are always clobbered, but the object register is only 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // clobbered if it the same as the holder register. The function 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // returns a register containing the holder - either object_reg or 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // holder_reg. 2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // The function can optionally (when save_at_depth != 2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // kInvalidProtoDepth) save the object at the given depth by moving 2816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // it to [sp]. 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register CheckMaps(JSObject* object, Register object_reg, 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, Register holder_reg, 2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int save_at_depth, 2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate code for checking access rights - used for security checks 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on access to global objects across environments. The holder register 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is left untouched, whereas both scratch registers are clobbered. 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CheckAccessGlobalProxy(Register holder_reg, 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocation support 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate an object in new space. The object_size is specified in words (not 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bytes). If the new space is exhausted control continues at the gc_required 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // label. The allocated object is returned in result. If the flag 30225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // tag_allocated_object is true the result is tagged as as a heap object. All 30325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // registers are clobbered also when control continues at the gc_required 30425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // label. 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(int object_size, 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateInNewSpace(Register object_size, 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required, 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocationFlags flags); 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Undo allocation in new space. The object passed and objects allocated after 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // it will no longer be allocated. The caller must make sure that no pointers 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // are left to the object(s) no longer allocated as they would be invalid when 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allocation is undone. 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UndoAllocationInNewSpace(Register object, Register scratch); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void AllocateTwoByteString(Register result, 3263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register length, 3273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, 3283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch2, 3293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch3, 3303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* gc_required); 3313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void AllocateAsciiString(Register result, 3323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register length, 3333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, 3343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch2, 3353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch3, 3363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* gc_required); 3373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void AllocateTwoByteConsString(Register result, 3383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register length, 3393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, 3403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch2, 3413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* gc_required); 3423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void AllocateAsciiConsString(Register result, 3433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register length, 3443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, 3453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch2, 3463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* gc_required); 3473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 34825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Allocates a heap number or jumps to the gc_required label if the young 34925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // space is full and a scavenge is needed. All registers are clobbered also 35025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // when control continues at the gc_required label. 3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void AllocateHeapNumber(Register result, 3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* gc_required); 3553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Support functions. 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Try to get function prototype of a function and puts the value in 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the result register. Checks that the function really is a 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // function and jumps to the miss label if the fast checks fail. The 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // function register will be untouched; the other registers may be 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // clobbered. 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void TryGetFunctionPrototype(Register function, 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss); 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare object type for heap object. heap_object contains a non-Smi 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // whose object type should be compared with the given type. This both 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sets the flags and leaves the object type in the type_reg register. 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // It leaves the map in the map register (unless the type_reg and map register 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // are the same register). It leaves the heap object in the heap_object 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register unless the heap_object register is the same register as one of the 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // other registers. 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompareObjectType(Register heap_object, 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register map, 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register type_reg, 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type); 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare instance type in a map. map contains a valid map object whose 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object type should be compared with the given type. This both 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sets the flags and leaves the object type in the type_reg register. It 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // leaves the heap object in the heap_object register unless the heap_object 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register is the same register as type_reg. 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompareInstanceType(Register map, 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register type_reg, 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstanceType type); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Check if the map of an object is equal to a specified map and 3923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // branch to label if not. Skip the smi check if not required 3933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // (object is known to be a heap object) 3943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void CheckMap(Register obj, 3953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch, 3963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Map> map, 3973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* fail, 3983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool is_heap_object); 3993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Load and check the instance type of an object for being a string. 4013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Loads the type into the second argument register. 4023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Returns a condition that will be enabled if the object was a string. 4033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Condition IsObjectStringType(Register obj, 4043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register type) { 4053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset)); 4063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset)); 4073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu tst(type, Operand(kIsNotStringMask)); 4083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT_EQ(0, kStringTag); 4093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return eq; 4103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 4113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void BranchOnSmi(Register value, Label* smi_label) { 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tst(value, Operand(kSmiTagMask)); 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block b(eq, smi_label); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void BranchOnNotSmi(Register value, Label* not_smi_label) { 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tst(value, Operand(kSmiTagMask)); 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block b(ne, not_smi_label); 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generates code for reporting that an illegal operation has 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // occurred. 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void IllegalOperation(int num_arguments); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Get the number of least significant bits from a register 4283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); 4293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Uses VFP instructions to Convert a Smi to a double. 431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void IntegerToDoubleConversionWithVFP3(Register inReg, 432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register outHighReg, 433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Register outLowReg); 434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz 4366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // instruction. On pre-ARM5 hardware this routine gives the wrong answer 4376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // for 0 (31 instead of 32). 4386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CountLeadingZeros(Register source, 4396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register zeros); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Runtime calls 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call a code stub. 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CallStub(CodeStub* stub, Condition cond = al); 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Call a code stub. 4493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void TailCallStub(CodeStub* stub, Condition cond = al); 4503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return from a code stub after popping its arguments. 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void StubReturn(int argc); 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call a runtime routine. 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CallRuntime(Runtime::Function* f, int num_arguments); 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convenience function: Same as above, but takes the fid instead. 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CallRuntime(Runtime::FunctionId fid, int num_arguments); 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Convenience function: call an external reference. 461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void CallExternalReference(const ExternalReference& ext, 462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int num_arguments); 463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tail call of a runtime routine (jump). 4656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Like JumpToExternalReference, but also takes care of passing the number 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of parameters. 4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void TailCallExternalReference(const ExternalReference& ext, 4686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int num_arguments, 4696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size); 4706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Convenience function: tail call a runtime routine (jump). 4726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void TailCallRuntime(Runtime::FunctionId fid, 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_arguments, 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result_size); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Before calling a C-function from generated code, align arguments on stack. 4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // After aligning the frame, non-register arguments must be stored in 4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments 4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // are word sized. 4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Some compilers/platforms require the stack to be aligned when calling 4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // C++ code. 4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Needs a scratch register to do some arithmetic. This register will be 4836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // trashed. 4846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void PrepareCallCFunction(int num_arguments, Register scratch); 4856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Calls a C function and cleans up the space for arguments allocated 4876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // by PrepareCallCFunction. The called function is not allowed to trigger a 4886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // garbage collection, since that might move the code and invalidate the 4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // return address (unless this is somehow accounted for by the called 4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // function). 4916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CallCFunction(ExternalReference function, int num_arguments); 4926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CallCFunction(Register function, int num_arguments); 4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to a runtime routine. 4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void JumpToExternalReference(const ExternalReference& builtin); 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke specified builtin JavaScript function. Adds an entry to 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the unresolved list if the name does not resolve. 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokeBuiltin(Builtins::JavaScript id, InvokeJSFlags flags); 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the code object for the given builtin in the target register and 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // setup the function in r1. 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GetBuiltinEntry(Register target, Builtins::JavaScript id); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> CodeObject() { return code_object_; } 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // StatsCounter support 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetCounter(StatsCounter* counter, int value, 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, Register scratch2); 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void IncrementCounter(StatsCounter* counter, int value, 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, Register scratch2); 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void DecrementCounter(StatsCounter* counter, int value, 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, Register scratch2); 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugging 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calls Abort(msg) if the condition cc is not satisfied. 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use --debug_code to enable. 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Assert(Condition cc, const char* msg); 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Like Assert(), but always enabled. 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Check(Condition cc, const char* msg); 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print a message to stdout and abort execution. 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Abort(const char* msg); 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Verify restrictions about code generated in stubs. 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_generating_stub(bool value) { generating_stub_ = value; } 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool generating_stub() { return generating_stub_; } 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool allow_stub_calls() { return allow_stub_calls_; } 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 538d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // --------------------------------------------------------------------------- 5393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Smi utilities 5403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Jump if either of the registers contain a non-smi. 5423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); 5433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Jump if either of the registers contain a smi. 5443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); 5453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // --------------------------------------------------------------------------- 547d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // String utilities 548d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 549d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Checks if both objects are sequential ASCII strings and jumps to label 550d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // if either is not. Assumes that neither object is a smi. 551d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1, 552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register object2, 553d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch1, 554d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch2, 5556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* failure); 556d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 557d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Checks if both objects are sequential ASCII strings and jumps to label 558d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // if either is not. 559d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void JumpIfNotBothSequentialAsciiStrings(Register first, 560d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register second, 561d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch1, 562d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Register scratch2, 563d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label* not_flat_ascii_strings); 564d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Checks if both instance types are sequential ASCII strings and jumps to 5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // label if either is not. 5676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void JumpIfBothInstanceTypesAreNotSequentialAscii( 5686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register first_object_instance_type, 5696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register second_object_instance_type, 5706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 5716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 5726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* failure); 5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if instance type is sequential ASCII string and jump to label if 5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // it is not. 5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void JumpIfInstanceTypeIsNotSequentialAscii(Register type, 5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* failure); 5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 5823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); 5833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Helper functions for generating invokes. 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void InvokePrologue(const ParameterCount& expected, 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& actual, 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_constant, 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register code_reg, 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* done, 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InvokeFlag flag); 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Activation support. 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void EnterFrame(StackFrame::Type type); 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LeaveFrame(StackFrame::Type type); 5963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void InitializeNewString(Register string, 5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register length, 5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Heap::RootListIndex map_index, 6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 6016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2); 6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool generating_stub_; 6043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool allow_stub_calls_; 6053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // This handle will be patched with the code object on installation. 6063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Handle<Object> code_object_; 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. It is not legal to emit 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion to fail. 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher { 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodePatcher(byte* address, int instructions); 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~CodePatcher(); 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Macro assembler to emit code. 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler* masm() { return &masm_; } 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit an instruction directly. 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Emit(Instr x); 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit an address directly. 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Emit(Address addr); 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* address_; // The address of the code being patched. 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int instructions_; // Number of instructions of the expected patch size. 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_; // Number of bytes of the expected patch size. 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacroAssembler masm_; // Macro assembler used to generate the code. 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_DEBUGGER_SUPPORT 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions. 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef GENERATED_CODE_COVERAGE 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_STRINGIFY(x) #x 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm-> 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ 655