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.
333233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
345c838251403b0be9a882540f1922577abba4c872ager@chromium.org
355c838251403b0be9a882540f1922577abba4c872ager@chromium.org
365c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "v8.h"
379dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3893a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_MIPS
399dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
405c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "mips/assembler-mips-inl.h"
415c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "serialize.h"
425c838251403b0be9a882540f1922577abba4c872ager@chromium.org
435c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace v8 {
445c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace internal {
455c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org#ifdef DEBUG
4783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgbool CpuFeatures::initialized_ = false;
4883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org#endif
4983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgunsigned CpuFeatures::supported_ = 0;
50750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgunsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
5163ea3d20e0c5531a4bb0853218d5f746117edea1mvstanton@chromium.orgunsigned CpuFeatures::cross_compile_ = 0;
525c838251403b0be9a882540f1922577abba4c872ager@chromium.org
531805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
54003650ee766f5e92756d470a37973fd371757485yangguo@chromium.orgExternalReference ExternalReference::cpu_features() {
55003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org  ASSERT(CpuFeatures::initialized_);
56003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org  return ExternalReference(&CpuFeatures::supported_);
57003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org}
58003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org
59003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org
601805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org// Get the CPU features enabled by the build. For cross compilation the
611805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org// preprocessor symbols CAN_USE_FPU_INSTRUCTIONS
621805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org// can be defined to enable FPU instructions when building the
631805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org// snapshot.
641805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.orgstatic uint64_t CpuFeaturesImpliedByCompiler() {
651805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  uint64_t answer = 0;
661805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org#ifdef CAN_USE_FPU_INSTRUCTIONS
67750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  answer |= static_cast<uint64_t>(1) << FPU;
681805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org#endif  // def CAN_USE_FPU_INSTRUCTIONS
691805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
701805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org#ifdef __mips__
711805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // If the compiler is allowed to use FPU then we can use FPU too in our code
721805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // generation even when generating snapshots.  This won't work for cross
731805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // compilation.
741805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org#if(defined(__mips_hard_float) && __mips_hard_float != 0)
75750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  answer |= static_cast<uint64_t>(1) << FPU;
761805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org#endif  // defined(__mips_hard_float) && __mips_hard_float != 0
771805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org#endif  // def __mips__
781805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
791805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  return answer;
801805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org}
811805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
821805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
8359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.orgconst char* DoubleRegister::AllocationIndexToString(int index) {
84e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
85e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  const char* const names[] = {
86e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f0",
87e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f2",
88e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f4",
89e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f6",
90e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f8",
91e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f10",
92e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f12",
93e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f14",
94e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f16",
95e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f18",
96e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f20",
97e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f22",
98e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f24",
99e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    "f26"
100e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  };
101e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return names[index];
10259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org}
10359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
10459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
10583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgvoid CpuFeatures::Probe() {
106b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  unsigned standard_features = (OS::CpuFeaturesImpliedByPlatform() |
107b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org                                CpuFeaturesImpliedByCompiler());
108b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  ASSERT(supported_ == 0 || supported_ == standard_features);
10983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org#ifdef DEBUG
11083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  initialized_ = true;
11183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org#endif
1121805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
1131805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Get the features implied by the OS and the compiler settings. This is the
1141805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // minimal set of features which is also allowed for generated code in the
1151805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // snapshot.
116b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  supported_ |= standard_features;
1171805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
1181805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  if (Serializer::enabled()) {
1191805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    // No probing for features if we might serialize (generate snapshot).
1201805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    return;
1211805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  }
1221805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
1237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // If the compiler is allowed to use fpu then we can use fpu too in our
1247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // code generation.
1257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#if !defined(__mips__)
126e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // For the simulator build, use FPU.
127e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  supported_ |= static_cast<uint64_t>(1) << FPU;
1287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#else
1291805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Probe for additional features not already known to be available.
1301e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  CPU cpu;
1311e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  if (cpu.has_fpu()) {
1327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    // This implementation also sets the FPU flags if
1337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    // runtime detection of FPU returns true.
134750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    supported_ |= static_cast<uint64_t>(1) << FPU;
135750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << FPU;
1367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
1377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#endif
1387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1395c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1405c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1415c838251403b0be9a882540f1922577abba4c872ager@chromium.orgint ToNumber(Register reg) {
1425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(reg.is_valid());
1435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  const int kNumbers[] = {
1445c838251403b0be9a882540f1922577abba4c872ager@chromium.org    0,    // zero_reg
1455c838251403b0be9a882540f1922577abba4c872ager@chromium.org    1,    // at
1465c838251403b0be9a882540f1922577abba4c872ager@chromium.org    2,    // v0
1475c838251403b0be9a882540f1922577abba4c872ager@chromium.org    3,    // v1
1485c838251403b0be9a882540f1922577abba4c872ager@chromium.org    4,    // a0
1495c838251403b0be9a882540f1922577abba4c872ager@chromium.org    5,    // a1
1505c838251403b0be9a882540f1922577abba4c872ager@chromium.org    6,    // a2
1515c838251403b0be9a882540f1922577abba4c872ager@chromium.org    7,    // a3
1525c838251403b0be9a882540f1922577abba4c872ager@chromium.org    8,    // t0
1535c838251403b0be9a882540f1922577abba4c872ager@chromium.org    9,    // t1
1545c838251403b0be9a882540f1922577abba4c872ager@chromium.org    10,   // t2
1555c838251403b0be9a882540f1922577abba4c872ager@chromium.org    11,   // t3
1565c838251403b0be9a882540f1922577abba4c872ager@chromium.org    12,   // t4
1575c838251403b0be9a882540f1922577abba4c872ager@chromium.org    13,   // t5
1585c838251403b0be9a882540f1922577abba4c872ager@chromium.org    14,   // t6
1595c838251403b0be9a882540f1922577abba4c872ager@chromium.org    15,   // t7
1605c838251403b0be9a882540f1922577abba4c872ager@chromium.org    16,   // s0
1615c838251403b0be9a882540f1922577abba4c872ager@chromium.org    17,   // s1
1625c838251403b0be9a882540f1922577abba4c872ager@chromium.org    18,   // s2
1635c838251403b0be9a882540f1922577abba4c872ager@chromium.org    19,   // s3
1645c838251403b0be9a882540f1922577abba4c872ager@chromium.org    20,   // s4
1655c838251403b0be9a882540f1922577abba4c872ager@chromium.org    21,   // s5
1665c838251403b0be9a882540f1922577abba4c872ager@chromium.org    22,   // s6
1675c838251403b0be9a882540f1922577abba4c872ager@chromium.org    23,   // s7
1685c838251403b0be9a882540f1922577abba4c872ager@chromium.org    24,   // t8
1695c838251403b0be9a882540f1922577abba4c872ager@chromium.org    25,   // t9
1705c838251403b0be9a882540f1922577abba4c872ager@chromium.org    26,   // k0
1715c838251403b0be9a882540f1922577abba4c872ager@chromium.org    27,   // k1
1725c838251403b0be9a882540f1922577abba4c872ager@chromium.org    28,   // gp
1735c838251403b0be9a882540f1922577abba4c872ager@chromium.org    29,   // sp
1747d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    30,   // fp
1755c838251403b0be9a882540f1922577abba4c872ager@chromium.org    31,   // ra
1765c838251403b0be9a882540f1922577abba4c872ager@chromium.org  };
1775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  return kNumbers[reg.code()];
1785c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
1795c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1815c838251403b0be9a882540f1922577abba4c872ager@chromium.orgRegister ToRegister(int num) {
1825c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(num >= 0 && num < kNumRegisters);
1835c838251403b0be9a882540f1922577abba4c872ager@chromium.org  const Register kRegisters[] = {
1845c838251403b0be9a882540f1922577abba4c872ager@chromium.org    zero_reg,
1855c838251403b0be9a882540f1922577abba4c872ager@chromium.org    at,
1865c838251403b0be9a882540f1922577abba4c872ager@chromium.org    v0, v1,
1875c838251403b0be9a882540f1922577abba4c872ager@chromium.org    a0, a1, a2, a3,
1885c838251403b0be9a882540f1922577abba4c872ager@chromium.org    t0, t1, t2, t3, t4, t5, t6, t7,
1895c838251403b0be9a882540f1922577abba4c872ager@chromium.org    s0, s1, s2, s3, s4, s5, s6, s7,
1905c838251403b0be9a882540f1922577abba4c872ager@chromium.org    t8, t9,
1915c838251403b0be9a882540f1922577abba4c872ager@chromium.org    k0, k1,
1925c838251403b0be9a882540f1922577abba4c872ager@chromium.org    gp,
1935c838251403b0be9a882540f1922577abba4c872ager@chromium.org    sp,
1947d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    fp,
1955c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ra
1965c838251403b0be9a882540f1922577abba4c872ager@chromium.org  };
1975c838251403b0be9a882540f1922577abba4c872ager@chromium.org  return kRegisters[num];
1985c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
1995c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2005c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2015c838251403b0be9a882540f1922577abba4c872ager@chromium.org// -----------------------------------------------------------------------------
2025c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Implementation of RelocInfo.
2035c838251403b0be9a882540f1922577abba4c872ager@chromium.org
20434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgconst int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
20534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org                                  1 << RelocInfo::INTERNAL_REFERENCE;
2065c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool RelocInfo::IsCodedSpecially() {
2097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // The deserializer needs to know whether a pointer is specially coded.  Being
2107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // specially coded on MIPS means that it is a lui/ori instruction, and that is
2117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // always the case inside code objects.
2127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return true;
2137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
2147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2165c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Patch the code at the current address with the supplied instructions.
2175c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid RelocInfo::PatchCode(byte* instructions, int instruction_count) {
2185c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr* pc = reinterpret_cast<Instr*>(pc_);
2195c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr* instr = reinterpret_cast<Instr*>(instructions);
2205c838251403b0be9a882540f1922577abba4c872ager@chromium.org  for (int i = 0; i < instruction_count; i++) {
2215c838251403b0be9a882540f1922577abba4c872ager@chromium.org    *(pc + i) = *(instr + i);
2225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
2235c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2245c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Indicate that code has changed.
2255c838251403b0be9a882540f1922577abba4c872ager@chromium.org  CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
2265c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
2275c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2285c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2295c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Patch the code at the current PC with a call to the target address.
2305c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Additional guard instructions can be added if required.
2315c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
2325c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Patch the code at the current address with a call to the target.
2335c838251403b0be9a882540f1922577abba4c872ager@chromium.org  UNIMPLEMENTED_MIPS();
2345c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
2355c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2365c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2375c838251403b0be9a882540f1922577abba4c872ager@chromium.org// -----------------------------------------------------------------------------
2385c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Implementation of Operand and MemOperand.
2395c838251403b0be9a882540f1922577abba4c872ager@chromium.org// See assembler-mips-inl.h for inlined constructors.
2405c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2415c838251403b0be9a882540f1922577abba4c872ager@chromium.orgOperand::Operand(Handle<Object> handle) {
24279e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org  AllowDeferredHandleDereference using_raw_address;
2435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  rm_ = no_reg;
2445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Verify all Objects referred by code are NOT in new space.
2455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Object* obj = *handle;
2465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if (obj->IsHeapObject()) {
247e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
2485c838251403b0be9a882540f1922577abba4c872ager@chromium.org    imm32_ = reinterpret_cast<intptr_t>(handle.location());
2495c838251403b0be9a882540f1922577abba4c872ager@chromium.org    rmode_ = RelocInfo::EMBEDDED_OBJECT;
2505c838251403b0be9a882540f1922577abba4c872ager@chromium.org  } else {
2515c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // No relocation needed.
2525c838251403b0be9a882540f1922577abba4c872ager@chromium.org    imm32_ = reinterpret_cast<intptr_t>(obj);
25359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    rmode_ = RelocInfo::NONE32;
2545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
2555c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
2565c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgMemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) {
2595c838251403b0be9a882540f1922577abba4c872ager@chromium.org  offset_ = offset;
2605c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
2615c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2625c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2635c838251403b0be9a882540f1922577abba4c872ager@chromium.org// -----------------------------------------------------------------------------
2647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Specific instructions, constants, and masks.
2657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgstatic const int kNegOffset = 0x00008000;
2677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
2687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// operations as post-increment of sp.
2697d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgconst Instr kPopInstruction = ADDIU | (kRegister_sp_Code << kRsShift)
2707d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org      | (kRegister_sp_Code << kRtShift) | (kPointerSize & kImm16Mask);
2717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
2727d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgconst Instr kPushInstruction = ADDIU | (kRegister_sp_Code << kRsShift)
2737d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org      | (kRegister_sp_Code << kRtShift) | (-kPointerSize & kImm16Mask);
2747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// sw(r, MemOperand(sp, 0))
2757d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgconst Instr kPushRegPattern = SW | (kRegister_sp_Code << kRsShift)
2767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      |  (0 & kImm16Mask);
2777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org//  lw(r, MemOperand(sp, 0))
2787d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgconst Instr kPopRegPattern = LW | (kRegister_sp_Code << kRsShift)
2797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      |  (0 & kImm16Mask);
2807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2817d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgconst Instr kLwRegFpOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
2827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      |  (0 & kImm16Mask);
2837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2847d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgconst Instr kSwRegFpOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
2857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      |  (0 & kImm16Mask);
2867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2877d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgconst Instr kLwRegFpNegOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
2887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      |  (kNegOffset & kImm16Mask);
2897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2907d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgconst Instr kSwRegFpNegOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
2917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      |  (kNegOffset & kImm16Mask);
2927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// A mask for the Rt register for push, pop, lw, sw instructions.
2937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst Instr kRtMask = kRtFieldMask;
2947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst Instr kLwSwInstrTypeMask = 0xffe00000;
2957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst Instr kLwSwInstrArgumentMask  = ~kLwSwInstrTypeMask;
2967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst Instr kLwSwOffsetMask = kImm16Mask;
2977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2998e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.orgAssembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
3008e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org    : AssemblerBase(isolate, buffer, buffer_size),
301471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org      recorded_ast_id_(TypeFeedbackId::None()),
302e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org      positions_recorder_(this) {
3038e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
3047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  last_trampoline_pool_end_ = 0;
3067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  no_trampoline_pool_before_ = 0;
3077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  trampoline_pool_blocked_nesting_ = 0;
3083cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // We leave space (16 * kTrampolineSlotsSize)
3093cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // for BlockTrampolinePoolScope buffer.
3103cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  next_buffer_check_ = kMaxBranchOffset - kTrampolineSlotsSize * 16;
31183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  internal_trampoline_exception_ = false;
312c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  last_bound_pos_ = 0;
31383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
3143cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  trampoline_emitted_ = false;
3153cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  unbound_labels_count_ = 0;
3163cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  block_buffer_growth_ = false;
3173cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
318717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org  ClearRecordedAstId();
3195c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
3205c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3215c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3225c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::GetCode(CodeDesc* desc) {
3237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(pc_ <= reloc_info_writer.pos());  // No overlap.
324f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up code descriptor.
3255c838251403b0be9a882540f1922577abba4c872ager@chromium.org  desc->buffer = buffer_;
3265c838251403b0be9a882540f1922577abba4c872ager@chromium.org  desc->buffer_size = buffer_size_;
3275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  desc->instr_size = pc_offset();
3285c838251403b0be9a882540f1922577abba4c872ager@chromium.org  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
3299af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  desc->origin = this;
3305c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
3315c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3325c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::Align(int m) {
3347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(m >= 4 && IsPowerOf2(m));
3357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  while ((pc_offset() & (m - 1)) != 0) {
3367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    nop();
3377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
3387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
3397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::CodeTargetAlign() {
3427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // No advantage to aligning branch/call targets to more than
3437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // single instruction, that I am aware of.
3447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Align(4);
3457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
3467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
34883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgRegister Assembler::GetRtReg(Instr instr) {
3497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Register rt;
35083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  rt.code_ = (instr & kRtFieldMask) >> kRtShift;
3517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return rt;
3527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
3537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
35583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgRegister Assembler::GetRsReg(Instr instr) {
35683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Register rs;
35783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  rs.code_ = (instr & kRsFieldMask) >> kRsShift;
35883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return rs;
35983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
36083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
36183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
36283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgRegister Assembler::GetRdReg(Instr instr) {
36383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Register rd;
36483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  rd.code_ = (instr & kRdFieldMask) >> kRdShift;
36583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return rd;
36683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
36783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
36883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
36983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetRt(Instr instr) {
37083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return (instr & kRtFieldMask) >> kRtShift;
37183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
37283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
37383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
37483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetRtField(Instr instr) {
37583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return instr & kRtFieldMask;
37683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
37783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
37883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
37983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetRs(Instr instr) {
38083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return (instr & kRsFieldMask) >> kRsShift;
38183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
38283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
38383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
38483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetRsField(Instr instr) {
38583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return instr & kRsFieldMask;
38683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
38783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
38883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
38983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetRd(Instr instr) {
39083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return  (instr & kRdFieldMask) >> kRdShift;
39183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
39283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
39383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
39483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetRdField(Instr instr) {
39583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return  instr & kRdFieldMask;
39683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
39783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
39883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
39983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetSa(Instr instr) {
40083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return (instr & kSaFieldMask) >> kSaShift;
40183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
40283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
40383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
40483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetSaField(Instr instr) {
40583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return instr & kSaFieldMask;
40683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
40783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
40883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
40983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetOpcodeField(Instr instr) {
41083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return instr & kOpcodeMask;
41183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
41283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
41383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
4143cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orguint32_t Assembler::GetFunction(Instr instr) {
4153cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  return (instr & kFunctionFieldMask) >> kFunctionShift;
4163cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org}
4173cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
4183cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
4193cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orguint32_t Assembler::GetFunctionField(Instr instr) {
4203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  return instr & kFunctionFieldMask;
4213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org}
4223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
4233cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
42483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetImmediate16(Instr instr) {
42583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return instr & kImm16Mask;
42683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
42783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
42883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
42983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orguint32_t Assembler::GetLabelConst(Instr instr) {
43083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return instr & ~kImm16Mask;
43183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
43283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
43383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
4347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsPop(Instr instr) {
4357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return (instr & ~kRtMask) == kPopRegPattern;
4367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
4377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsPush(Instr instr) {
4407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return (instr & ~kRtMask) == kPushRegPattern;
4417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
4427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsSwRegFpOffset(Instr instr) {
4457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern);
4467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
4477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsLwRegFpOffset(Instr instr) {
4507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern);
4517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
4527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsSwRegFpNegOffset(Instr instr) {
4557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
4567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          kSwRegFpNegOffsetPattern);
4577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
4587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsLwRegFpNegOffset(Instr instr) {
4617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
4627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          kLwRegFpNegOffsetPattern);
4637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
4647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4665c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Labels refer to positions in the (to be) generated code.
4675c838251403b0be9a882540f1922577abba4c872ager@chromium.org// There are bound, linked, and unused labels.
4685c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
4695c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Bound labels refer to known positions in the already
4705c838251403b0be9a882540f1922577abba4c872ager@chromium.org// generated code. pos() is the position the label refers to.
4715c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
4725c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Linked labels refer to unknown positions in the code
4735c838251403b0be9a882540f1922577abba4c872ager@chromium.org// to be generated; pos() is the position of the last
4745c838251403b0be9a882540f1922577abba4c872ager@chromium.org// instruction using the label.
4755c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// The link chain is terminated by a value in the instruction of -1,
4777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// which is an otherwise illegal value (branch -1 is inf loop).
4787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// The instruction 16-bit offset field addresses 32-bit words, but in
4797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// code is conv to an 18-bit value addressing bytes, hence the -4 value.
4805c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4815c838251403b0be9a882540f1922577abba4c872ager@chromium.orgconst int kEndOfChain = -4;
4823cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org// Determines the end of the Jump chain (a subset of the label link chain).
4833cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orgconst int kEndOfJumpChain = 0;
4845c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsBranch(Instr instr) {
48783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  uint32_t opcode   = GetOpcodeField(instr);
48883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  uint32_t rt_field = GetRtField(instr);
48983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  uint32_t rs_field = GetRsField(instr);
4905c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Checks if the instruction is a branch.
4915c838251403b0be9a882540f1922577abba4c872ager@chromium.org  return opcode == BEQ ||
4925c838251403b0be9a882540f1922577abba4c872ager@chromium.org      opcode == BNE ||
4935c838251403b0be9a882540f1922577abba4c872ager@chromium.org      opcode == BLEZ ||
4945c838251403b0be9a882540f1922577abba4c872ager@chromium.org      opcode == BGTZ ||
4955c838251403b0be9a882540f1922577abba4c872ager@chromium.org      opcode == BEQL ||
4965c838251403b0be9a882540f1922577abba4c872ager@chromium.org      opcode == BNEL ||
4975c838251403b0be9a882540f1922577abba4c872ager@chromium.org      opcode == BLEZL ||
49883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      opcode == BGTZL ||
4995c838251403b0be9a882540f1922577abba4c872ager@chromium.org      (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
5005c838251403b0be9a882540f1922577abba4c872ager@chromium.org                            rt_field == BLTZAL || rt_field == BGEZAL)) ||
5017bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org      (opcode == COP1 && rs_field == BC1);  // Coprocessor branch.
5027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
5037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
504e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
5057bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.orgbool Assembler::IsEmittedConstant(Instr instr) {
5067bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  uint32_t label_constant = GetLabelConst(instr);
5077bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  return label_constant == 0;  // Emitted label const in reg-exp engine.
5087bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org}
5097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
510e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
51183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgbool Assembler::IsBeq(Instr instr) {
51283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return GetOpcodeField(instr) == BEQ;
51383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
51483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
51583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
51683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgbool Assembler::IsBne(Instr instr) {
51783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return GetOpcodeField(instr) == BNE;
51883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
51983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
52083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
5213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orgbool Assembler::IsJump(Instr instr) {
5223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  uint32_t opcode   = GetOpcodeField(instr);
5233cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  uint32_t rt_field = GetRtField(instr);
5243cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  uint32_t rd_field = GetRdField(instr);
5253cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  uint32_t function_field = GetFunctionField(instr);
5263cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Checks if the instruction is a jump.
5273cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  return opcode == J || opcode == JAL ||
5283cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      (opcode == SPECIAL && rt_field == 0 &&
5293cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      ((function_field == JALR) || (rd_field == 0 && (function_field == JR))));
5303cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org}
5313cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
5323cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
5333cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orgbool Assembler::IsJ(Instr instr) {
5343cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  uint32_t opcode = GetOpcodeField(instr);
5353cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Checks if the instruction is a jump.
5363cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  return opcode == J;
5373cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org}
5383cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
5393cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
54034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgbool Assembler::IsJal(Instr instr) {
54134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  return GetOpcodeField(instr) == JAL;
54234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org}
54334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
544e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
54534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgbool Assembler::IsJr(Instr instr) {
54634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR;
54734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org}
54834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
549e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
55034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgbool Assembler::IsJalr(Instr instr) {
55134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JALR;
55234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org}
55334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
55434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
5553cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orgbool Assembler::IsLui(Instr instr) {
5563cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  uint32_t opcode = GetOpcodeField(instr);
5573cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Checks if the instruction is a load upper immediate.
5583cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  return opcode == LUI;
5593cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org}
5603cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
5613cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
5623cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orgbool Assembler::IsOri(Instr instr) {
5633cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  uint32_t opcode = GetOpcodeField(instr);
5643cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Checks if the instruction is a load upper immediate.
5653cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  return opcode == ORI;
5663cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org}
5673cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
5683cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
5697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsNop(Instr instr, unsigned int type) {
5707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // See Assembler::nop(type).
5717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(type < 32);
57283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  uint32_t opcode = GetOpcodeField(instr);
57333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  uint32_t function = GetFunctionField(instr);
57483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  uint32_t rt = GetRt(instr);
57533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  uint32_t rd = GetRd(instr);
57683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  uint32_t sa = GetSa(instr);
5777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
57833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // Traditional mips nop == sll(zero_reg, zero_reg, 0)
57933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // When marking non-zero type, use sll(zero_reg, at, type)
58033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // to avoid use of mips ssnop and ehb special encodings
58133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // of the sll instruction.
5827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
58333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  Register nop_rt_reg = (type == 0) ? zero_reg : at;
58433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  bool ret = (opcode == SPECIAL && function == SLL &&
58533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org              rd == static_cast<uint32_t>(ToNumber(zero_reg)) &&
58633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org              rt == static_cast<uint32_t>(ToNumber(nop_rt_reg)) &&
5877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org              sa == type);
5887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ret;
5907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
5917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgint32_t Assembler::GetBranchOffset(Instr instr) {
5947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(IsBranch(instr));
59559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  return (static_cast<int16_t>(instr & kImm16Mask)) << 2;
5967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
5977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsLw(Instr instr) {
6007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ((instr & kOpcodeMask) == LW);
6017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
6027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgint16_t Assembler::GetLwOffset(Instr instr) {
6057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(IsLw(instr));
6067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ((instr & kImm16Mask));
6077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
6087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgInstr Assembler::SetLwOffset(Instr instr, int16_t offset) {
6117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(IsLw(instr));
6127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // We actually create a new lw instruction based on the original one.
6147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask)
6157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      | (offset & kImm16Mask);
6167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return temp_instr;
6187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
6197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsSw(Instr instr) {
6227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ((instr & kOpcodeMask) == SW);
6237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
6247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgInstr Assembler::SetSwOffset(Instr instr, int16_t offset) {
6277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(IsSw(instr));
6287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
6297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
6307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::IsAddImmediate(Instr instr) {
6337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ((instr & kOpcodeMask) == ADDIU);
6347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
6357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
6377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgInstr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
6387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(IsAddImmediate(instr));
6397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
6405c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
6415c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6425c838251403b0be9a882540f1922577abba4c872ager@chromium.org
64383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgbool Assembler::IsAndImmediate(Instr instr) {
64483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return GetOpcodeField(instr) == ANDI;
64583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
64683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
64783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
6485c838251403b0be9a882540f1922577abba4c872ager@chromium.orgint Assembler::target_at(int32_t pos) {
6495c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = instr_at(pos);
6505c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if ((instr & ~kImm16Mask) == 0) {
6515c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // Emitted label constant, not part of a branch.
6527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    if (instr == 0) {
6537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org       return kEndOfChain;
6547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org     } else {
6557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org       int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
6567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org       return (imm18 + pos);
6577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org     }
6585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
6593cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Check we have a branch or jump instruction.
6603cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr));
6615c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
6625c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // the compiler uses arithmectic shifts for signed integers.
6633cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  if (IsBranch(instr)) {
6643cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
6655c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6663cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    if (imm18 == kEndOfChain) {
6673cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      // EndOfChain sentinel is returned directly, not relative to pc or pos.
6683cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      return kEndOfChain;
6693cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    } else {
6703cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      return pos + kBranchPCOffset + imm18;
6713cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
6723cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  } else if (IsLui(instr)) {
6733cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
6743cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
6753cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT(IsOri(instr_ori));
6763cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
6773cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
6783cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
6793cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    if (imm == kEndOfJumpChain) {
6803cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      // EndOfChain sentinel is returned directly, not relative to pc or pos.
6813cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      return kEndOfChain;
6823cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    } else {
6833cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
6843cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      int32_t delta = instr_address - imm;
6853cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      ASSERT(pos > delta);
6863cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      return pos - delta;
6873cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
6887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {
6893cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
6903cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    if (imm28 == kEndOfJumpChain) {
6913cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      // EndOfChain sentinel is returned directly, not relative to pc or pos.
6923cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      return kEndOfChain;
6933cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    } else {
6943cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
6953cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      instr_address &= kImm28Mask;
6963cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      int32_t delta = instr_address - imm28;
6973cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      ASSERT(pos > delta);
6983cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      return pos - delta;
6993cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
7007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
7015c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
7025c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7035c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7045c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::target_at_put(int32_t pos, int32_t target_pos) {
7055c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = instr_at(pos);
7065c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if ((instr & ~kImm16Mask) == 0) {
7075c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT(target_pos == kEndOfChain || target_pos >= 0);
7085c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // Emitted label constant, not part of a branch.
7095c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // Make label relative to Code* of generated Code object.
7105c838251403b0be9a882540f1922577abba4c872ager@chromium.org    instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
7115c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return;
7125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
7135c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7143cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr));
7153cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  if (IsBranch(instr)) {
7163cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    int32_t imm18 = target_pos - (pos + kBranchPCOffset);
7173cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT((imm18 & 3) == 0);
7183cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
7193cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr &= ~kImm16Mask;
7203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    int32_t imm16 = imm18 >> 2;
7213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT(is_int16(imm16));
7223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
7233cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_at_put(pos, instr | (imm16 & kImm16Mask));
7243cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  } else if (IsLui(instr)) {
7253cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
7263cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
7273cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT(IsOri(instr_ori));
72859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
7293cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT((imm & 3) == 0);
7303cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
7313cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_lui &= ~kImm16Mask;
7323cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_ori &= ~kImm16Mask;
7333cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
7343cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_at_put(pos + 0 * Assembler::kInstrSize,
7353cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org                 instr_lui | ((imm & kHiMask) >> kLuiShift));
7363cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_at_put(pos + 1 * Assembler::kInstrSize,
7373cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org                 instr_ori | (imm & kImm16Mask));
7383cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  } else {
73959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    uint32_t imm28 = reinterpret_cast<uint32_t>(buffer_) + target_pos;
7403cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    imm28 &= kImm28Mask;
7413cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT((imm28 & 3) == 0);
7425c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7433cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr &= ~kImm26Mask;
7443cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    uint32_t imm26 = imm28 >> 2;
7453cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT(is_uint26(imm26));
7465c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7473cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_at_put(pos, instr | (imm26 & kImm26Mask));
7483cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
7495c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
7505c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7515c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7525c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::print(Label* L) {
7535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if (L->is_unused()) {
7545c838251403b0be9a882540f1922577abba4c872ager@chromium.org    PrintF("unused label\n");
7555c838251403b0be9a882540f1922577abba4c872ager@chromium.org  } else if (L->is_bound()) {
7565c838251403b0be9a882540f1922577abba4c872ager@chromium.org    PrintF("bound label to %d\n", L->pos());
7575c838251403b0be9a882540f1922577abba4c872ager@chromium.org  } else if (L->is_linked()) {
7585c838251403b0be9a882540f1922577abba4c872ager@chromium.org    Label l = *L;
7595c838251403b0be9a882540f1922577abba4c872ager@chromium.org    PrintF("unbound label");
7605c838251403b0be9a882540f1922577abba4c872ager@chromium.org    while (l.is_linked()) {
7615c838251403b0be9a882540f1922577abba4c872ager@chromium.org      PrintF("@ %d ", l.pos());
7625c838251403b0be9a882540f1922577abba4c872ager@chromium.org      Instr instr = instr_at(l.pos());
7635c838251403b0be9a882540f1922577abba4c872ager@chromium.org      if ((instr & ~kImm16Mask) == 0) {
7645c838251403b0be9a882540f1922577abba4c872ager@chromium.org        PrintF("value\n");
7655c838251403b0be9a882540f1922577abba4c872ager@chromium.org      } else {
7665c838251403b0be9a882540f1922577abba4c872ager@chromium.org        PrintF("%d\n", instr);
7675c838251403b0be9a882540f1922577abba4c872ager@chromium.org      }
7685c838251403b0be9a882540f1922577abba4c872ager@chromium.org      next(&l);
7695c838251403b0be9a882540f1922577abba4c872ager@chromium.org    }
7705c838251403b0be9a882540f1922577abba4c872ager@chromium.org  } else {
7715c838251403b0be9a882540f1922577abba4c872ager@chromium.org    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
7725c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
7735c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
7745c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7755c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7765c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bind_to(Label* L, int pos) {
7777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(0 <= pos && pos <= pc_offset());  // Must have valid binding position.
7783cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  int32_t trampoline_pos = kInvalidSlotPos;
7793cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  if (L->is_linked() && !trampoline_emitted_) {
7803cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    unbound_labels_count_--;
7813cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    next_buffer_check_ += kTrampolineSlotsSize;
7823cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
7833cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
7845c838251403b0be9a882540f1922577abba4c872ager@chromium.org  while (L->is_linked()) {
7855c838251403b0be9a882540f1922577abba4c872ager@chromium.org    int32_t fixup_pos = L->pos();
7867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int32_t dist = pos - fixup_pos;
7877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    next(L);  // Call next before overwriting link with target at fixup_pos.
7883cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Instr instr = instr_at(fixup_pos);
7893cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    if (IsBranch(instr)) {
7903cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      if (dist > kMaxBranchOffset) {
7913cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        if (trampoline_pos == kInvalidSlotPos) {
7923cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org          trampoline_pos = get_trampoline_entry(fixup_pos);
7933cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org          CHECK(trampoline_pos != kInvalidSlotPos);
79483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        }
7957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org        ASSERT((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
7967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org        target_at_put(fixup_pos, trampoline_pos);
7977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org        fixup_pos = trampoline_pos;
7987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org        dist = pos - fixup_pos;
7993cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      }
8003cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      target_at_put(fixup_pos, pos);
8013cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    } else {
8027bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org      ASSERT(IsJ(instr) || IsLui(instr) || IsEmittedConstant(instr));
8033cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      target_at_put(fixup_pos, pos);
8043cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
8055c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
8065c838251403b0be9a882540f1922577abba4c872ager@chromium.org  L->bind_to(pos);
8075c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8085c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Keep track of the last bound label so we don't eliminate any instructions
8095c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // before a bound label.
8105c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if (pos > last_bound_pos_)
8115c838251403b0be9a882540f1922577abba4c872ager@chromium.org    last_bound_pos_ = pos;
8125c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
8135c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8145c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8155c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bind(Label* L) {
8167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(!L->is_bound());  // Label can only be bound once.
8175c838251403b0be9a882540f1922577abba4c872ager@chromium.org  bind_to(L, pc_offset());
8185c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
8195c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8205c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8215c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::next(Label* L) {
8225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(L->is_linked());
8235c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int link = target_at(L->pos());
8247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (link == kEndOfChain) {
8255c838251403b0be9a882540f1922577abba4c872ager@chromium.org    L->Unuse();
82680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  } else {
82780c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    ASSERT(link >= 0);
8287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    L->link_to(link);
8295c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
8305c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
8315c838251403b0be9a882540f1922577abba4c872ager@chromium.org
832e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
8333cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orgbool Assembler::is_near(Label* L) {
8343cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  if (L->is_bound()) {
8353cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    return ((pc_offset() - L->pos()) < kMaxBranchOffset - 4 * kInstrSize);
8363cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
8373cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  return false;
8383cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org}
8395c838251403b0be9a882540f1922577abba4c872ager@chromium.org
840e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
8415c838251403b0be9a882540f1922577abba4c872ager@chromium.org// We have to use a temporary register for things that can be relocated even
8425c838251403b0be9a882540f1922577abba4c872ager@chromium.org// if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
8435c838251403b0be9a882540f1922577abba4c872ager@chromium.org// space.  There is no guarantee that the relocated location can be similarly
8445c838251403b0be9a882540f1922577abba4c872ager@chromium.org// encoded.
8457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool Assembler::MustUseReg(RelocInfo::Mode rmode) {
8464cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  return !RelocInfo::IsNone(rmode);
8475c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
8485c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8495c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::GenInstrRegister(Opcode opcode,
8505c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 Register rs,
8515c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 Register rt,
8525c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 Register rd,
8535c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 uint16_t sa,
8545c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 SecondaryField func) {
8555c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
8565c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
8575c838251403b0be9a882540f1922577abba4c872ager@chromium.org      | (rd.code() << kRdShift) | (sa << kSaShift) | func;
8585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
8595c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
8605c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8615c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8625c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::GenInstrRegister(Opcode opcode,
8637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                 Register rs,
8647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                 Register rt,
8657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                 uint16_t msb,
8667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                 uint16_t lsb,
8677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                 SecondaryField func) {
8687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb));
8697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
8707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      | (msb << kRdShift) | (lsb << kSaShift) | func;
8717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  emit(instr);
8727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
8737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::GenInstrRegister(Opcode opcode,
8765c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 SecondaryField fmt,
8775c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 FPURegister ft,
8785c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 FPURegister fs,
8795c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 FPURegister fd,
8805c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 SecondaryField func) {
8815c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid());
8827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
8837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      | (fd.code() << kFdShift) | func;
8845c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
8855c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
8865c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8875c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8885c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::GenInstrRegister(Opcode opcode,
88959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                                 FPURegister fr,
89059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                                 FPURegister ft,
89159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                                 FPURegister fs,
89259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                                 FPURegister fd,
89359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                                 SecondaryField func) {
89459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  ASSERT(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid());
89559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift)
89659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org      | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
89759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  emit(instr);
89859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org}
89959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
90059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
90159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.orgvoid Assembler::GenInstrRegister(Opcode opcode,
9025c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 SecondaryField fmt,
9035c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 Register rt,
9045c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 FPURegister fs,
9055c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 FPURegister fd,
9065c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                 SecondaryField func) {
9075c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid());
9085c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = opcode | fmt | (rt.code() << kRtShift)
9097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
9107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  emit(instr);
9117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::GenInstrRegister(Opcode opcode,
9157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                 SecondaryField fmt,
9167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                 Register rt,
9177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                 FPUControlRegister fs,
9187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                 SecondaryField func) {
9197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(fs.is_valid() && rt.is_valid());
9207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Instr instr =
9217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
9225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
9235c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
9245c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9255c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9265c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Instructions with immediate value.
9275c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Registers are in the order of the instruction encoding, from left to right.
9285c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::GenInstrImmediate(Opcode opcode,
9295c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                  Register rs,
9305c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                  Register rt,
9315c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                  int32_t j) {
9325c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
9335c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
9345c838251403b0be9a882540f1922577abba4c872ager@chromium.org      | (j & kImm16Mask);
9355c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
9365c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
9375c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9385c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9395c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::GenInstrImmediate(Opcode opcode,
9405c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                  Register rs,
9415c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                  SecondaryField SF,
9425c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                  int32_t j) {
9435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(rs.is_valid() && (is_int16(j) || is_uint16(j)));
9445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
9455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
9465c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
9475c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9485c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9495c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::GenInstrImmediate(Opcode opcode,
9505c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                  Register rs,
9515c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                  FPURegister ft,
9525c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                  int32_t j) {
9535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
9545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
9555c838251403b0be9a882540f1922577abba4c872ager@chromium.org      | (j & kImm16Mask);
9565c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
9575c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
9585c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9595c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9605c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::GenInstrJump(Opcode opcode,
96134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org                             uint32_t address) {
9627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
9635c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(is_uint26(address));
9645c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = opcode | address;
9655c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
9667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
9677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9703cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org// Returns the next free trampoline entry.
9713cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orgint32_t Assembler::get_trampoline_entry(int32_t pos) {
9723cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  int32_t trampoline_entry = kInvalidSlotPos;
9737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9743cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  if (!internal_trampoline_exception_) {
9753cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    if (trampoline_.start() > pos) {
9763cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org     trampoline_entry = trampoline_.take_slot();
9777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
9783cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
9793cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    if (kInvalidSlotPos == trampoline_entry) {
9803cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      internal_trampoline_exception_ = true;
9817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
9827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
9833cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  return trampoline_entry;
9847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9873cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orguint32_t Assembler::jump_address(Label* L) {
9883cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  int32_t target_pos;
9897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9903cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  if (L->is_bound()) {
9913cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    target_pos = L->pos();
9923cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  } else {
9933cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    if (L->is_linked()) {
9943cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      target_pos = L->pos();  // L's link.
9953cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      L->link_to(pc_offset());
9963cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    } else {
9973cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      L->link_to(pc_offset());
9983cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      return kEndOfJumpChain;
99983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
10007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
10013cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
100259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
10033cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  ASSERT((imm & 3) == 0);
10043cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10053cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  return imm;
10065c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
10075c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10085c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10095c838251403b0be9a882540f1922577abba4c872ager@chromium.orgint32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
10105c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int32_t target_pos;
10117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if (L->is_bound()) {
10135c838251403b0be9a882540f1922577abba4c872ager@chromium.org    target_pos = L->pos();
10145c838251403b0be9a882540f1922577abba4c872ager@chromium.org  } else {
10155c838251403b0be9a882540f1922577abba4c872ager@chromium.org    if (L->is_linked()) {
10163cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      target_pos = L->pos();
10177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      L->link_to(pc_offset());
10185c838251403b0be9a882540f1922577abba4c872ager@chromium.org    } else {
10197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      L->link_to(pc_offset());
10203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      if (!trampoline_emitted_) {
10213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        unbound_labels_count_++;
10223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        next_buffer_check_ -= kTrampolineSlotsSize;
10233cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      }
10247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      return kEndOfChain;
10255c838251403b0be9a882540f1922577abba4c872ager@chromium.org    }
10265c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
10275c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10285c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
10297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT((offset & 3) == 0);
10307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(is_int16(offset >> 2));
10317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10325c838251403b0be9a882540f1922577abba4c872ager@chromium.org  return offset;
10335c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
10345c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10355c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10365c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::label_at_put(Label* L, int at_offset) {
10375c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int target_pos;
10385c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if (L->is_bound()) {
10395c838251403b0be9a882540f1922577abba4c872ager@chromium.org    target_pos = L->pos();
10407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
10415c838251403b0be9a882540f1922577abba4c872ager@chromium.org  } else {
10425c838251403b0be9a882540f1922577abba4c872ager@chromium.org    if (L->is_linked()) {
10437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      target_pos = L->pos();  // L's link.
10447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      int32_t imm18 = target_pos - at_offset;
10457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      ASSERT((imm18 & 3) == 0);
10467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      int32_t imm16 = imm18 >> 2;
10477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      ASSERT(is_int16(imm16));
10487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      instr_at_put(at_offset, (imm16 & kImm16Mask));
10495c838251403b0be9a882540f1922577abba4c872ager@chromium.org    } else {
10505c838251403b0be9a882540f1922577abba4c872ager@chromium.org      target_pos = kEndOfChain;
10517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      instr_at_put(at_offset, 0);
10523cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      if (!trampoline_emitted_) {
10533cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        unbound_labels_count_++;
10543cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        next_buffer_check_ -= kTrampolineSlotsSize;
10553cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      }
10565c838251403b0be9a882540f1922577abba4c872ager@chromium.org    }
10575c838251403b0be9a882540f1922577abba4c872ager@chromium.org    L->link_to(at_offset);
10585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
10595c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
10605c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10615c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10625c838251403b0be9a882540f1922577abba4c872ager@chromium.org//------- Branch and jump instructions --------
10635c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10645c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::b(int16_t offset) {
10655c838251403b0be9a882540f1922577abba4c872ager@chromium.org  beq(zero_reg, zero_reg, offset);
10665c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
10675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10685c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10695c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bal(int16_t offset) {
10707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  positions_recorder()->WriteRecordedPositions();
10715c838251403b0be9a882540f1922577abba4c872ager@chromium.org  bgezal(zero_reg, offset);
10725c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
10735c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10745c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10755c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::beq(Register rs, Register rt, int16_t offset) {
10767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
10775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(BEQ, rs, rt, offset);
10787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
10795c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
10805c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10815c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10825c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bgez(Register rs, int16_t offset) {
10837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
10845c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(REGIMM, rs, BGEZ, offset);
10857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
10865c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
10875c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10885c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10895c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bgezal(Register rs, int16_t offset) {
10907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
10917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  positions_recorder()->WriteRecordedPositions();
10925c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
10937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
10945c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
10955c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10965c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10975c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bgtz(Register rs, int16_t offset) {
10987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
10995c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(BGTZ, rs, zero_reg, offset);
11007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
11015c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
11025c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11035c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11045c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::blez(Register rs, int16_t offset) {
11057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
11065c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(BLEZ, rs, zero_reg, offset);
11077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
11085c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
11095c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11105c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11115c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bltz(Register rs, int16_t offset) {
11127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
11135c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(REGIMM, rs, BLTZ, offset);
11147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
11155c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
11165c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11175c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11185c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bltzal(Register rs, int16_t offset) {
11197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
11207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  positions_recorder()->WriteRecordedPositions();
11215c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
11227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
11235c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
11245c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11255c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11265c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bne(Register rs, Register rt, int16_t offset) {
11277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
11285c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(BNE, rs, rt, offset);
11297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
11305c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
11315c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11325c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11335c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::j(int32_t target) {
113434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org#if DEBUG
113534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Get pc of delay slot.
113634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
113759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
113859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                  (kImm26Bits + kImmFieldShift)) == 0;
113934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  ASSERT(in_range && ((target & 3) == 0));
114034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org#endif
11415c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrJump(J, target >> 2);
11425c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
11435c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11445c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11455c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::jr(Register rs) {
11467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
11477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (rs.is(ra)) {
11487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    positions_recorder()->WriteRecordedPositions();
11497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
11505c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
11517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
11525c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
11535c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11545c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11555c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::jal(int32_t target) {
115634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org#ifdef DEBUG
115734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Get pc of delay slot.
115834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
115959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
116059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                  (kImm26Bits + kImmFieldShift)) == 0;
116134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  ASSERT(in_range && ((target & 3) == 0));
116234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org#endif
11637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  positions_recorder()->WriteRecordedPositions();
11645c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrJump(JAL, target >> 2);
11655c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
11665c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11685c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::jalr(Register rs, Register rd) {
11697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolScope block_trampoline_pool(this);
11707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  positions_recorder()->WriteRecordedPositions();
11715c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
11727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolFor(1);  // For associated delay slot.
11735c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
11745c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11755c838251403b0be9a882540f1922577abba4c872ager@chromium.org
117634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgvoid Assembler::j_or_jr(int32_t target, Register rs) {
117734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Get pc of delay slot.
117834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
117959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
118059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                  (kImm26Bits + kImmFieldShift)) == 0;
118134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (in_range) {
118234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      j(target);
118334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  } else {
118434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      jr(t9);
118534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
118634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org}
118734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
118834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
118934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgvoid Assembler::jal_or_jalr(int32_t target, Register rs) {
119034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Get pc of delay slot.
119134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
119259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  bool in_range = (ipc ^ static_cast<uint32_t>(target) >>
119359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                  (kImm26Bits+kImmFieldShift)) == 0;
119434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (in_range) {
119534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      jal(target);
119634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  } else {
119734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      jalr(t9);
119834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
119934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org}
120034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
120134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
12025c838251403b0be9a882540f1922577abba4c872ager@chromium.org//-------Data-processing-instructions---------
12035c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12045c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Arithmetic.
12055c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12065c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::addu(Register rd, Register rs, Register rt) {
12075c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
12085c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12095c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12105c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12115c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::addiu(Register rd, Register rs, int32_t j) {
12125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(ADDIU, rs, rd, j);
12135c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12145c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12155c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12165c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::subu(Register rd, Register rs, Register rt) {
12175c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
12185c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12195c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12205c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12215c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::mul(Register rd, Register rs, Register rt) {
12225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
12235c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12245c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12255c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12265c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::mult(Register rs, Register rt) {
12275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
12285c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12295c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12305c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12315c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::multu(Register rs, Register rt) {
12325c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
12335c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12345c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12355c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12365c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::div(Register rs, Register rt) {
12375c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
12385c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12395c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12405c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12415c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::divu(Register rs, Register rt) {
12425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
12435c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12445c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12455c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12465c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Logical.
12475c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12485c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::and_(Register rd, Register rs, Register rt) {
12495c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
12505c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12515c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12525c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12535c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::andi(Register rt, Register rs, int32_t j) {
125478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  ASSERT(is_uint16(j));
12555c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(ANDI, rs, rt, j);
12565c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12575c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12585c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12595c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::or_(Register rd, Register rs, Register rt) {
12605c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
12615c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12625c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12635c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12645c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::ori(Register rt, Register rs, int32_t j) {
126578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  ASSERT(is_uint16(j));
12665c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(ORI, rs, rt, j);
12675c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12685c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12695c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12705c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::xor_(Register rd, Register rs, Register rt) {
12715c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
12725c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12735c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12745c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12755c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::xori(Register rt, Register rs, int32_t j) {
127678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  ASSERT(is_uint16(j));
12775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(XORI, rs, rt, j);
12785c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12795c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12805c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12815c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::nor(Register rd, Register rs, Register rt) {
12825c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
12835c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12845c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12855c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12865c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Shifts.
12877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::sll(Register rd,
12887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                    Register rt,
12897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                    uint16_t sa,
12907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                    bool coming_from_nop) {
12917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Don't allow nop instructions in the form sll zero_reg, zero_reg to be
12927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // generated using the sll instruction. They must be generated using
12937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // nop(int/NopMarkerTypes) or MarkCode(int/NopMarkerTypes) pseudo
12947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // instructions.
12957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(coming_from_nop || !(rd.is(zero_reg) && rt.is(zero_reg)));
12965c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SLL);
12975c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12985c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12995c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13005c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::sllv(Register rd, Register rt, Register rs) {
13015c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
13025c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
13035c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13045c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13055c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::srl(Register rd, Register rt, uint16_t sa) {
13065c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRL);
13075c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
13085c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13095c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13105c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::srlv(Register rd, Register rt, Register rs) {
13115c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
13125c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
13135c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13145c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13155c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::sra(Register rd, Register rt, uint16_t sa) {
13165c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRA);
13175c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
13185c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13195c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13205c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::srav(Register rd, Register rt, Register rs) {
13215c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
13225c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
13235c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13245c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::rotr(Register rd, Register rt, uint16_t sa) {
13267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Should be called via MacroAssembler::Ror.
13277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(rd.is_valid() && rt.is_valid() && is_uint5(sa));
13283233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org  ASSERT(kArchVariant == kMips32r2);
13297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
13307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      | (rd.code() << kRdShift) | (sa << kSaShift) | SRL;
13317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  emit(instr);
13327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
13337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::rotrv(Register rd, Register rt, Register rs) {
13367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Should be called via MacroAssembler::Ror.
13377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(rd.is_valid() && rt.is_valid() && rs.is_valid() );
13383233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org  ASSERT(kArchVariant == kMips32r2);
13397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
13407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org     | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV;
13417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  emit(instr);
13427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
13437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13455c838251403b0be9a882540f1922577abba4c872ager@chromium.org//------------Memory-instructions-------------
13465c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Helper for base-reg + offset, when offset is larger than int16.
13487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) {
13497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(!src.rm().is(at));
135009b3454f8cdcc19655f7e1d6362f8f0216941235palfia@homejinni.com  lui(at, (src.offset_ >> kLuiShift) & kImm16Mask);
13517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ori(at, at, src.offset_ & kImm16Mask);  // Load 32-bit offset.
13527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  addu(at, at, src.rm());  // Add base register.
13537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
13547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13565c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::lb(Register rd, const MemOperand& rs) {
13577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (is_int16(rs.offset_)) {
13587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
13597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {  // Offset > 16 bits, use multiple instructions to load.
13607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    LoadRegPlusOffsetToAt(rs);
13617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(LB, at, rd, 0);  // Equiv to lb(rd, MemOperand(at, 0));
13627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
13635c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
13645c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13655c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13665c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::lbu(Register rd, const MemOperand& rs) {
13677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (is_int16(rs.offset_)) {
13687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
13697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {  // Offset > 16 bits, use multiple instructions to load.
13707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    LoadRegPlusOffsetToAt(rs);
13717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(LBU, at, rd, 0);  // Equiv to lbu(rd, MemOperand(at, 0));
13727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
13737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
13747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::lh(Register rd, const MemOperand& rs) {
13777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (is_int16(rs.offset_)) {
13787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
13797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {  // Offset > 16 bits, use multiple instructions to load.
13807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    LoadRegPlusOffsetToAt(rs);
13817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(LH, at, rd, 0);  // Equiv to lh(rd, MemOperand(at, 0));
13827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
13837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
13847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::lhu(Register rd, const MemOperand& rs) {
13877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (is_int16(rs.offset_)) {
13887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
13897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {  // Offset > 16 bits, use multiple instructions to load.
13907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    LoadRegPlusOffsetToAt(rs);
13917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(LHU, at, rd, 0);  // Equiv to lhu(rd, MemOperand(at, 0));
13927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
13935c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
13945c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13955c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13965c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::lw(Register rd, const MemOperand& rs) {
13977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (is_int16(rs.offset_)) {
13987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
13997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {  // Offset > 16 bits, use multiple instructions to load.
14007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    LoadRegPlusOffsetToAt(rs);
14017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(LW, at, rd, 0);  // Equiv to lw(rd, MemOperand(at, 0));
14027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
14037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
14047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::lwl(Register rd, const MemOperand& rs) {
14077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
14087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
14097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::lwr(Register rd, const MemOperand& rs) {
14127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
14135c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
14145c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14155c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14165c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::sb(Register rd, const MemOperand& rs) {
14177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (is_int16(rs.offset_)) {
14187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
14197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {  // Offset > 16 bits, use multiple instructions to store.
14207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    LoadRegPlusOffsetToAt(rs);
14217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(SB, at, rd, 0);  // Equiv to sb(rd, MemOperand(at, 0));
14227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
14237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
14247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::sh(Register rd, const MemOperand& rs) {
14277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (is_int16(rs.offset_)) {
14287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
14297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {  // Offset > 16 bits, use multiple instructions to store.
14307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    LoadRegPlusOffsetToAt(rs);
14317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(SH, at, rd, 0);  // Equiv to sh(rd, MemOperand(at, 0));
14327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
14335c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
14345c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14355c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14365c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::sw(Register rd, const MemOperand& rs) {
14377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (is_int16(rs.offset_)) {
14387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
14397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {  // Offset > 16 bits, use multiple instructions to store.
14407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    LoadRegPlusOffsetToAt(rs);
14417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenInstrImmediate(SW, at, rd, 0);  // Equiv to sw(rd, MemOperand(at, 0));
14427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
14437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
14447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::swl(Register rd, const MemOperand& rs) {
14477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
14487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
14497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::swr(Register rd, const MemOperand& rs) {
14527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
14535c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
14545c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14555c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14565c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::lui(Register rd, int32_t j) {
145778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  ASSERT(is_uint16(j));
14585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(LUI, zero_reg, rd, j);
14595c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
14605c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14615c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14625c838251403b0be9a882540f1922577abba4c872ager@chromium.org//-------------Misc-instructions--------------
14635c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14645c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Break / Trap instructions.
1465c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.orgvoid Assembler::break_(uint32_t code, bool break_as_stop) {
14665c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT((code & ~0xfffff) == 0);
1467c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  // We need to invalidate breaks that could be stops as well because the
1468c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  // simulator expects a char pointer after the stop instruction.
1469c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  // See constants-mips.h for explanation.
1470c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  ASSERT((break_as_stop &&
1471c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org          code <= kMaxStopCode &&
1472c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org          code > kMaxWatchpointCode) ||
1473c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org         (!break_as_stop &&
1474c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org          (code > kMaxStopCode ||
1475c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org           code <= kMaxWatchpointCode)));
14765c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr break_instr = SPECIAL | BREAK | (code << 6);
14775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(break_instr);
14785c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
14795c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14805c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1481c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.orgvoid Assembler::stop(const char* msg, uint32_t code) {
1482c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  ASSERT(code > kMaxWatchpointCode);
1483c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  ASSERT(code <= kMaxStopCode);
148493a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_HOST_ARCH_MIPS
1485c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  break_(0x54321);
1486c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org#else  // V8_HOST_ARCH_MIPS
1487c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  BlockTrampolinePoolFor(2);
1488c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  // The Simulator will handle the stop instruction and get the message address.
1489c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  // On MIPS stop() is just a special kind of break_().
1490c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  break_(code, true);
1491c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  emit(reinterpret_cast<Instr>(msg));
1492c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org#endif
1493c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org}
1494c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org
1495c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org
14965c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::tge(Register rs, Register rt, uint16_t code) {
14975c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(is_uint10(code));
14985c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = SPECIAL | TGE | rs.code() << kRsShift
14995c838251403b0be9a882540f1922577abba4c872ager@chromium.org      | rt.code() << kRtShift | code << 6;
15005c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
15015c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15025c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15035c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15045c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::tgeu(Register rs, Register rt, uint16_t code) {
15055c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(is_uint10(code));
15065c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = SPECIAL | TGEU | rs.code() << kRsShift
15075c838251403b0be9a882540f1922577abba4c872ager@chromium.org      | rt.code() << kRtShift | code << 6;
15085c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
15095c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15105c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15115c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15125c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::tlt(Register rs, Register rt, uint16_t code) {
15135c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(is_uint10(code));
15145c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr =
15155c838251403b0be9a882540f1922577abba4c872ager@chromium.org      SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
15165c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
15175c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15185c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15195c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15205c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::tltu(Register rs, Register rt, uint16_t code) {
15215c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(is_uint10(code));
15227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Instr instr =
15237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      SPECIAL | TLTU | rs.code() << kRsShift
15245c838251403b0be9a882540f1922577abba4c872ager@chromium.org      | rt.code() << kRtShift | code << 6;
15255c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
15265c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15275c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15285c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15295c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::teq(Register rs, Register rt, uint16_t code) {
15305c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(is_uint10(code));
15315c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr =
15325c838251403b0be9a882540f1922577abba4c872ager@chromium.org      SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
15335c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
15345c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15355c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15365c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15375c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::tne(Register rs, Register rt, uint16_t code) {
15385c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(is_uint10(code));
15395c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr =
15405c838251403b0be9a882540f1922577abba4c872ager@chromium.org      SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
15415c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
15425c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15435c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15445c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15455c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Move from HI/LO register.
15465c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15475c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::mfhi(Register rd) {
15485c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
15495c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15505c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15515c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15525c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::mflo(Register rd) {
15535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
15545c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15555c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15565c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15575c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Set on less than instructions.
15585c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::slt(Register rd, Register rs, Register rt) {
15595c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
15605c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15615c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15625c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15635c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::sltu(Register rd, Register rs, Register rt) {
15645c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
15655c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15665c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15685c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::slti(Register rt, Register rs, int32_t j) {
15695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(SLTI, rs, rt, j);
15705c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15715c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15725c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15735c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::sltiu(Register rt, Register rs, int32_t j) {
15745c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(SLTIU, rs, rt, j);
15755c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15765c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15775c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Conditional move.
15797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::movz(Register rd, Register rs, Register rt) {
15807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ);
15817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
15827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
15837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
15847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::movn(Register rd, Register rs, Register rt) {
15857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
15867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
15877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
15887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
15897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::movt(Register rd, Register rs, uint16_t cc) {
15907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Register rt;
159183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  rt.code_ = (cc & 0x0007) << 2 | 1;
15927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
15937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
15947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
15957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
15967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::movf(Register rd, Register rs, uint16_t cc) {
15977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Register rt;
159883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  rt.code_ = (cc & 0x0007) << 2 | 0;
15997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
16007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
16017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Bit twiddling.
16047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::clz(Register rd, Register rs) {
16057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Clz instr requires same GPR number in 'rd' and 'rt' fields.
16067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
16077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
16087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
16117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Should be called via MacroAssembler::Ins.
16127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Ins instr has 'rt' field as dest, and two uint5: msb, lsb.
16133233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org  ASSERT(kArchVariant == kMips32r2);
16147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS);
16157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
16167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
16197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Should be called via MacroAssembler::Ext.
16207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Ext instr has 'rt' field as dest, and two uint5: msb, lsb.
16213233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org  ASSERT(kArchVariant == kMips32r2);
16227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT);
16237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
16247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16265c838251403b0be9a882540f1922577abba4c872ager@chromium.org//--------Coprocessor-instructions----------------
16275c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16285c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Load, store, move.
16295c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::lwc1(FPURegister fd, const MemOperand& src) {
16305c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
16315c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
16325c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16335c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16345c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::ldc1(FPURegister fd, const MemOperand& src) {
16357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
16367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // load to two 32-bit loads.
16377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
16387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  FPURegister nextfpreg;
16397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  nextfpreg.setcode(fd.code() + 1);
16407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ + 4);
16415c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
16425c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16435c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16445c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::swc1(FPURegister fd, const MemOperand& src) {
16455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
16465c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
16475c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16485c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16495c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::sdc1(FPURegister fd, const MemOperand& src) {
16507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
16517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // store to two 32-bit stores.
16527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
16537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  FPURegister nextfpreg;
16547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  nextfpreg.setcode(fd.code() + 1);
16557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ + 4);
16565c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
16575c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16585c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::mtc1(Register rt, FPURegister fs) {
16605c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, MTC1, rt, fs, f0);
16615c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
16625c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16635c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::mfc1(Register rt, FPURegister fs) {
16657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, MFC1, rt, fs, f0);
16665c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
16675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16685c838251403b0be9a882540f1922577abba4c872ager@chromium.org
16697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::ctc1(Register rt, FPUControlRegister fs) {
16707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, CTC1, rt, fs);
16717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
16727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::cfc1(Register rt, FPUControlRegister fs) {
16757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, CFC1, rt, fs);
16767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
16777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1678e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
167934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgvoid Assembler::DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
168034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  uint64_t i;
1681e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  OS::MemCopy(&i, &d, 8);
168234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
168334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  *lo = i & 0xffffffff;
168434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  *hi = i >> 32;
168534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org}
16867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1687e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
16887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Arithmetic.
16897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
16917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, ft, fs, fd, ADD_D);
16927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
16937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) {
16967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, ft, fs, fd, SUB_D);
16977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
16987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
16997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
17017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
17027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
170559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.orgvoid Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
170659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    FPURegister ft) {
170759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D);
170859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org}
170959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
171059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
17117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) {
17127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, ft, fs, fd, DIV_D);
17137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::abs_d(FPURegister fd, FPURegister fs) {
17177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, ABS_D);
17185c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
17195c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17205c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::mov_d(FPURegister fd, FPURegister fs) {
17227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, MOV_D);
17237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::neg_d(FPURegister fd, FPURegister fs) {
17277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
17287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::sqrt_d(FPURegister fd, FPURegister fs) {
17327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D);
17335c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
17345c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17355c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17365c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Conversions.
17375c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17385c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
17395c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
17405c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
17415c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17425c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17435c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
17445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
17455c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
17465c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17475c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::trunc_w_s(FPURegister fd, FPURegister fs) {
17497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S);
17507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::trunc_w_d(FPURegister fd, FPURegister fs) {
17547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D);
17557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::round_w_s(FPURegister fd, FPURegister fs) {
17597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S);
17607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::round_w_d(FPURegister fd, FPURegister fs) {
17647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D);
17657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::floor_w_s(FPURegister fd, FPURegister fs) {
17697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S);
17707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::floor_w_d(FPURegister fd, FPURegister fs) {
17747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D);
17757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::ceil_w_s(FPURegister fd, FPURegister fs) {
17797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S);
17807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::ceil_w_d(FPURegister fd, FPURegister fs) {
17847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D);
17857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
17867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
17885c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
17893233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org  ASSERT(kArchVariant == kMips32r2);
17905c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
17915c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
17925c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17935c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17945c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
17953233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org  ASSERT(kArchVariant == kMips32r2);
17965c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
17975c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
17985c838251403b0be9a882540f1922577abba4c872ager@chromium.org
17995c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::trunc_l_s(FPURegister fd, FPURegister fs) {
18013233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org  ASSERT(kArchVariant == kMips32r2);
18027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S);
18037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
18047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::trunc_l_d(FPURegister fd, FPURegister fs) {
18073233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org  ASSERT(kArchVariant == kMips32r2);
18087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D);
18097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
18107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::round_l_s(FPURegister fd, FPURegister fs) {
18137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S);
18147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
18157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::round_l_d(FPURegister fd, FPURegister fs) {
18187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D);
18197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
18207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::floor_l_s(FPURegister fd, FPURegister fs) {
18237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S);
18247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
18257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::floor_l_d(FPURegister fd, FPURegister fs) {
18287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D);
18297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
18307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::ceil_l_s(FPURegister fd, FPURegister fs) {
18337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S);
18347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
18357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
18387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D);
18397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
18407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18425c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
18435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
18445c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
18455c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18465c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18475c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
18483233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org  ASSERT(kArchVariant == kMips32r2);
18495c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
18505c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
18515c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18525c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18535c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
18545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
18555c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
18565c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18575c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18585c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
18595c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
18605c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
18615c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18625c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18635c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
18643233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org  ASSERT(kArchVariant == kMips32r2);
18655c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
18665c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
18675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18685c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18695c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
18705c838251403b0be9a882540f1922577abba4c872ager@chromium.org  GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
18715c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
18725c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18735c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18745c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Conditions.
18755c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::c(FPUCondition cond, SecondaryField fmt,
18767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    FPURegister fs, FPURegister ft, uint16_t cc) {
18775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(is_uint3(cc));
18785c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT((fmt & ~(31 << kRsShift)) == 0);
18795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
18805c838251403b0be9a882540f1922577abba4c872ager@chromium.org      | cc << 8 | 3 << 4 | cond;
18815c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
18825c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
18835c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18845c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::fcmp(FPURegister src1, const double src2,
18867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      FPUCondition cond) {
18877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  ASSERT(src2 == 0.0);
18887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  mtc1(zero_reg, f14);
18897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  cvt_d_w(f14, f14);
18907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  c(cond, D, src1, f14, 0);
18917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
18927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
18945c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bc1f(int16_t offset, uint16_t cc) {
18955c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(is_uint3(cc));
18965c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
18975c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
18985c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
18995c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19005c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19015c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::bc1t(int16_t offset, uint16_t cc) {
19025c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(is_uint3(cc));
19035c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
19045c838251403b0be9a882540f1922577abba4c872ager@chromium.org  emit(instr);
19055c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
19065c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19075c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19085c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Debugging.
19095c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::RecordJSReturn() {
19107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  positions_recorder()->WriteRecordedPositions();
19115c838251403b0be9a882540f1922577abba4c872ager@chromium.org  CheckBuffer();
19125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  RecordRelocInfo(RelocInfo::JS_RETURN);
19135c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
19145c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19155c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::RecordDebugBreakSlot() {
19177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  positions_recorder()->WriteRecordedPositions();
19187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  CheckBuffer();
19197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
19205c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
19215c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19225c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::RecordComment(const char* msg) {
19247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (FLAG_code_comments) {
19255c838251403b0be9a882540f1922577abba4c872ager@chromium.org    CheckBuffer();
19267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
19275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
19285c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
19295c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19305c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19313cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orgint Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) {
19323cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  Instr instr = instr_at(pc);
19333cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  ASSERT(IsJ(instr) || IsLui(instr));
19343cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  if (IsLui(instr)) {
19353cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize);
19363cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize);
19373cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT(IsOri(instr_ori));
19383cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
19393cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
19403cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    if (imm == kEndOfJumpChain) {
19413cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      return 0;  // Number of instructions patched.
19423cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
19433cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    imm += pc_delta;
19443cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT((imm & 3) == 0);
19453cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
19463cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_lui &= ~kImm16Mask;
19473cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_ori &= ~kImm16Mask;
19483cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
19493cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_at_put(pc + 0 * Assembler::kInstrSize,
19503cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org                 instr_lui | ((imm >> kLuiShift) & kImm16Mask));
19513cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_at_put(pc + 1 * Assembler::kInstrSize,
19523cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org                 instr_ori | (imm & kImm16Mask));
19533cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    return 2;  // Number of instructions patched.
19543cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  } else {
19553cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
195659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    if (static_cast<int32_t>(imm28) == kEndOfJumpChain) {
19573cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      return 0;  // Number of instructions patched.
19583cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
19593cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    imm28 += pc_delta;
19603cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    imm28 &= kImm28Mask;
19613cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT((imm28 & 3) == 0);
19623cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
19633cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr &= ~kImm26Mask;
19643cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    uint32_t imm26 = imm28 >> 2;
19653cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT(is_uint26(imm26));
19663cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
19673cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    instr_at_put(pc, instr | (imm26 & kImm26Mask));
19683cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    return 1;  // Number of instructions patched.
19693cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
19703cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org}
19713cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
19723cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
19735c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::GrowBuffer() {
19745c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if (!own_buffer_) FATAL("external code buffer is too small");
19755c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19765c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Compute new buffer size.
19777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  CodeDesc desc;  // The new buffer.
19785c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if (buffer_size_ < 4*KB) {
19795c838251403b0be9a882540f1922577abba4c872ager@chromium.org    desc.buffer_size = 4*KB;
19805c838251403b0be9a882540f1922577abba4c872ager@chromium.org  } else if (buffer_size_ < 1*MB) {
19815c838251403b0be9a882540f1922577abba4c872ager@chromium.org    desc.buffer_size = 2*buffer_size_;
19825c838251403b0be9a882540f1922577abba4c872ager@chromium.org  } else {
19835c838251403b0be9a882540f1922577abba4c872ager@chromium.org    desc.buffer_size = buffer_size_ + 1*MB;
19845c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
19857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  CHECK_GT(desc.buffer_size, 0);  // No overflow.
19865c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1987f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up new buffer.
19885c838251403b0be9a882540f1922577abba4c872ager@chromium.org  desc.buffer = NewArray<byte>(desc.buffer_size);
19895c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19905c838251403b0be9a882540f1922577abba4c872ager@chromium.org  desc.instr_size = pc_offset();
19915c838251403b0be9a882540f1922577abba4c872ager@chromium.org  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
19925c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19935c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Copy the data.
19945c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int pc_delta = desc.buffer - buffer_;
19955c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
1996e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  OS::MemMove(desc.buffer, buffer_, desc.instr_size);
1997e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  OS::MemMove(reloc_info_writer.pos() + rc_delta,
1998e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org              reloc_info_writer.pos(), desc.reloc_size);
19995c838251403b0be9a882540f1922577abba4c872ager@chromium.org
20005c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Switch buffers.
20015c838251403b0be9a882540f1922577abba4c872ager@chromium.org  DeleteArray(buffer_);
20025c838251403b0be9a882540f1922577abba4c872ager@chromium.org  buffer_ = desc.buffer;
20035c838251403b0be9a882540f1922577abba4c872ager@chromium.org  buffer_size_ = desc.buffer_size;
20045c838251403b0be9a882540f1922577abba4c872ager@chromium.org  pc_ += pc_delta;
20055c838251403b0be9a882540f1922577abba4c872ager@chromium.org  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
20065c838251403b0be9a882540f1922577abba4c872ager@chromium.org                               reloc_info_writer.last_pc() + pc_delta);
20075c838251403b0be9a882540f1922577abba4c872ager@chromium.org
20083cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Relocate runtime entries.
20093cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  for (RelocIterator it(desc); !it.done(); it.next()) {
20103cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    RelocInfo::Mode rmode = it.rinfo()->rmode();
20113cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    if (rmode == RelocInfo::INTERNAL_REFERENCE) {
20123cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      byte* p = reinterpret_cast<byte*>(it.rinfo()->pc());
20133cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      RelocateInternalReference(p, pc_delta);
20143cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
20153cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
20165c838251403b0be9a882540f1922577abba4c872ager@chromium.org
20175c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ASSERT(!overflow());
20185c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
20195c838251403b0be9a882540f1922577abba4c872ager@chromium.org
20205c838251403b0be9a882540f1922577abba4c872ager@chromium.org
20217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::db(uint8_t data) {
20227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  CheckBuffer();
20237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  *reinterpret_cast<uint8_t*>(pc_) = data;
20247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  pc_ += sizeof(uint8_t);
20257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
20267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
20277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
20287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::dd(uint32_t data) {
20297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  CheckBuffer();
20307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  *reinterpret_cast<uint32_t*>(pc_) = data;
20317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  pc_ += sizeof(uint32_t);
2032057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org}
2033057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org
2034057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org
2035057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.orgvoid Assembler::emit_code_stub_address(Code* stub) {
2036057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  CheckBuffer();
2037057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  *reinterpret_cast<uint32_t*>(pc_) =
2038057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org      reinterpret_cast<uint32_t>(stub->instruction_start());
2039057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  pc_ += sizeof(uint32_t);
20407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
20417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
20427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
20435c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2044b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  // We do not try to reuse pool constants.
2045b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  RelocInfo rinfo(pc_, rmode, data, NULL);
20467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
20475c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // Adjust code for new modes.
20487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
20497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org           || RelocInfo::IsJSReturn(rmode)
20505c838251403b0be9a882540f1922577abba4c872ager@chromium.org           || RelocInfo::IsComment(rmode)
20515c838251403b0be9a882540f1922577abba4c872ager@chromium.org           || RelocInfo::IsPosition(rmode));
20525c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // These modes do not need an entry in the constant pool.
20535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
20544cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  if (!RelocInfo::IsNone(rinfo.rmode())) {
20555c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // Don't record external references unless the heap will be serialized.
205634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
205734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org#ifdef DEBUG
205834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      if (!Serializer::enabled()) {
205934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org        Serializer::TooLateToEnableNow();
206034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      }
206134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org#endif
206234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      if (!Serializer::enabled() && !emit_debug_code()) {
206334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org        return;
206434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      }
20655c838251403b0be9a882540f1922577abba4c872ager@chromium.org    }
20667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(buffer_space() >= kMaxRelocSize);  // Too late to grow buffer here.
206783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
2068471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org      RelocInfo reloc_info_with_ast_id(pc_,
2069471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                                       rmode,
2070471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                                       RecordedAstId().ToInt(),
2071471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                                       NULL);
2072717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org      ClearRecordedAstId();
207383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      reloc_info_writer.Write(&reloc_info_with_ast_id);
207483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    } else {
207583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      reloc_info_writer.Write(&rinfo);
207683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    }
20775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
20785c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
20795c838251403b0be9a882540f1922577abba4c872ager@chromium.org
20805c838251403b0be9a882540f1922577abba4c872ager@chromium.org
20817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Assembler::BlockTrampolinePoolFor(int instructions) {
20827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
20837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
20847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
20857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
20863cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orgvoid Assembler::CheckTrampolinePool() {
20877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Some small sequences of instructions must not be broken up by the
20887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // insertion of a trampoline pool; such sequences are protected by setting
20897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
20907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // which are both checked here. Also, recursive calls to CheckTrampolinePool
20917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // are blocked by trampoline_pool_blocked_nesting_.
20927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if ((trampoline_pool_blocked_nesting_ > 0) ||
20937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      (pc_offset() < no_trampoline_pool_before_)) {
20947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    // Emission is currently blocked; make sure we try again as soon as
20957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    // possible.
20967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    if (trampoline_pool_blocked_nesting_ > 0) {
20977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      next_buffer_check_ = pc_offset() + kInstrSize;
20987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    } else {
20997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      next_buffer_check_ = no_trampoline_pool_before_;
21007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
21017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return;
21027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
21037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
21043cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  ASSERT(!trampoline_emitted_);
21053cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  ASSERT(unbound_labels_count_ >= 0);
21063cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  if (unbound_labels_count_ > 0) {
21073cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    // First we emit jump (2 instructions), then we emit trampoline pool.
21083cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    { BlockTrampolinePoolScope block_trampoline_pool(this);
21093cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      Label after_pool;
21107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      b(&after_pool);
21117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      nop();
21123cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
21133cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      int pool_start = pc_offset();
21143cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      for (int i = 0; i < unbound_labels_count_; i++) {
21153cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        uint32_t imm32;
21163cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        imm32 = jump_address(&after_pool);
21173cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        { BlockGrowBufferScope block_buf_growth(this);
21183cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org          // Buffer growth (and relocation) must be blocked for internal
21193cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org          // references until associated instructions are emitted and available
21203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org          // to be patched.
21213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org          RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
21223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org          lui(at, (imm32 & kHiMask) >> kLuiShift);
21233cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org          ori(at, at, (imm32 & kImm16Mask));
21243cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        }
21253cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        jr(at);
21263cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        nop();
21273cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      }
21283cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      bind(&after_pool);
21293cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      trampoline_ = Trampoline(pool_start, unbound_labels_count_);
21303cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
21313cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      trampoline_emitted_ = true;
21323cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      // As we are only going to emit trampoline once, we need to prevent any
21333cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      // further emission.
21343cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      next_buffer_check_ = kMaxInt;
21357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
21363cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  } else {
21373cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    // Number of branches to unbound label at this point is zero, so we can
21383cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    // move next buffer check to maximum.
21393cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    next_buffer_check_ = pc_offset() +
21403cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        kMaxBranchOffset - kTrampolineSlotsSize * 16;
21417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
21427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return;
21437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
21447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
21457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
21465c838251403b0be9a882540f1922577abba4c872ager@chromium.orgAddress Assembler::target_address_at(Address pc) {
21475c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr1 = instr_at(pc);
21485c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr2 = instr_at(pc + kInstrSize);
214983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Interpret 2 instructions generated by li: lui/ori
215083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) {
215183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    // Assemble the 32 bit value.
21525c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return reinterpret_cast<Address>(
215383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        (GetImmediate16(instr1) << 16) | GetImmediate16(instr2));
21545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
21555c838251403b0be9a882540f1922577abba4c872ager@chromium.org
215683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // We should never get here, force a bad address if we do.
21575c838251403b0be9a882540f1922577abba4c872ager@chromium.org  UNREACHABLE();
21585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  return (Address)0x0;
21595c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
21605c838251403b0be9a882540f1922577abba4c872ager@chromium.org
21615c838251403b0be9a882540f1922577abba4c872ager@chromium.org
216288d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org// MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32
216388d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org// qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap
216488d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org// snapshot generated on ia32, the resulting MIPS sNaN must be quieted.
216588d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org// OS::nan_value() returns a qNaN.
216628faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.orgvoid Assembler::QuietNaN(HeapObject* object) {
216788d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org  HeapNumber::cast(object)->set_value(OS::nan_value());
216828faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org}
216928faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org
217028faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org
217134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// On Mips, a target address is stored in a lui/ori instruction pair, each
217234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// of which load 16 bits of the 32-bit address to a register.
217334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// Patching the address must replace both instr, and flush the i-cache.
217434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org//
217534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// There is an optimization below, which emits a nop when the address
217634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// fits in just 16 bits. This is unlikely to help, and should be benchmarked,
217734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// and possibly removed.
21785c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Assembler::set_target_address_at(Address pc, Address target) {
21795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr2 = instr_at(pc + kInstrSize);
218034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  uint32_t rt_code = GetRtField(instr2);
218134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  uint32_t* p = reinterpret_cast<uint32_t*>(pc);
218234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  uint32_t itarget = reinterpret_cast<uint32_t>(target);
218334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
21845c838251403b0be9a882540f1922577abba4c872ager@chromium.org#ifdef DEBUG
218534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Check we have the result from a li macro-instruction, using instr pair.
21865c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr1 = instr_at(pc);
218783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI));
21885c838251403b0be9a882540f1922577abba4c872ager@chromium.org#endif
21895c838251403b0be9a882540f1922577abba4c872ager@chromium.org
219034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Must use 2 instructions to insure patchable code => just use lui and ori.
219134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // lui rt, upper-16.
219234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // ori rt rt, lower-16.
219383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
219483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask);
21955c838251403b0be9a882540f1922577abba4c872ager@chromium.org
219634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // The following code is an optimization for the common case of Call()
219734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // or Jump() which is load to register, and jump through register:
219834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  //     li(t9, address); jalr(t9)    (or jr(t9)).
219934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // If the destination address is in the same 256 MB page as the call, it
220034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // is faster to do a direct jal, or j, rather than jump thru register, since
220134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // that lets the cpu pipeline prefetch the target address. However each
220234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // time the address above is patched, we have to patch the direct jal/j
220334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // instruction, as well as possibly revert to jalr/jr if we now cross a
220434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // 256 MB page. Note that with the jal/j instructions, we do not need to
220534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // load the register, but that code is left, since it makes it easy to
220634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // revert this process. A further optimization could try replacing the
220734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // li sequence with nops.
220834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // This optimization can only be applied if the rt-code from instr2 is the
220934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // register used for the jalr/jr. Finally, we have to skip 'jr ra', which is
221034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // mips return. Occasionally this lands after an li().
221134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
221234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  Instr instr3 = instr_at(pc + 2 * kInstrSize);
221334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  uint32_t ipc = reinterpret_cast<uint32_t>(pc + 3 * kInstrSize);
221432cb9b2c195baa85d4c04f4c7b22b9aa04e97d3fverwaest@chromium.org  bool in_range = ((ipc ^ itarget) >> (kImm26Bits + kImmFieldShift)) == 0;
221559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  uint32_t target_field =
2216837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org      static_cast<uint32_t>(itarget & kJumpAddrMask) >> kImmFieldShift;
221734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  bool patched_jump = false;
221834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
221934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org#ifndef ALLOW_JAL_IN_BOUNDARY_REGION
222034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // This is a workaround to the 24k core E156 bug (affect some 34k cores also).
222134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Since the excluded space is only 64KB out of 256MB (0.02 %), we will just
222234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // apply this workaround for all cores so we don't have to identify the core.
222334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (in_range) {
222434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    // The 24k core E156 bug has some very specific requirements, we only check
222534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    // the most simple one: if the address of the delay slot instruction is in
222634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    // the first or last 32 KB of the 256 MB segment.
222734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    uint32_t segment_mask = ((256 * MB) - 1) ^ ((32 * KB) - 1);
222834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    uint32_t ipc_segment_addr = ipc & segment_mask;
222934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    if (ipc_segment_addr == 0 || ipc_segment_addr == segment_mask)
223034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      in_range = false;
223134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
223234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org#endif
223334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
223434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (IsJalr(instr3)) {
223534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    // Try to convert JALR to JAL.
223634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    if (in_range && GetRt(instr2) == GetRs(instr3)) {
223734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      *(p+2) = JAL | target_field;
223834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      patched_jump = true;
223934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    }
224034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  } else if (IsJr(instr3)) {
224134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    // Try to convert JR to J, skip returns (jr ra).
224234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    bool is_ret = static_cast<int>(GetRs(instr3)) == ra.code();
224334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    if (in_range && !is_ret && GetRt(instr2) == GetRs(instr3)) {
224434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      *(p+2) = J | target_field;
224534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      patched_jump = true;
224634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    }
224734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  } else if (IsJal(instr3)) {
224834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    if (in_range) {
224934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      // We are patching an already converted JAL.
225034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      *(p+2) = JAL | target_field;
225134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    } else {
225234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      // Patch JAL, but out of range, revert to JALR.
225334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      // JALR rs reg is the rt reg specified in the ORI instruction.
225434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      uint32_t rs_field = GetRt(instr2) << kRsShift;
225534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      uint32_t rd_field = ra.code() << kRdShift;  // Return-address (ra) reg.
225634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      *(p+2) = SPECIAL | rs_field | rd_field | JALR;
225734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    }
225834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    patched_jump = true;
225934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  } else if (IsJ(instr3)) {
226034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    if (in_range) {
226134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      // We are patching an already converted J (jump).
226234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      *(p+2) = J | target_field;
226334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    } else {
226434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      // Trying patch J, but out of range, just go back to JR.
226534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      // JR 'rs' reg is the 'rt' reg specified in the ORI instruction (instr2).
226634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      uint32_t rs_field = GetRt(instr2) << kRsShift;
226734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      *(p+2) = SPECIAL | rs_field | JR;
226834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    }
226934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    patched_jump = true;
227034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
227134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
227234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  CPU::FlushICache(pc, (patched_jump ? 3 : 2) * sizeof(int32_t));
22735c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
22745c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2275e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
227634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgvoid Assembler::JumpLabelToJumpRegister(Address pc) {
227734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Address pc points to lui/ori instructions.
227834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Jump to label may follow at pc + 2 * kInstrSize.
227934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  uint32_t* p = reinterpret_cast<uint32_t*>(pc);
228034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org#ifdef DEBUG
228134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  Instr instr1 = instr_at(pc);
228234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org#endif
228334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  Instr instr2 = instr_at(pc + 1 * kInstrSize);
228434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  Instr instr3 = instr_at(pc + 2 * kInstrSize);
228534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  bool patched = false;
228634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
228734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (IsJal(instr3)) {
228834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(GetOpcodeField(instr1) == LUI);
228934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(GetOpcodeField(instr2) == ORI);
229034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
229134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    uint32_t rs_field = GetRt(instr2) << kRsShift;
229234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    uint32_t rd_field = ra.code() << kRdShift;  // Return-address (ra) reg.
229334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    *(p+2) = SPECIAL | rs_field | rd_field | JALR;
229434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    patched = true;
229534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  } else if (IsJ(instr3)) {
229634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(GetOpcodeField(instr1) == LUI);
229734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(GetOpcodeField(instr2) == ORI);
229834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
229934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    uint32_t rs_field = GetRt(instr2) << kRsShift;
230034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    *(p+2) = SPECIAL | rs_field | JR;
230134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    patched = true;
230234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
230334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
230434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (patched) {
230534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      CPU::FlushICache(pc+2, sizeof(Address));
230634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
230734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org}
23085c838251403b0be9a882540f1922577abba4c872ager@chromium.org
23095c838251403b0be9a882540f1922577abba4c872ager@chromium.org} }  // namespace v8::internal
23105c838251403b0be9a882540f1922577abba4c872ager@chromium.org
23119dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_MIPS
2312