15c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Copyright (c) 1994-2006 Sun Microsystems Inc. 25c838251403b0be9a882540f1922577abba4c872ager@chromium.org// All Rights Reserved. 35c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 45c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Redistribution and use in source and binary forms, with or without 55c838251403b0be9a882540f1922577abba4c872ager@chromium.org// modification, are permitted provided that the following conditions are 65c838251403b0be9a882540f1922577abba4c872ager@chromium.org// met: 75c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 85c838251403b0be9a882540f1922577abba4c872ager@chromium.org// - Redistributions of source code must retain the above copyright notice, 95c838251403b0be9a882540f1922577abba4c872ager@chromium.org// this list of conditions and the following disclaimer. 105c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 115c838251403b0be9a882540f1922577abba4c872ager@chromium.org// - Redistribution in binary form must reproduce the above copyright 125c838251403b0be9a882540f1922577abba4c872ager@chromium.org// notice, this list of conditions and the following disclaimer in the 135c838251403b0be9a882540f1922577abba4c872ager@chromium.org// documentation and/or other materials provided with the distribution. 145c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 155c838251403b0be9a882540f1922577abba4c872ager@chromium.org// - Neither the name of Sun Microsystems or the names of contributors may 165c838251403b0be9a882540f1922577abba4c872ager@chromium.org// be used to endorse or promote products derived from this software without 175c838251403b0be9a882540f1922577abba4c872ager@chromium.org// specific prior written permission. 185c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 195c838251403b0be9a882540f1922577abba4c872ager@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 205c838251403b0be9a882540f1922577abba4c872ager@chromium.org// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 215c838251403b0be9a882540f1922577abba4c872ager@chromium.org// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 225c838251403b0be9a882540f1922577abba4c872ager@chromium.org// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 235c838251403b0be9a882540f1922577abba4c872ager@chromium.org// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 245c838251403b0be9a882540f1922577abba4c872ager@chromium.org// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 255c838251403b0be9a882540f1922577abba4c872ager@chromium.org// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 265c838251403b0be9a882540f1922577abba4c872ager@chromium.org// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 275c838251403b0be9a882540f1922577abba4c872ager@chromium.org// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 285c838251403b0be9a882540f1922577abba4c872ager@chromium.org// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 295c838251403b0be9a882540f1922577abba4c872ager@chromium.org// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 305c838251403b0be9a882540f1922577abba4c872ager@chromium.org 315c838251403b0be9a882540f1922577abba4c872ager@chromium.org// The original source code covered by the above license above has been 325c838251403b0be9a882540f1922577abba4c872ager@chromium.org// modified significantly by Google Inc. 332efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 345c838251403b0be9a882540f1922577abba4c872ager@chromium.org 355c838251403b0be9a882540f1922577abba4c872ager@chromium.org 365c838251403b0be9a882540f1922577abba4c872ager@chromium.org#ifndef V8_MIPS_ASSEMBLER_MIPS_H_ 375c838251403b0be9a882540f1922577abba4c872ager@chromium.org#define V8_MIPS_ASSEMBLER_MIPS_H_ 385c838251403b0be9a882540f1922577abba4c872ager@chromium.org 395c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include <stdio.h> 4069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 41196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/assembler.h" 42196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/mips/constants-mips.h" 43196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/serialize.h" 445c838251403b0be9a882540f1922577abba4c872ager@chromium.org 455c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace v8 { 465c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace internal { 475c838251403b0be9a882540f1922577abba4c872ager@chromium.org 485c838251403b0be9a882540f1922577abba4c872ager@chromium.org// CPU Registers. 495c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 505c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 1) We would prefer to use an enum, but enum values are assignment- 515c838251403b0be9a882540f1922577abba4c872ager@chromium.org// compatible with int, which has caused code-generation bugs. 525c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 535c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 2) We would prefer to use a class instead of a struct but we don't like 545c838251403b0be9a882540f1922577abba4c872ager@chromium.org// the register initialization to depend on the particular initialization 555c838251403b0be9a882540f1922577abba4c872ager@chromium.org// order (which appears to be different on OS X, Linux, and Windows for the 565c838251403b0be9a882540f1922577abba4c872ager@chromium.org// installed versions of C++ we tried). Using a struct permits C-style 575c838251403b0be9a882540f1922577abba4c872ager@chromium.org// "initialization". Also, the Register objects cannot be const as this 585c838251403b0be9a882540f1922577abba4c872ager@chromium.org// forces initialization stubs in MSVC, making us dependent on initialization 595c838251403b0be9a882540f1922577abba4c872ager@chromium.org// order. 605c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 615c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 3) By not using an enum, we are possibly preventing the compiler from 625c838251403b0be9a882540f1922577abba4c872ager@chromium.org// doing certain constant folds, which may significantly reduce the 635c838251403b0be9a882540f1922577abba4c872ager@chromium.org// code generated for some assembly instructions (because they boil down 645c838251403b0be9a882540f1922577abba4c872ager@chromium.org// to a few constants). If this is a problem, we could change the code 655c838251403b0be9a882540f1922577abba4c872ager@chromium.org// such that we use an enum in optimized mode, and the struct in debug 665c838251403b0be9a882540f1922577abba4c872ager@chromium.org// mode. This way we get the compile-time error checking in debug mode 675c838251403b0be9a882540f1922577abba4c872ager@chromium.org// and best performance in optimized code. 685c838251403b0be9a882540f1922577abba4c872ager@chromium.org 695c838251403b0be9a882540f1922577abba4c872ager@chromium.org 705c838251403b0be9a882540f1922577abba4c872ager@chromium.org// ----------------------------------------------------------------------------- 7183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org// Implementation of Register and FPURegister. 725c838251403b0be9a882540f1922577abba4c872ager@chromium.org 735c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Core register. 745c838251403b0be9a882540f1922577abba4c872ager@chromium.orgstruct Register { 757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kNumRegisters = v8::internal::kNumRegisters; 76fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org static const int kMaxNumAllocatableRegisters = 14; // v0 through t6 and cp. 7783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static const int kSizeInBytes = 4; 78fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org static const int kCpRegister = 23; // cp (s7) is the 23rd register. 7959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org 80731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org#if defined(V8_TARGET_LITTLE_ENDIAN) 81731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org static const int kMantissaOffset = 0; 82731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org static const int kExponentOffset = 4; 83731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org#elif defined(V8_TARGET_BIG_ENDIAN) 84731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org static const int kMantissaOffset = 4; 85731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org static const int kExponentOffset = 0; 86731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org#else 87731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org#error Unknown endianness 88731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org#endif 89731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org 9059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org inline static int NumAllocatableRegisters(); 917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static int ToAllocationIndex(Register reg) { 93fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org ASSERT((reg.code() - 2) < (kMaxNumAllocatableRegisters - 1) || 94fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org reg.is(from_code(kCpRegister))); 95fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org return reg.is(from_code(kCpRegister)) ? 96fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org kMaxNumAllocatableRegisters - 1 : // Return last index for 'cp'. 97fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org reg.code() - 2; // zero_reg and 'at' are skipped. 987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 1007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static Register FromAllocationIndex(int index) { 10159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); 102fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org return index == kMaxNumAllocatableRegisters - 1 ? 103fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org from_code(kCpRegister) : // Last index is always the 'cp' register. 104fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org from_code(index + 2); // zero_reg and 'at' are skipped. 1057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 1067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 1077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const char* AllocationIndexToString(int index) { 10859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); 1097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org const char* const names[] = { 1107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "v0", 1117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "v1", 1127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "a0", 1137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "a1", 1147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "a2", 1157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "a3", 1167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "t0", 1177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "t1", 1187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "t2", 1197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "t3", 1207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "t4", 1217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "t5", 1227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org "t6", 123fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org "s7", 1247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org }; 1257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return names[index]; 1267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 1277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 1287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static Register from_code(int code) { 1297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org Register r = { code }; 1307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return r; 1317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 1327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 1334a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 1344a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org bool is(Register reg) const { return code_ == reg.code_; } 1354a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org int code() const { 1365c838251403b0be9a882540f1922577abba4c872ager@chromium.org ASSERT(is_valid()); 1375c838251403b0be9a882540f1922577abba4c872ager@chromium.org return code_; 1385c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 1394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org int bit() const { 1405c838251403b0be9a882540f1922577abba4c872ager@chromium.org ASSERT(is_valid()); 1415c838251403b0be9a882540f1922577abba4c872ager@chromium.org return 1 << code_; 1425c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 1435c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1445c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Unfortunately we can't make this private in a struct. 1455c838251403b0be9a882540f1922577abba4c872ager@chromium.org int code_; 1465c838251403b0be9a882540f1922577abba4c872ager@chromium.org}; 1475c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1487d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org#define REGISTER(N, C) \ 1497d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org const int kRegister_ ## N ## _Code = C; \ 1507d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org const Register N = { C } 1517d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org 1527d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(no_reg, -1); 1537d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// Always zero. 1547d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(zero_reg, 0); 1557d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// at: Reserved for synthetic instructions. 1567d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(at, 1); 1577d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// v0, v1: Used when returning multiple values from subroutines. 1587d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(v0, 2); 1597d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(v1, 3); 1607d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// a0 - a4: Used to pass non-FP parameters. 1617d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a0, 4); 1627d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a1, 5); 1637d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a2, 6); 1647d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a3, 7); 1657d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// t0 - t9: Can be used without reservation, act as temporary registers and are 1667d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// allowed to be destroyed by subroutines. 1677d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t0, 8); 1687d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t1, 9); 1697d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t2, 10); 1707d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t3, 11); 1717d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t4, 12); 1727d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t5, 13); 1737d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t6, 14); 1747d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t7, 15); 1757d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// s0 - s7: Subroutine register variables. Subroutines that write to these 1767d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// registers must restore their values before exiting so that the caller can 1777d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// expect the values to be preserved. 1787d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s0, 16); 1797d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s1, 17); 1807d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s2, 18); 1817d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s3, 19); 1827d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s4, 20); 1837d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s5, 21); 1847d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s6, 22); 1857d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s7, 23); 1867d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t8, 24); 1877d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t9, 25); 1887d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// k0, k1: Reserved for system calls and interrupt handlers. 1897d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(k0, 26); 1907d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(k1, 27); 1917d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// gp: Reserved. 1927d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(gp, 28); 1937d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// sp: Stack pointer. 1947d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(sp, 29); 1957d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// fp: Frame pointer. 1967d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(fp, 30); 1977d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// ra: Return address pointer. 1987d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(ra, 31); 1997d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org 2007d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org#undef REGISTER 2017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 2025c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2035c838251403b0be9a882540f1922577abba4c872ager@chromium.orgint ToNumber(Register reg); 2045c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2055c838251403b0be9a882540f1922577abba4c872ager@chromium.orgRegister ToRegister(int num); 2065c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2075c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Coprocessor register. 2085c838251403b0be9a882540f1922577abba4c872ager@chromium.orgstruct FPURegister { 2097c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org static const int kMaxNumRegisters = v8::internal::kNumFPURegisters; 21034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 21134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers 21234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to 21334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // number of Double regs (64-bit regs, or FPU-reg-pairs). 21434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 21534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // A few double registers are reserved: one as a scratch register and one to 21634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // hold 0.0. 21734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // f28: 0.0 21834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // f30: scratch register. 21934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static const int kNumReservedRegisters = 2; 2207c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org static const int kMaxNumAllocatableRegisters = kMaxNumRegisters / 2 - 22134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org kNumReservedRegisters; 22234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 22359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org inline static int NumRegisters(); 22459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org inline static int NumAllocatableRegisters(); 2252efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org inline static int ToAllocationIndex(FPURegister reg); 22659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org static const char* AllocationIndexToString(int index); 2277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 2287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static FPURegister FromAllocationIndex(int index) { 22959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); 23034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org return from_code(index * 2); 2317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 2327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 2337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static FPURegister from_code(int code) { 2347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org FPURegister r = { code }; 2357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return r; 2367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 2377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 2387c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; } 2394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org bool is(FPURegister creg) const { return code_ == creg.code_; } 24034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org FPURegister low() const { 24134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // Find low reg of a Double-reg pair, which is the reg itself. 24234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org ASSERT(code_ % 2 == 0); // Specified Double reg must be even. 24334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org FPURegister reg; 24434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org reg.code_ = code_; 24534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org ASSERT(reg.is_valid()); 24634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org return reg; 24734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org } 24834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org FPURegister high() const { 24934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // Find high reg of a Doubel-reg pair, which is reg + 1. 25034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org ASSERT(code_ % 2 == 0); // Specified Double reg must be even. 25134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org FPURegister reg; 25234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org reg.code_ = code_ + 1; 25334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org ASSERT(reg.is_valid()); 25434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org return reg; 25534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org } 25634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 2574a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org int code() const { 2585c838251403b0be9a882540f1922577abba4c872ager@chromium.org ASSERT(is_valid()); 2595c838251403b0be9a882540f1922577abba4c872ager@chromium.org return code_; 2605c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 2614a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org int bit() const { 2625c838251403b0be9a882540f1922577abba4c872ager@chromium.org ASSERT(is_valid()); 2635c838251403b0be9a882540f1922577abba4c872ager@chromium.org return 1 << code_; 2645c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 2657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void setcode(int f) { 2667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org code_ = f; 2677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org ASSERT(is_valid()); 2687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 2695c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Unfortunately we can't make this private in a struct. 2705c838251403b0be9a882540f1922577abba4c872ager@chromium.org int code_; 2715c838251403b0be9a882540f1922577abba4c872ager@chromium.org}; 2725c838251403b0be9a882540f1922577abba4c872ager@chromium.org 27334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// V8 now supports the O32 ABI, and the FPU Registers are organized as 32 27434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// 32-bit registers, f0 through f31. When used as 'double' they are used 27534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// in pairs, starting with the even numbered register. So a double operation 27634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// on f0 really uses f0 and f1. 27734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// (Modern mips hardware also supports 32 64-bit registers, via setting 27834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// (priviledged) Status Register FR bit to 1. This is used by the N32 ABI, 27934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// but it is not in common use. Someday we will want to support this in v8.) 28034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 28134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers. 2827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgtypedef FPURegister DoubleRegister; 28334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgtypedef FPURegister FloatRegister; 2847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 28534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgconst FPURegister no_freg = { -1 }; 2867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 2877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f0 = { 0 }; // Return value in hard float mode. 2887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f1 = { 1 }; 2897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f2 = { 2 }; 2907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f3 = { 3 }; 2917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f4 = { 4 }; 2927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f5 = { 5 }; 2937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f6 = { 6 }; 2947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f7 = { 7 }; 2957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f8 = { 8 }; 2967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f9 = { 9 }; 2977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f10 = { 10 }; 2987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f11 = { 11 }; 2997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f12 = { 12 }; // Arg 0 in hard float mode. 3007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f13 = { 13 }; 3017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f14 = { 14 }; // Arg 1 in hard float mode. 3027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f15 = { 15 }; 3037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f16 = { 16 }; 3047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f17 = { 17 }; 3057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f18 = { 18 }; 3067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f19 = { 19 }; 3077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f20 = { 20 }; 3087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f21 = { 21 }; 3097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f22 = { 22 }; 3107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f23 = { 23 }; 3117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f24 = { 24 }; 3127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f25 = { 25 }; 3137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f26 = { 26 }; 3147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f27 = { 27 }; 3157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f28 = { 28 }; 3167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f29 = { 29 }; 3177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f30 = { 30 }; 3187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f31 = { 31 }; 3197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 3202efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org// Register aliases. 3212efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org// cp is assumed to be a callee saved register. 32289e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org// Defined using #define instead of "static const Register&" because Clang 32389e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org// complains otherwise when a compilation unit that includes this header 32489e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org// doesn't use the variables. 32589e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kRootRegister s6 32689e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define cp s7 32789e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kLithiumScratchReg s3 32889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kLithiumScratchReg2 s4 32989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kLithiumScratchDouble f30 33089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kDoubleRegZero f28 33134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 3327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// FPU (coprocessor 1) control registers. 3337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Currently only FCSR (#31) is implemented. 3347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgstruct FPUControlRegister { 3357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org bool is_valid() const { return code_ == kFCSRRegister; } 3367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org bool is(FPUControlRegister creg) const { return code_ == creg.code_; } 3377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int code() const { 3387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org ASSERT(is_valid()); 3397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return code_; 3407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 3417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int bit() const { 3427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org ASSERT(is_valid()); 3437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return 1 << code_; 3447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 3457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void setcode(int f) { 3467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org code_ = f; 3477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org ASSERT(is_valid()); 3487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 3497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Unfortunately we can't make this private in a struct. 3507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int code_; 3515c838251403b0be9a882540f1922577abba4c872ager@chromium.org}; 3525c838251403b0be9a882540f1922577abba4c872ager@chromium.org 35383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgconst FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister }; 3547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPUControlRegister FCSR = { kFCSRRegister }; 3555c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3565c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3575c838251403b0be9a882540f1922577abba4c872ager@chromium.org// ----------------------------------------------------------------------------- 3585c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Machine instruction Operands. 3595c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3605c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Class Operand represents a shifter operand in data processing instructions. 3615c838251403b0be9a882540f1922577abba4c872ager@chromium.orgclass Operand BASE_EMBEDDED { 3625c838251403b0be9a882540f1922577abba4c872ager@chromium.org public: 3635c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Immediate. 3645c838251403b0be9a882540f1922577abba4c872ager@chromium.org INLINE(explicit Operand(int32_t immediate, 36559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org RelocInfo::Mode rmode = RelocInfo::NONE32)); 3665c838251403b0be9a882540f1922577abba4c872ager@chromium.org INLINE(explicit Operand(const ExternalReference& f)); 3675c838251403b0be9a882540f1922577abba4c872ager@chromium.org INLINE(explicit Operand(const char* s)); 3685c838251403b0be9a882540f1922577abba4c872ager@chromium.org INLINE(explicit Operand(Object** opp)); 3695c838251403b0be9a882540f1922577abba4c872ager@chromium.org INLINE(explicit Operand(Context** cpp)); 3705c838251403b0be9a882540f1922577abba4c872ager@chromium.org explicit Operand(Handle<Object> handle); 3715c838251403b0be9a882540f1922577abba4c872ager@chromium.org INLINE(explicit Operand(Smi* value)); 3725c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3735c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Register. 3745c838251403b0be9a882540f1922577abba4c872ager@chromium.org INLINE(explicit Operand(Register rm)); 3755c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3765c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Return true if this is a register operand. 3775c838251403b0be9a882540f1922577abba4c872ager@chromium.org INLINE(bool is_reg() const); 3785c838251403b0be9a882540f1922577abba4c872ager@chromium.org 379594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org inline int32_t immediate() const { 380594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org ASSERT(!is_reg()); 381594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org return imm32_; 382594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org } 383594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org 3845c838251403b0be9a882540f1922577abba4c872ager@chromium.org Register rm() const { return rm_; } 3855c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3865c838251403b0be9a882540f1922577abba4c872ager@chromium.org private: 3875c838251403b0be9a882540f1922577abba4c872ager@chromium.org Register rm_; 38883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org int32_t imm32_; // Valid if rm_ == no_reg. 3895c838251403b0be9a882540f1922577abba4c872ager@chromium.org RelocInfo::Mode rmode_; 3905c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3915c838251403b0be9a882540f1922577abba4c872ager@chromium.org friend class Assembler; 3925c838251403b0be9a882540f1922577abba4c872ager@chromium.org friend class MacroAssembler; 3935c838251403b0be9a882540f1922577abba4c872ager@chromium.org}; 3945c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3955c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3965c838251403b0be9a882540f1922577abba4c872ager@chromium.org// On MIPS we have only one adressing mode with base_reg + offset. 3975c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Class MemOperand represents a memory operand in load and store instructions. 3985c838251403b0be9a882540f1922577abba4c872ager@chromium.orgclass MemOperand : public Operand { 3995c838251403b0be9a882540f1922577abba4c872ager@chromium.org public: 400afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org // Immediate value attached to offset. 401afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org enum OffsetAddend { 402afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org offset_minus_one = -1, 403afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org offset_zero = 0 404afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org }; 405afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org 4067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org explicit MemOperand(Register rn, int32_t offset = 0); 407afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org explicit MemOperand(Register rn, int32_t unit, int32_t multiplier, 408afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org OffsetAddend offset_addend = offset_zero); 40904921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org int32_t offset() const { return offset_; } 4105c838251403b0be9a882540f1922577abba4c872ager@chromium.org 41134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org bool OffsetIsInt16Encodable() const { 41234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org return is_int16(offset_); 41334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org } 41434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 4155c838251403b0be9a882540f1922577abba4c872ager@chromium.org private: 4167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int32_t offset_; 4175c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4185c838251403b0be9a882540f1922577abba4c872ager@chromium.org friend class Assembler; 4195c838251403b0be9a882540f1922577abba4c872ager@chromium.org}; 4205c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4215c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgclass Assembler : public AssemblerBase { 4235c838251403b0be9a882540f1922577abba4c872ager@chromium.org public: 4245c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Create an assembler. Instructions and relocation information are emitted 4255c838251403b0be9a882540f1922577abba4c872ager@chromium.org // into a buffer, with the instructions starting from the beginning and the 4265c838251403b0be9a882540f1922577abba4c872ager@chromium.org // relocation information starting from the end of the buffer. See CodeDesc 4275c838251403b0be9a882540f1922577abba4c872ager@chromium.org // for a detailed comment on the layout (globals.h). 4285c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 4295c838251403b0be9a882540f1922577abba4c872ager@chromium.org // If the provided buffer is NULL, the assembler allocates and grows its own 4305c838251403b0be9a882540f1922577abba4c872ager@chromium.org // buffer, and buffer_size determines the initial buffer size. The buffer is 4315c838251403b0be9a882540f1922577abba4c872ager@chromium.org // owned by the assembler and deallocated upon destruction of the assembler. 4325c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 4335c838251403b0be9a882540f1922577abba4c872ager@chromium.org // If the provided buffer is not NULL, the assembler uses the provided buffer 4345c838251403b0be9a882540f1922577abba4c872ager@chromium.org // for code generation and assumes its size to be buffer_size. If the buffer 4355c838251403b0be9a882540f1922577abba4c872ager@chromium.org // is too small, a fatal error occurs. No deallocation of the buffer is done 4365c838251403b0be9a882540f1922577abba4c872ager@chromium.org // upon destruction of the assembler. 43783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Assembler(Isolate* isolate, void* buffer, int buffer_size); 4388e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org virtual ~Assembler() { } 4395c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4405c838251403b0be9a882540f1922577abba4c872ager@chromium.org // GetCode emits any pending (non-emitted) code and fills the descriptor 4415c838251403b0be9a882540f1922577abba4c872ager@chromium.org // desc. GetCode() is idempotent; it returns the same result if no other 4425c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Assembler functions are invoked in between GetCode() calls. 4435c838251403b0be9a882540f1922577abba4c872ager@chromium.org void GetCode(CodeDesc* desc); 4445c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4455c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Label operations & relative jumps (PPUM Appendix D). 4465c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 4475c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Takes a branch opcode (cc) and a label (L) and generates 4485c838251403b0be9a882540f1922577abba4c872ager@chromium.org // either a backward branch or a forward branch and links it 4495c838251403b0be9a882540f1922577abba4c872ager@chromium.org // to the label fixup chain. Usage: 4505c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 4515c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Label L; // unbound label 4525c838251403b0be9a882540f1922577abba4c872ager@chromium.org // j(cc, &L); // forward branch to unbound label 4535c838251403b0be9a882540f1922577abba4c872ager@chromium.org // bind(&L); // bind label to the current pc 4545c838251403b0be9a882540f1922577abba4c872ager@chromium.org // j(cc, &L); // backward branch to bound label 4555c838251403b0be9a882540f1922577abba4c872ager@chromium.org // bind(&L); // illegal: a label may be bound only once 4565c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 4575c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Note: The same Label can be used for forward and backward branches 4585c838251403b0be9a882540f1922577abba4c872ager@chromium.org // but it may be bound only once. 45983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org void bind(Label* L); // Binds an unbound label L to current code position. 4603cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // Determines if Label is bound and near enough so that branch instruction 4613cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // can be used to reach it, instead of jump instruction. 4623cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org bool is_near(Label* L); 4635c838251403b0be9a882540f1922577abba4c872ager@chromium.org 46483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Returns the branch offset to the given label from the current code 46583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // position. Links the label to the current position if it is still unbound. 4665c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Manages the jump elimination optimization if the second parameter is true. 4675c838251403b0be9a882540f1922577abba4c872ager@chromium.org int32_t branch_offset(Label* L, bool jump_elimination_allowed); 4685c838251403b0be9a882540f1922577abba4c872ager@chromium.org int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) { 4695c838251403b0be9a882540f1922577abba4c872ager@chromium.org int32_t o = branch_offset(L, jump_elimination_allowed); 4705c838251403b0be9a882540f1922577abba4c872ager@chromium.org ASSERT((o & 3) == 0); // Assert the offset is aligned. 4715c838251403b0be9a882540f1922577abba4c872ager@chromium.org return o >> 2; 4725c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 4733cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org uint32_t jump_address(Label* L); 4745c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4755c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Puts a labels target address at the given position. 4765c838251403b0be9a882540f1922577abba4c872ager@chromium.org // The high 8 bits are set to zero. 4775c838251403b0be9a882540f1922577abba4c872ager@chromium.org void label_at_put(Label* L, int at_offset); 4785c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4795c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Read/Modify the code target address in the branch/call instruction at pc. 4805c838251403b0be9a882540f1922577abba4c872ager@chromium.org static Address target_address_at(Address pc); 4816a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org static void set_target_address_at(Address pc, 4826a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org Address target, 4836a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org ICacheFlushMode icache_flush_mode = 4846a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org FLUSH_ICACHE_IF_NEEDED); 48597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org // On MIPS there is no Constant Pool so we skip that parameter. 48697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org INLINE(static Address target_address_at(Address pc, 48797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org ConstantPoolArray* constant_pool)) { 48897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org return target_address_at(pc); 48997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org } 49097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org INLINE(static void set_target_address_at(Address pc, 49197b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org ConstantPoolArray* constant_pool, 4926a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org Address target, 4936a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org ICacheFlushMode icache_flush_mode = 4946a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org FLUSH_ICACHE_IF_NEEDED)) { 4956a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org set_target_address_at(pc, target, icache_flush_mode); 49697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org } 49797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org INLINE(static Address target_address_at(Address pc, Code* code)) { 49897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; 49997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org return target_address_at(pc, constant_pool); 50097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org } 50197b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org INLINE(static void set_target_address_at(Address pc, 50297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org Code* code, 5036a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org Address target, 5046a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org ICacheFlushMode icache_flush_mode = 5056a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org FLUSH_ICACHE_IF_NEEDED)) { 50697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; 5076a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org set_target_address_at(pc, constant_pool, target, icache_flush_mode); 50897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org } 5095c838251403b0be9a882540f1922577abba4c872ager@chromium.org 51089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org // Return the code target address at a call site from the return address 51189e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org // of that call in the instruction stream. 51289e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org inline static Address target_address_from_return_address(Address pc); 51389e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org 51434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static void JumpLabelToJumpRegister(Address pc); 51534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 51628faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org static void QuietNaN(HeapObject* nan); 51728faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org 5185c838251403b0be9a882540f1922577abba4c872ager@chromium.org // This sets the branch destination (which gets loaded at the call address). 51988aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org // This is for calls and branches within generated code. The serializer 52088aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org // has already deserialized the lui/ori instructions etc. 52188aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org inline static void deserialization_set_special_target_at( 52297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org Address instruction_payload, Code* code, Address target) { 52388aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org set_target_address_at( 52488aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org instruction_payload - kInstructionsFor32BitConstant * kInstrSize, 52597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org code, 52688aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org target); 5275c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 5285c838251403b0be9a882540f1922577abba4c872ager@chromium.org 5297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Size of an instruction. 5307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kInstrSize = sizeof(Instr); 5317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 5327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Difference between address of current opcode and target address offset. 5337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kBranchPCOffset = 4; 5347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 5357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Here we are patching the address in the LUI/ORI instruction pair. 5367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // These values are used in the serialization process and must be zero for 5377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // MIPS platform, as Code, Embedded Object or External-reference pointers 5387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // are split across two consecutive instructions and don't exist separately 5397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // in the code, so the serializer should not step forwards in memory after 5407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // a target is resolved and written. 54188aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org static const int kSpecialTargetSize = 0; 5427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 5437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Number of consecutive instructions used to store 32bit constant. 54434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // Before jump-optimizations, this constant was used in 54534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // RelocInfo::target_address_address() function to tell serializer address of 54634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // the instruction that follows LUI/ORI instruction pair. Now, with new jump 54734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // optimization, where jump-through-register instruction that usually 54834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // follows LUI/ORI pair is substituted with J/JAL, this constant equals 54934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // to 3 instructions (LUI+ORI+J/JAL/JR/JALR). 55034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static const int kInstructionsFor32BitConstant = 3; 5515c838251403b0be9a882540f1922577abba4c872ager@chromium.org 5525c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Distance between the instruction referring to the address of the call 5535c838251403b0be9a882540f1922577abba4c872ager@chromium.org // target and the return address. 5545c838251403b0be9a882540f1922577abba4c872ager@chromium.org static const int kCallTargetAddressOffset = 4 * kInstrSize; 5555c838251403b0be9a882540f1922577abba4c872ager@chromium.org 5565c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Distance between start of patched return sequence and the emitted address 5575c838251403b0be9a882540f1922577abba4c872ager@chromium.org // to jump to. 5587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kPatchReturnSequenceAddressOffset = 0; 5595c838251403b0be9a882540f1922577abba4c872ager@chromium.org 5602356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org // Distance between start of patched debug break slot and the emitted address 5612356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org // to jump to. 5627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; 5637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 5647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Difference between address of current opcode and value read from pc 5657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // register. 5667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kPcLoadDelta = 4; 5677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 56889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org static const int kPatchDebugBreakSlotReturnOffset = 4 * kInstrSize; 56989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org 5707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Number of instructions used for the JS return sequence. The constant is 5717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // used by the debugger to patch the JS return sequence. 5727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kJSReturnSequenceInstructions = 7; 5737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kDebugBreakSlotInstructions = 4; 5747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kDebugBreakSlotLength = 5757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org kDebugBreakSlotInstructions * kInstrSize; 5767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 5775c838251403b0be9a882540f1922577abba4c872ager@chromium.org 5785c838251403b0be9a882540f1922577abba4c872ager@chromium.org // --------------------------------------------------------------------------- 5795c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Code generation. 5805c838251403b0be9a882540f1922577abba4c872ager@chromium.org 5817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Insert the smallest number of nop instructions 5827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // possible to align the pc offset to a multiple 5837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // of m. m must be a power of 2 (>= 4). 5847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void Align(int m); 5857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Aligns code to something that's optimal for a jump target for the platform. 5867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void CodeTargetAlign(); 5877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 5887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Different nop operations are used by the code generator to detect certain 5897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // states of the generated code. 5907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org enum NopMarkerTypes { 5917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org NON_MARKING_NOP = 0, 5927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org DEBUG_BREAK_NOP, 5937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // IC markers. 5947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org PROPERTY_ACCESS_INLINED, 5957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org PROPERTY_ACCESS_INLINED_CONTEXT, 5967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE, 5977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Helper values. 5987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org LAST_CODE_MARKER, 599fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED, 600fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // Code aging 601ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org CODE_AGE_MARKER_NOP = 6, 602ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org CODE_AGE_SEQUENCE_NOP 6037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org }; 6047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 60533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org // Type == 0 is the default non-marking nop. For mips this is a 60633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org // sll(zero_reg, zero_reg, 0). We use rt_reg == at for non-zero 60733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org // marking, to avoid conflict with ssnop and ehb instructions. 6087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void nop(unsigned int type = 0) { 6097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org ASSERT(type < 32); 61033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org Register nop_rt_reg = (type == 0) ? zero_reg : at; 61133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org sll(zero_reg, nop_rt_reg, type, true); 6127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 6135c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6145c838251403b0be9a882540f1922577abba4c872ager@chromium.org 61583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // --------Branch-and-jump-instructions---------- 6165c838251403b0be9a882540f1922577abba4c872ager@chromium.org // We don't use likely variant of instructions. 6175c838251403b0be9a882540f1922577abba4c872ager@chromium.org void b(int16_t offset); 6185c838251403b0be9a882540f1922577abba4c872ager@chromium.org void b(Label* L) { b(branch_offset(L, false)>>2); } 6195c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bal(int16_t offset); 6205c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bal(Label* L) { bal(branch_offset(L, false)>>2); } 6215c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6225c838251403b0be9a882540f1922577abba4c872ager@chromium.org void beq(Register rs, Register rt, int16_t offset); 6235c838251403b0be9a882540f1922577abba4c872ager@chromium.org void beq(Register rs, Register rt, Label* L) { 6245c838251403b0be9a882540f1922577abba4c872ager@chromium.org beq(rs, rt, branch_offset(L, false) >> 2); 6255c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 6265c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bgez(Register rs, int16_t offset); 6275c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bgezal(Register rs, int16_t offset); 6285c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bgtz(Register rs, int16_t offset); 6295c838251403b0be9a882540f1922577abba4c872ager@chromium.org void blez(Register rs, int16_t offset); 6305c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bltz(Register rs, int16_t offset); 6315c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bltzal(Register rs, int16_t offset); 6325c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bne(Register rs, Register rt, int16_t offset); 6335c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bne(Register rs, Register rt, Label* L) { 6345c838251403b0be9a882540f1922577abba4c872ager@chromium.org bne(rs, rt, branch_offset(L, false)>>2); 6355c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 6365c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6375c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Never use the int16_t b(l)cond version with a branch offset 63883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // instead of using the Label* version. 6395c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6402efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits. 6415c838251403b0be9a882540f1922577abba4c872ager@chromium.org void j(int32_t target); 6425c838251403b0be9a882540f1922577abba4c872ager@chromium.org void jal(int32_t target); 6435c838251403b0be9a882540f1922577abba4c872ager@chromium.org void jalr(Register rs, Register rd = ra); 6445c838251403b0be9a882540f1922577abba4c872ager@chromium.org void jr(Register target); 64534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org void j_or_jr(int32_t target, Register rs); 64634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org void jal_or_jalr(int32_t target, Register rs); 6475c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6485c838251403b0be9a882540f1922577abba4c872ager@chromium.org 649e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org // -------Data-processing-instructions--------- 6505c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6515c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Arithmetic. 6525c838251403b0be9a882540f1922577abba4c872ager@chromium.org void addu(Register rd, Register rs, Register rt); 6535c838251403b0be9a882540f1922577abba4c872ager@chromium.org void subu(Register rd, Register rs, Register rt); 6545c838251403b0be9a882540f1922577abba4c872ager@chromium.org void mult(Register rs, Register rt); 6555c838251403b0be9a882540f1922577abba4c872ager@chromium.org void multu(Register rs, Register rt); 6565c838251403b0be9a882540f1922577abba4c872ager@chromium.org void div(Register rs, Register rt); 6575c838251403b0be9a882540f1922577abba4c872ager@chromium.org void divu(Register rs, Register rt); 6585c838251403b0be9a882540f1922577abba4c872ager@chromium.org void mul(Register rd, Register rs, Register rt); 6595c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6605c838251403b0be9a882540f1922577abba4c872ager@chromium.org void addiu(Register rd, Register rs, int32_t j); 6615c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6625c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Logical. 6635c838251403b0be9a882540f1922577abba4c872ager@chromium.org void and_(Register rd, Register rs, Register rt); 6645c838251403b0be9a882540f1922577abba4c872ager@chromium.org void or_(Register rd, Register rs, Register rt); 6655c838251403b0be9a882540f1922577abba4c872ager@chromium.org void xor_(Register rd, Register rs, Register rt); 6665c838251403b0be9a882540f1922577abba4c872ager@chromium.org void nor(Register rd, Register rs, Register rt); 6675c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6685c838251403b0be9a882540f1922577abba4c872ager@chromium.org void andi(Register rd, Register rs, int32_t j); 6695c838251403b0be9a882540f1922577abba4c872ager@chromium.org void ori(Register rd, Register rs, int32_t j); 6705c838251403b0be9a882540f1922577abba4c872ager@chromium.org void xori(Register rd, Register rs, int32_t j); 6715c838251403b0be9a882540f1922577abba4c872ager@chromium.org void lui(Register rd, int32_t j); 6725c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6735c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Shifts. 6747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop 6757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // and may cause problems in normal code. coming_from_nop makes sure this 6767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // doesn't happen. 6777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false); 6785c838251403b0be9a882540f1922577abba4c872ager@chromium.org void sllv(Register rd, Register rt, Register rs); 6795c838251403b0be9a882540f1922577abba4c872ager@chromium.org void srl(Register rd, Register rt, uint16_t sa); 6805c838251403b0be9a882540f1922577abba4c872ager@chromium.org void srlv(Register rd, Register rt, Register rs); 6815c838251403b0be9a882540f1922577abba4c872ager@chromium.org void sra(Register rt, Register rd, uint16_t sa); 6825c838251403b0be9a882540f1922577abba4c872ager@chromium.org void srav(Register rt, Register rd, Register rs); 6837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void rotr(Register rd, Register rt, uint16_t sa); 6847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void rotrv(Register rd, Register rt, Register rs); 6855c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6865c838251403b0be9a882540f1922577abba4c872ager@chromium.org 687e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org // ------------Memory-instructions------------- 6885c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6895c838251403b0be9a882540f1922577abba4c872ager@chromium.org void lb(Register rd, const MemOperand& rs); 6905c838251403b0be9a882540f1922577abba4c872ager@chromium.org void lbu(Register rd, const MemOperand& rs); 6917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void lh(Register rd, const MemOperand& rs); 6927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void lhu(Register rd, const MemOperand& rs); 6935c838251403b0be9a882540f1922577abba4c872ager@chromium.org void lw(Register rd, const MemOperand& rs); 6947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void lwl(Register rd, const MemOperand& rs); 6957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void lwr(Register rd, const MemOperand& rs); 6965c838251403b0be9a882540f1922577abba4c872ager@chromium.org void sb(Register rd, const MemOperand& rs); 6977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void sh(Register rd, const MemOperand& rs); 6985c838251403b0be9a882540f1922577abba4c872ager@chromium.org void sw(Register rd, const MemOperand& rs); 6997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void swl(Register rd, const MemOperand& rs); 7007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void swr(Register rd, const MemOperand& rs); 7015c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7025c838251403b0be9a882540f1922577abba4c872ager@chromium.org 703e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org // ----------------Prefetch-------------------- 704afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org 705afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org void pref(int32_t hint, const MemOperand& rs); 706afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org 707afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org 708e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org // -------------Misc-instructions-------------- 7095c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7105c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Break / Trap instructions. 711c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org void break_(uint32_t code, bool break_as_stop = false); 712c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org void stop(const char* msg, uint32_t code = kMaxStopCode); 7135c838251403b0be9a882540f1922577abba4c872ager@chromium.org void tge(Register rs, Register rt, uint16_t code); 7145c838251403b0be9a882540f1922577abba4c872ager@chromium.org void tgeu(Register rs, Register rt, uint16_t code); 7155c838251403b0be9a882540f1922577abba4c872ager@chromium.org void tlt(Register rs, Register rt, uint16_t code); 7165c838251403b0be9a882540f1922577abba4c872ager@chromium.org void tltu(Register rs, Register rt, uint16_t code); 7175c838251403b0be9a882540f1922577abba4c872ager@chromium.org void teq(Register rs, Register rt, uint16_t code); 7185c838251403b0be9a882540f1922577abba4c872ager@chromium.org void tne(Register rs, Register rt, uint16_t code); 7195c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7205c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Move from HI/LO register. 7215c838251403b0be9a882540f1922577abba4c872ager@chromium.org void mfhi(Register rd); 7225c838251403b0be9a882540f1922577abba4c872ager@chromium.org void mflo(Register rd); 7235c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7245c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Set on less than. 7255c838251403b0be9a882540f1922577abba4c872ager@chromium.org void slt(Register rd, Register rs, Register rt); 7265c838251403b0be9a882540f1922577abba4c872ager@chromium.org void sltu(Register rd, Register rs, Register rt); 7275c838251403b0be9a882540f1922577abba4c872ager@chromium.org void slti(Register rd, Register rs, int32_t j); 7285c838251403b0be9a882540f1922577abba4c872ager@chromium.org void sltiu(Register rd, Register rs, int32_t j); 7295c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Conditional move. 7317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void movz(Register rd, Register rs, Register rt); 7327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void movn(Register rd, Register rs, Register rt); 7337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void movt(Register rd, Register rs, uint16_t cc = 0); 7347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void movf(Register rd, Register rs, uint16_t cc = 0); 7357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 7367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Bit twiddling. 7377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void clz(Register rd, Register rs); 7387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void ins_(Register rt, Register rs, uint16_t pos, uint16_t size); 7397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void ext_(Register rt, Register rs, uint16_t pos, uint16_t size); 7405c838251403b0be9a882540f1922577abba4c872ager@chromium.org 741e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org // --------Coprocessor-instructions---------------- 7425c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7435c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Load, store, and move. 7445c838251403b0be9a882540f1922577abba4c872ager@chromium.org void lwc1(FPURegister fd, const MemOperand& src); 7455c838251403b0be9a882540f1922577abba4c872ager@chromium.org void ldc1(FPURegister fd, const MemOperand& src); 7465c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7475c838251403b0be9a882540f1922577abba4c872ager@chromium.org void swc1(FPURegister fs, const MemOperand& dst); 7485c838251403b0be9a882540f1922577abba4c872ager@chromium.org void sdc1(FPURegister fs, const MemOperand& dst); 7495c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void mtc1(Register rt, FPURegister fs); 7517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void mfc1(Register rt, FPURegister fs); 7527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 7537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void ctc1(Register rt, FPUControlRegister fs); 7547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void cfc1(Register rt, FPUControlRegister fs); 7557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 7567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Arithmetic. 7577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void add_d(FPURegister fd, FPURegister fs, FPURegister ft); 7587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void sub_d(FPURegister fd, FPURegister fs, FPURegister ft); 7597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void mul_d(FPURegister fd, FPURegister fs, FPURegister ft); 76059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft); 7617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void div_d(FPURegister fd, FPURegister fs, FPURegister ft); 7627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void abs_d(FPURegister fd, FPURegister fs); 7637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void mov_d(FPURegister fd, FPURegister fs); 7647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void neg_d(FPURegister fd, FPURegister fs); 7657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void sqrt_d(FPURegister fd, FPURegister fs); 7665c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7675c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Conversion. 7685c838251403b0be9a882540f1922577abba4c872ager@chromium.org void cvt_w_s(FPURegister fd, FPURegister fs); 7695c838251403b0be9a882540f1922577abba4c872ager@chromium.org void cvt_w_d(FPURegister fd, FPURegister fs); 7707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void trunc_w_s(FPURegister fd, FPURegister fs); 7717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void trunc_w_d(FPURegister fd, FPURegister fs); 7727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void round_w_s(FPURegister fd, FPURegister fs); 7737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void round_w_d(FPURegister fd, FPURegister fs); 7747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void floor_w_s(FPURegister fd, FPURegister fs); 7757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void floor_w_d(FPURegister fd, FPURegister fs); 7767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void ceil_w_s(FPURegister fd, FPURegister fs); 7777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void ceil_w_d(FPURegister fd, FPURegister fs); 7785c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7795c838251403b0be9a882540f1922577abba4c872ager@chromium.org void cvt_l_s(FPURegister fd, FPURegister fs); 7805c838251403b0be9a882540f1922577abba4c872ager@chromium.org void cvt_l_d(FPURegister fd, FPURegister fs); 7817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void trunc_l_s(FPURegister fd, FPURegister fs); 7827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void trunc_l_d(FPURegister fd, FPURegister fs); 7837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void round_l_s(FPURegister fd, FPURegister fs); 7847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void round_l_d(FPURegister fd, FPURegister fs); 7857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void floor_l_s(FPURegister fd, FPURegister fs); 7867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void floor_l_d(FPURegister fd, FPURegister fs); 7877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void ceil_l_s(FPURegister fd, FPURegister fs); 7887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void ceil_l_d(FPURegister fd, FPURegister fs); 7895c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7905c838251403b0be9a882540f1922577abba4c872ager@chromium.org void cvt_s_w(FPURegister fd, FPURegister fs); 7915c838251403b0be9a882540f1922577abba4c872ager@chromium.org void cvt_s_l(FPURegister fd, FPURegister fs); 7925c838251403b0be9a882540f1922577abba4c872ager@chromium.org void cvt_s_d(FPURegister fd, FPURegister fs); 7935c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7945c838251403b0be9a882540f1922577abba4c872ager@chromium.org void cvt_d_w(FPURegister fd, FPURegister fs); 7955c838251403b0be9a882540f1922577abba4c872ager@chromium.org void cvt_d_l(FPURegister fd, FPURegister fs); 7965c838251403b0be9a882540f1922577abba4c872ager@chromium.org void cvt_d_s(FPURegister fd, FPURegister fs); 7975c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7985c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Conditions and branches. 7995c838251403b0be9a882540f1922577abba4c872ager@chromium.org void c(FPUCondition cond, SecondaryField fmt, 8005c838251403b0be9a882540f1922577abba4c872ager@chromium.org FPURegister ft, FPURegister fs, uint16_t cc = 0); 8015c838251403b0be9a882540f1922577abba4c872ager@chromium.org 8025c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bc1f(int16_t offset, uint16_t cc = 0); 8035c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bc1f(Label* L, uint16_t cc = 0) { bc1f(branch_offset(L, false)>>2, cc); } 8045c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bc1t(int16_t offset, uint16_t cc = 0); 8055c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bc1t(Label* L, uint16_t cc = 0) { bc1t(branch_offset(L, false)>>2, cc); } 8067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void fcmp(FPURegister src1, const double src2, FPUCondition cond); 8075c838251403b0be9a882540f1922577abba4c872ager@chromium.org 8085c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Check the code size generated from label to here. 8096db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org int SizeOfCodeGeneratedSince(Label* label) { 8106db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org return pc_offset() - label->pos(); 8116db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org } 8126db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org 8136db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org // Check the number of instructions generated from label to here. 8146db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org int InstructionsGeneratedSince(Label* label) { 8156db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org return SizeOfCodeGeneratedSince(label) / kInstrSize; 8165c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 8175c838251403b0be9a882540f1922577abba4c872ager@chromium.org 8187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Class for scoping postponing the trampoline pool generation. 8197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org class BlockTrampolinePoolScope { 8207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org public: 8217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) { 8227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org assem_->StartBlockTrampolinePool(); 8237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 8247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org ~BlockTrampolinePoolScope() { 8257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org assem_->EndBlockTrampolinePool(); 8267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 8277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 8287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org private: 8297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org Assembler* assem_; 8307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 8317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope); 8327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org }; 8337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 8343cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // Class for postponing the assembly buffer growth. Typically used for 8353cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // sequences of instructions that must be emitted as a unit, before 8363cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // buffer growth (and relocation) can occur. 8373cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // This blocking scope is not nestable. 8383cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org class BlockGrowBufferScope { 8393cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org public: 8403cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) { 8413cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org assem_->StartBlockGrowBuffer(); 8423cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org } 8433cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org ~BlockGrowBufferScope() { 8443cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org assem_->EndBlockGrowBuffer(); 8453cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org } 8463cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 8473c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org private: 8483c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org Assembler* assem_; 8493cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 8503c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope); 8513cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org }; 8523cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 8535c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Debugging. 8545c838251403b0be9a882540f1922577abba4c872ager@chromium.org 8555c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Mark address of the ExitJSFrame code. 8565c838251403b0be9a882540f1922577abba4c872ager@chromium.org void RecordJSReturn(); 8575c838251403b0be9a882540f1922577abba4c872ager@chromium.org 8587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Mark address of a debug break slot. 8597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void RecordDebugBreakSlot(); 8607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 86183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Record the AST id of the CallIC being compiled, so that it can be placed 86283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // in the relocation information. 863471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org void SetRecordedAstId(TypeFeedbackId ast_id) { 864471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org ASSERT(recorded_ast_id_.IsNone()); 865717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org recorded_ast_id_ = ast_id; 866717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org } 867717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org 868471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org TypeFeedbackId RecordedAstId() { 869471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org ASSERT(!recorded_ast_id_.IsNone()); 870717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org return recorded_ast_id_; 871717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org } 872717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org 873471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); } 87483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 8755c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Record a comment relocation entry that can be used by a disassembler. 8767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Use --code-comments to enable. 8775c838251403b0be9a882540f1922577abba4c872ager@chromium.org void RecordComment(const char* msg); 8785c838251403b0be9a882540f1922577abba4c872ager@chromium.org 8793cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org static int RelocateInternalReference(byte* pc, intptr_t pc_delta); 8803cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 8817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Writes a single byte or word of data in the code stream. Used for 8827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // inline tables, e.g., jump-tables. 8837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void db(uint8_t data); 8847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void dd(uint32_t data); 8855c838251403b0be9a882540f1922577abba4c872ager@chromium.org 886057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org // Emits the address of the code stub's first instruction. 887057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org void emit_code_stub_address(Code* stub); 888057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org 8897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org PositionsRecorder* positions_recorder() { return &positions_recorder_; } 8907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 8917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Postpone the generation of the trampoline pool for the specified number of 8927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // instructions. 8937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void BlockTrampolinePoolFor(int instructions); 8947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 8955c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Check if there is less than kGap bytes available in the buffer. 8965c838251403b0be9a882540f1922577abba4c872ager@chromium.org // If this is the case, we need to grow the buffer before emitting 8975c838251403b0be9a882540f1922577abba4c872ager@chromium.org // an instruction or relocation information. 8985c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; } 8995c838251403b0be9a882540f1922577abba4c872ager@chromium.org 9005c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Get the number of bytes available in the buffer. 9015c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline int available_space() const { return reloc_info_writer.pos() - pc_; } 9025c838251403b0be9a882540f1922577abba4c872ager@chromium.org 9035c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Read/patch instructions. 9045c838251403b0be9a882540f1922577abba4c872ager@chromium.org static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } 9057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static void instr_at_put(byte* pc, Instr instr) { 9065c838251403b0be9a882540f1922577abba4c872ager@chromium.org *reinterpret_cast<Instr*>(pc) = instr; 9075c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 9085c838251403b0be9a882540f1922577abba4c872ager@chromium.org Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } 9095c838251403b0be9a882540f1922577abba4c872ager@chromium.org void instr_at_put(int pos, Instr instr) { 9105c838251403b0be9a882540f1922577abba4c872ager@chromium.org *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 9115c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 9125c838251403b0be9a882540f1922577abba4c872ager@chromium.org 9135c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Check if an instruction is a branch of some kind. 9147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsBranch(Instr instr); 91583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static bool IsBeq(Instr instr); 91683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static bool IsBne(Instr instr); 9177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 9183cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org static bool IsJump(Instr instr); 9193cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org static bool IsJ(Instr instr); 9203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org static bool IsLui(Instr instr); 9213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org static bool IsOri(Instr instr); 9223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 92334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static bool IsJal(Instr instr); 92434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static bool IsJr(Instr instr); 92534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static bool IsJalr(Instr instr); 92634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 9277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsNop(Instr instr, unsigned int type); 9287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsPop(Instr instr); 9297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsPush(Instr instr); 9307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsLwRegFpOffset(Instr instr); 9317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsSwRegFpOffset(Instr instr); 9327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsLwRegFpNegOffset(Instr instr); 9337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsSwRegFpNegOffset(Instr instr); 9347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 93583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static Register GetRtReg(Instr instr); 93683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static Register GetRsReg(Instr instr); 93783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static Register GetRdReg(Instr instr); 93883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 93983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetRt(Instr instr); 94083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetRtField(Instr instr); 94183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetRs(Instr instr); 94283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetRsField(Instr instr); 94383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetRd(Instr instr); 94483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetRdField(Instr instr); 94583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetSa(Instr instr); 94683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetSaField(Instr instr); 94783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetOpcodeField(Instr instr); 9483cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org static uint32_t GetFunction(Instr instr); 9493cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org static uint32_t GetFunctionField(Instr instr); 95083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetImmediate16(Instr instr); 95183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static uint32_t GetLabelConst(Instr instr); 9527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 9537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static int32_t GetBranchOffset(Instr instr); 9547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsLw(Instr instr); 9557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static int16_t GetLwOffset(Instr instr); 9567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static Instr SetLwOffset(Instr instr, int16_t offset); 9577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 9587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsSw(Instr instr); 9597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static Instr SetSwOffset(Instr instr, int16_t offset); 9607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static bool IsAddImmediate(Instr instr); 9617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static Instr SetAddImmediateOffset(Instr instr, int16_t offset); 9627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 96383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static bool IsAndImmediate(Instr instr); 9647bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org static bool IsEmittedConstant(Instr instr); 96583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 9663cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org void CheckTrampolinePool(); 9677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 96869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Allocate a constant pool of the correct size for the generated code. 9699fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); 97069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 97169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Generate the constant pool for the generated code. 97269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org void PopulateConstantPool(ConstantPoolArray* constant_pool); 97369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 9747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org protected: 97583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Relocation for a type-recording IC has the AST id added to it. This 97683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // member variable is a way to pass the information from the call site to 97783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // the relocation info. 978471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org TypeFeedbackId recorded_ast_id_; 97983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 9807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; } 9815c838251403b0be9a882540f1922577abba4c872ager@chromium.org 9825c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Decode branch instruction at pos and return branch target pos. 9835c838251403b0be9a882540f1922577abba4c872ager@chromium.org int target_at(int32_t pos); 9845c838251403b0be9a882540f1922577abba4c872ager@chromium.org 9855c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Patch branch instruction at pos to branch to given branch target pos. 9865c838251403b0be9a882540f1922577abba4c872ager@chromium.org void target_at_put(int32_t pos, int32_t target_pos); 9875c838251403b0be9a882540f1922577abba4c872ager@chromium.org 9885c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Say if we need to relocate with this mode. 9897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org bool MustUseReg(RelocInfo::Mode rmode); 9905c838251403b0be9a882540f1922577abba4c872ager@chromium.org 9915c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Record reloc info for current pc_. 9925c838251403b0be9a882540f1922577abba4c872ager@chromium.org void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 9935c838251403b0be9a882540f1922577abba4c872ager@chromium.org 9947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Block the emission of the trampoline pool before pc_offset. 9957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void BlockTrampolinePoolBefore(int pc_offset) { 9967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org if (no_trampoline_pool_before_ < pc_offset) 9977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org no_trampoline_pool_before_ = pc_offset; 9987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 9997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 10007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void StartBlockTrampolinePool() { 10017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org trampoline_pool_blocked_nesting_++; 10027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 10033cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 10047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void EndBlockTrampolinePool() { 10057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org trampoline_pool_blocked_nesting_--; 10067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 10077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 10087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org bool is_trampoline_pool_blocked() const { 10097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return trampoline_pool_blocked_nesting_ > 0; 10107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 10117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 101283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org bool has_exception() const { 101383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org return internal_trampoline_exception_; 101483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org } 101583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 101634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi); 101734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 10183cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org bool is_trampoline_emitted() const { 10193cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org return trampoline_emitted_; 10203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org } 10213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 10223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // Temporarily block automatic assembly buffer growth. 10233cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org void StartBlockGrowBuffer() { 10243cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org ASSERT(!block_buffer_growth_); 10253cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org block_buffer_growth_ = true; 10263cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org } 10273cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 10283cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org void EndBlockGrowBuffer() { 10293cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org ASSERT(block_buffer_growth_); 10303cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org block_buffer_growth_ = false; 10313cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org } 10323cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 10333cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org bool is_buffer_growth_blocked() const { 10343cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org return block_buffer_growth_; 10353cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org } 10363cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 10375c838251403b0be9a882540f1922577abba4c872ager@chromium.org private: 10385c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Buffer size and constant pool distance are checked together at regular 10395c838251403b0be9a882540f1922577abba4c872ager@chromium.org // intervals of kBufferCheckInterval emitted bytes. 10405c838251403b0be9a882540f1922577abba4c872ager@chromium.org static const int kBufferCheckInterval = 1*KB/2; 10415c838251403b0be9a882540f1922577abba4c872ager@chromium.org 10425c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Code generation. 10435c838251403b0be9a882540f1922577abba4c872ager@chromium.org // The relocation writer's position is at least kGap bytes below the end of 10445c838251403b0be9a882540f1922577abba4c872ager@chromium.org // the generated instructions. This is so that multi-instruction sequences do 10455c838251403b0be9a882540f1922577abba4c872ager@chromium.org // not have to check for overflow. The same is true for writes of large 10465c838251403b0be9a882540f1922577abba4c872ager@chromium.org // relocation info entries. 10475c838251403b0be9a882540f1922577abba4c872ager@chromium.org static const int kGap = 32; 10485c838251403b0be9a882540f1922577abba4c872ager@chromium.org 10497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 10507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Repeated checking whether the trampoline pool should be emitted is rather 10517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // expensive. By default we only check again once a number of instructions 10527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // has been generated. 10537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kCheckConstIntervalInst = 32; 10547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; 10557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 10567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int next_buffer_check_; // pc offset of next buffer check. 10577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 10587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Emission of the trampoline pool may be blocked in some code sequences. 10597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int trampoline_pool_blocked_nesting_; // Block emission if this is not zero. 10607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int no_trampoline_pool_before_; // Block emission before this pc offset. 10617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 10627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Keep track of the last emitted pool to guarantee a maximal distance. 10637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int last_trampoline_pool_end_; // pc offset of the end of the last pool. 10647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 10653cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // Automatic growth of the assembly buffer may be blocked for some sequences. 10663cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org bool block_buffer_growth_; // Block growth when true. 10673cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org 10685c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Relocation information generation. 10695c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Each relocation is encoded as a variable size value. 10705c838251403b0be9a882540f1922577abba4c872ager@chromium.org static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 10715c838251403b0be9a882540f1922577abba4c872ager@chromium.org RelocInfoWriter reloc_info_writer; 10725c838251403b0be9a882540f1922577abba4c872ager@chromium.org 10735c838251403b0be9a882540f1922577abba4c872ager@chromium.org // The bound position, before this we cannot do instruction elimination. 10745c838251403b0be9a882540f1922577abba4c872ager@chromium.org int last_bound_pos_; 10755c838251403b0be9a882540f1922577abba4c872ager@chromium.org 10765c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Code emission. 10775c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline void CheckBuffer(); 10785c838251403b0be9a882540f1922577abba4c872ager@chromium.org void GrowBuffer(); 10795c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline void emit(Instr x); 10807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org inline void CheckTrampolinePoolQuick(); 10815c838251403b0be9a882540f1922577abba4c872ager@chromium.org 10825c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Instruction generation. 10835c838251403b0be9a882540f1922577abba4c872ager@chromium.org // We have 3 different kind of encoding layout on MIPS. 10845c838251403b0be9a882540f1922577abba4c872ager@chromium.org // However due to many different types of objects encoded in the same fields 10855c838251403b0be9a882540f1922577abba4c872ager@chromium.org // we have quite a few aliases for each mode. 10865c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Using the same structure to refer to Register and FPURegister would spare a 10875c838251403b0be9a882540f1922577abba4c872ager@chromium.org // few aliases, but mixing both does not look clean to me. 10885c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Anyway we could surely implement this differently. 10895c838251403b0be9a882540f1922577abba4c872ager@chromium.org 10905c838251403b0be9a882540f1922577abba4c872ager@chromium.org void GenInstrRegister(Opcode opcode, 10915c838251403b0be9a882540f1922577abba4c872ager@chromium.org Register rs, 10925c838251403b0be9a882540f1922577abba4c872ager@chromium.org Register rt, 10935c838251403b0be9a882540f1922577abba4c872ager@chromium.org Register rd, 10945c838251403b0be9a882540f1922577abba4c872ager@chromium.org uint16_t sa = 0, 10955c838251403b0be9a882540f1922577abba4c872ager@chromium.org SecondaryField func = NULLSF); 10965c838251403b0be9a882540f1922577abba4c872ager@chromium.org 10975c838251403b0be9a882540f1922577abba4c872ager@chromium.org void GenInstrRegister(Opcode opcode, 10987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org Register rs, 10997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org Register rt, 11007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org uint16_t msb, 11017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org uint16_t lsb, 11027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org SecondaryField func); 11037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 11047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void GenInstrRegister(Opcode opcode, 11055c838251403b0be9a882540f1922577abba4c872ager@chromium.org SecondaryField fmt, 11065c838251403b0be9a882540f1922577abba4c872ager@chromium.org FPURegister ft, 11075c838251403b0be9a882540f1922577abba4c872ager@chromium.org FPURegister fs, 11085c838251403b0be9a882540f1922577abba4c872ager@chromium.org FPURegister fd, 11095c838251403b0be9a882540f1922577abba4c872ager@chromium.org SecondaryField func = NULLSF); 11105c838251403b0be9a882540f1922577abba4c872ager@chromium.org 11115c838251403b0be9a882540f1922577abba4c872ager@chromium.org void GenInstrRegister(Opcode opcode, 111259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org FPURegister fr, 111359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org FPURegister ft, 111459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org FPURegister fs, 111559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org FPURegister fd, 111659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org SecondaryField func = NULLSF); 111759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org 111859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org void GenInstrRegister(Opcode opcode, 11195c838251403b0be9a882540f1922577abba4c872ager@chromium.org SecondaryField fmt, 11205c838251403b0be9a882540f1922577abba4c872ager@chromium.org Register rt, 11215c838251403b0be9a882540f1922577abba4c872ager@chromium.org FPURegister fs, 11225c838251403b0be9a882540f1922577abba4c872ager@chromium.org FPURegister fd, 11235c838251403b0be9a882540f1922577abba4c872ager@chromium.org SecondaryField func = NULLSF); 11245c838251403b0be9a882540f1922577abba4c872ager@chromium.org 11257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void GenInstrRegister(Opcode opcode, 11267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org SecondaryField fmt, 11277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org Register rt, 11287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org FPUControlRegister fs, 11297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org SecondaryField func = NULLSF); 11307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 11315c838251403b0be9a882540f1922577abba4c872ager@chromium.org 11325c838251403b0be9a882540f1922577abba4c872ager@chromium.org void GenInstrImmediate(Opcode opcode, 11335c838251403b0be9a882540f1922577abba4c872ager@chromium.org Register rs, 11345c838251403b0be9a882540f1922577abba4c872ager@chromium.org Register rt, 11355c838251403b0be9a882540f1922577abba4c872ager@chromium.org int32_t j); 11365c838251403b0be9a882540f1922577abba4c872ager@chromium.org void GenInstrImmediate(Opcode opcode, 11375c838251403b0be9a882540f1922577abba4c872ager@chromium.org Register rs, 11385c838251403b0be9a882540f1922577abba4c872ager@chromium.org SecondaryField SF, 11395c838251403b0be9a882540f1922577abba4c872ager@chromium.org int32_t j); 11405c838251403b0be9a882540f1922577abba4c872ager@chromium.org void GenInstrImmediate(Opcode opcode, 11415c838251403b0be9a882540f1922577abba4c872ager@chromium.org Register r1, 11425c838251403b0be9a882540f1922577abba4c872ager@chromium.org FPURegister r2, 11435c838251403b0be9a882540f1922577abba4c872ager@chromium.org int32_t j); 11445c838251403b0be9a882540f1922577abba4c872ager@chromium.org 11455c838251403b0be9a882540f1922577abba4c872ager@chromium.org 11465c838251403b0be9a882540f1922577abba4c872ager@chromium.org void GenInstrJump(Opcode opcode, 11475c838251403b0be9a882540f1922577abba4c872ager@chromium.org uint32_t address); 11485c838251403b0be9a882540f1922577abba4c872ager@chromium.org 11497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Helpers. 11507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void LoadRegPlusOffsetToAt(const MemOperand& src); 11515c838251403b0be9a882540f1922577abba4c872ager@chromium.org 11525c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Labels. 11535c838251403b0be9a882540f1922577abba4c872ager@chromium.org void print(Label* L); 11545c838251403b0be9a882540f1922577abba4c872ager@chromium.org void bind_to(Label* L, int pos); 11555c838251403b0be9a882540f1922577abba4c872ager@chromium.org void next(Label* L); 11565c838251403b0be9a882540f1922577abba4c872ager@chromium.org 11577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // One trampoline consists of: 11587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // - space for trampoline slots, 11597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // - space for labels. 11607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // 11617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Space for trampoline slots is equal to slot_count * 2 * kInstrSize. 11627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Space for trampoline slots preceeds space for labels. Each label is of one 11637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // instruction size, so total amount for labels is equal to 11647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // label_count * kInstrSize. 11657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org class Trampoline { 11667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org public: 11673cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org Trampoline() { 11683cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org start_ = 0; 11693cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org next_slot_ = 0; 11703cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org free_slot_count_ = 0; 11713cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org end_ = 0; 11723cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org } 11733cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org Trampoline(int start, int slot_count) { 11747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org start_ = start; 11757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org next_slot_ = start; 11767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org free_slot_count_ = slot_count; 11773cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org end_ = start + slot_count * kTrampolineSlotsSize; 11787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 11797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int start() { 11807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return start_; 11817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 11827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int end() { 11837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return end_; 11847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 11857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int take_slot() { 118683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org int trampoline_slot = kInvalidSlotPos; 118783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org if (free_slot_count_ <= 0) { 118883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // We have run out of space on trampolines. 118983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Make sure we fail in debug mode, so we become aware of each case 119083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // when this happens. 119183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org ASSERT(0); 119283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Internal exception will be caught. 119383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org } else { 119483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org trampoline_slot = next_slot_; 119583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org free_slot_count_--; 11963cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org next_slot_ += kTrampolineSlotsSize; 119783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org } 11987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return trampoline_slot; 11997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 120083e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org 12017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org private: 12027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int start_; 12037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int end_; 12047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int next_slot_; 12057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int free_slot_count_; 12067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org }; 12077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 12083cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org int32_t get_trampoline_entry(int32_t pos); 12093cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org int unbound_labels_count_; 12103cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // If trampoline is emitted, generated code is becoming large. As this is 12113cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // already a slow case which can possibly break our code generation for the 12123cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // extreme case, we use this information to trigger different mode of 12133cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // branch instruction generation, where we use jump instructions rather 12143cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org // than regular branch instructions. 12153cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org bool trampoline_emitted_; 12163cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org static const int kTrampolineSlotsSize = 4 * kInstrSize; 12177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; 121883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static const int kInvalidSlotPos = -1; 12197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 12203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org Trampoline trampoline_; 122183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org bool internal_trampoline_exception_; 12227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 12235c838251403b0be9a882540f1922577abba4c872ager@chromium.org friend class RegExpMacroAssemblerMIPS; 12245c838251403b0be9a882540f1922577abba4c872ager@chromium.org friend class RelocInfo; 12257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org friend class CodePatcher; 12267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org friend class BlockTrampolinePoolScope; 12277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 12287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org PositionsRecorder positions_recorder_; 12297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org friend class PositionsRecorder; 12307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org friend class EnsureSpace; 12317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}; 12327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 12337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 12347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgclass EnsureSpace BASE_EMBEDDED { 12357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org public: 12367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org explicit EnsureSpace(Assembler* assembler) { 12377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org assembler->CheckBuffer(); 12387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 12395c838251403b0be9a882540f1922577abba4c872ager@chromium.org}; 12405c838251403b0be9a882540f1922577abba4c872ager@chromium.org 12415c838251403b0be9a882540f1922577abba4c872ager@chromium.org} } // namespace v8::internal 12425c838251403b0be9a882540f1922577abba4c872ager@chromium.org 12435c838251403b0be9a882540f1922577abba4c872ager@chromium.org#endif // V8_ARM_ASSEMBLER_MIPS_H_ 1244