assembler-mips64.h revision b8a8cc1952d61a2f3a2568848933943a543b5d3e
1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright (c) 1994-2006 Sun Microsystems Inc. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// All Rights Reserved. 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Redistribution and use in source and binary forms, with or without 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// modification, are permitted provided that the following conditions are 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// met: 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - Redistributions of source code must retain the above copyright notice, 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// this list of conditions and the following disclaimer. 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - Redistribution in binary form must reproduce the above copyright 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// notice, this list of conditions and the following disclaimer in the 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// documentation and/or other materials provided with the distribution. 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - Neither the name of Sun Microsystems or the names of contributors may 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// be used to endorse or promote products derived from this software without 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// specific prior written permission. 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The original source code covered by the above license above has been 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// modified significantly by Google Inc. 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_MIPS_ASSEMBLER_MIPS_H_ 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_MIPS_ASSEMBLER_MIPS_H_ 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdio.h> 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h" 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/mips64/constants-mips64.h" 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/serialize.h" 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CPU Registers. 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 1) We would prefer to use an enum, but enum values are assignment- 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// compatible with int, which has caused code-generation bugs. 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 2) We would prefer to use a class instead of a struct but we don't like 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the register initialization to depend on the particular initialization 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// order (which appears to be different on OS X, Linux, and Windows for the 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// installed versions of C++ we tried). Using a struct permits C-style 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "initialization". Also, the Register objects cannot be const as this 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// forces initialization stubs in MSVC, making us dependent on initialization 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// order. 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 3) By not using an enum, we are possibly preventing the compiler from 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// doing certain constant folds, which may significantly reduce the 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code generated for some assembly instructions (because they boil down 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// to a few constants). If this is a problem, we could change the code 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// such that we use an enum in optimized mode, and the struct in debug 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// mode. This way we get the compile-time error checking in debug mode 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and best performance in optimized code. 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Implementation of Register and FPURegister. 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Core register. 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct Register { 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kNumRegisters = v8::internal::kNumRegisters; 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxNumAllocatableRegisters = 14; // v0 through t6 and cp. 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kSizeInBytes = 8; 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kCpRegister = 23; // cp (s7) is the 23rd register. 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static int NumAllocatableRegisters(); 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int ToAllocationIndex(Register reg) { 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((reg.code() - 2) < (kMaxNumAllocatableRegisters - 1) || 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg.is(from_code(kCpRegister))); 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reg.is(from_code(kCpRegister)) ? 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kMaxNumAllocatableRegisters - 1 : // Return last index for 'cp'. 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg.code() - 2; // zero_reg and 'at' are skipped. 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Register FromAllocationIndex(int index) { 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return index == kMaxNumAllocatableRegisters - 1 ? 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch from_code(kCpRegister) : // Last index is always the 'cp' register. 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch from_code(index + 2); // zero_reg and 'at' are skipped. 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const char* AllocationIndexToString(int index) { 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* const names[] = { 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "v0", 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "v1", 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "a0", 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "a1", 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "a2", 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "a3", 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "a4", 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "a5", 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "a6", 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "a7", 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "t0", 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "t1", 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "t2", 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "s7", 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return names[index]; 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Register from_code(int code) { 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register r = { code }; 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return r; 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is(Register reg) const { return code_ == reg.code_; } 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int code() const { 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_valid()); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return code_; 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int bit() const { 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_valid()); 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 1 << code_; 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unfortunately we can't make this private in a struct. 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int code_; 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define REGISTER(N, C) \ 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kRegister_ ## N ## _Code = C; \ 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register N = { C } 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(no_reg, -1); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Always zero. 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(zero_reg, 0); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// at: Reserved for synthetic instructions. 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(at, 1); 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// v0, v1: Used when returning multiple values from subroutines. 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(v0, 2); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(v1, 3); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// a0 - a4: Used to pass non-FP parameters. 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(a0, 4); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(a1, 5); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(a2, 6); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(a3, 7); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// a4 - a7 t0 - t3: Can be used without reservation, act as temporary registers 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and are allowed to be destroyed by subroutines. 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(a4, 8); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(a5, 9); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(a6, 10); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(a7, 11); 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(t0, 12); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(t1, 13); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(t2, 14); 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(t3, 15); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// s0 - s7: Subroutine register variables. Subroutines that write to these 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// registers must restore their values before exiting so that the caller can 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// expect the values to be preserved. 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(s0, 16); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(s1, 17); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(s2, 18); 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(s3, 19); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(s4, 20); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(s5, 21); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(s6, 22); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(s7, 23); 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(t8, 24); 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(t9, 25); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// k0, k1: Reserved for system calls and interrupt handlers. 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(k0, 26); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(k1, 27); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// gp: Reserved. 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(gp, 28); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// sp: Stack pointer. 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(sp, 29); 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// fp: Frame pointer. 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(fp, 30); 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ra: Return address pointer. 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER(ra, 31); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef REGISTER 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint ToNumber(Register reg); 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister ToRegister(int num); 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Coprocessor register. 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct FPURegister { 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxNumRegisters = v8::internal::kNumFPURegisters; 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // number of Double regs (64-bit regs, or FPU-reg-pairs). 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // A few double registers are reserved: one as a scratch register and one to 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // hold 0.0. 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // f28: 0.0 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // f30: scratch register. 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kNumReservedRegisters = 2; 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxNumAllocatableRegisters = kMaxNumRegisters / 2 - 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kNumReservedRegisters; 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static int NumRegisters(); 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static int NumAllocatableRegisters(); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static int ToAllocationIndex(FPURegister reg); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const char* AllocationIndexToString(int index); 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static FPURegister FromAllocationIndex(int index) { 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return from_code(index * 2); 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static FPURegister from_code(int code) { 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister r = { code }; 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return r; 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; } 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is(FPURegister creg) const { return code_ == creg.code_; } 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister low() const { 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(plind): Create DCHECK for FR=0 mode. This usage suspect for FR=1. 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Find low reg of a Double-reg pair, which is the reg itself. 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(code_ % 2 == 0); // Specified Double reg must be even. 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister reg; 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg.code_ = code_; 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg.is_valid()); 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reg; 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister high() const { 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(plind): Create DCHECK for FR=0 mode. This usage illegal in FR=1. 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Find high reg of a Doubel-reg pair, which is reg + 1. 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(code_ % 2 == 0); // Specified Double reg must be even. 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister reg; 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg.code_ = code_ + 1; 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg.is_valid()); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reg; 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int code() const { 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_valid()); 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return code_; 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int bit() const { 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_valid()); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 1 << code_; 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void setcode(int f) { 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code_ = f; 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_valid()); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unfortunately we can't make this private in a struct. 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int code_; 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// V8 now supports the O32 ABI, and the FPU Registers are organized as 32 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 32-bit registers, f0 through f31. When used as 'double' they are used 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// in pairs, starting with the even numbered register. So a double operation 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// on f0 really uses f0 and f1. 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (Modern mips hardware also supports 32 64-bit registers, via setting 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (privileged) Status Register FR bit to 1. This is used by the N32 ABI, 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// but it is not in common use. Someday we will want to support this in v8.) 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers. 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef FPURegister DoubleRegister; 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef FPURegister FloatRegister; 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister no_freg = { -1 }; 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f0 = { 0 }; // Return value in hard float mode. 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f1 = { 1 }; 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f2 = { 2 }; 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f3 = { 3 }; 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f4 = { 4 }; 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f5 = { 5 }; 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f6 = { 6 }; 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f7 = { 7 }; 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f8 = { 8 }; 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f9 = { 9 }; 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f10 = { 10 }; 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f11 = { 11 }; 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f12 = { 12 }; // Arg 0 in hard float mode. 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f13 = { 13 }; 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f14 = { 14 }; // Arg 1 in hard float mode. 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f15 = { 15 }; 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f16 = { 16 }; 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f17 = { 17 }; 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f18 = { 18 }; 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f19 = { 19 }; 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f20 = { 20 }; 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f21 = { 21 }; 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f22 = { 22 }; 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f23 = { 23 }; 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f24 = { 24 }; 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f25 = { 25 }; 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f26 = { 26 }; 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f27 = { 27 }; 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f28 = { 28 }; 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f29 = { 29 }; 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f30 = { 30 }; 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPURegister f31 = { 31 }; 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Register aliases. 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// cp is assumed to be a callee saved register. 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Defined using #define instead of "static const Register&" because Clang 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// complains otherwise when a compilation unit that includes this header 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// doesn't use the variables. 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kRootRegister s6 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define cp s7 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kLithiumScratchReg s3 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kLithiumScratchReg2 s4 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kLithiumScratchDouble f30 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kDoubleRegZero f28 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// FPU (coprocessor 1) control registers. 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Currently only FCSR (#31) is implemented. 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct FPUControlRegister { 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_valid() const { return code_ == kFCSRRegister; } 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is(FPUControlRegister creg) const { return code_ == creg.code_; } 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int code() const { 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_valid()); 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return code_; 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int bit() const { 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_valid()); 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 1 << code_; 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void setcode(int f) { 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code_ = f; 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_valid()); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unfortunately we can't make this private in a struct. 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int code_; 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister }; 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPUControlRegister FCSR = { kFCSRRegister }; 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Machine instruction Operands. 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst int kSmiShift = kSmiTagSize + kSmiShiftSize; 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1; 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Class Operand represents a shifter operand in data processing instructions. 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Operand BASE_EMBEDDED { 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Immediate. 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(explicit Operand(int64_t immediate, 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode rmode = RelocInfo::NONE64)); 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(explicit Operand(const ExternalReference& f)); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(explicit Operand(const char* s)); 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(explicit Operand(Object** opp)); 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(explicit Operand(Context** cpp)); 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit Operand(Handle<Object> handle); 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(explicit Operand(Smi* value)); 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Register. 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(explicit Operand(Register rm)); 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return true if this is a register operand. 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(bool is_reg() const); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int64_t immediate() const { 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!is_reg()); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return imm64_; 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rm() const { return rm_; } 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rm_; 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t imm64_; // Valid if rm_ == no_reg. 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode rmode_; 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class Assembler; 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class MacroAssembler; 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// On MIPS we have only one adressing mode with base_reg + offset. 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Class MemOperand represents a memory operand in load and store instructions. 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MemOperand : public Operand { 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Immediate value attached to offset. 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum OffsetAddend { 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset_minus_one = -1, 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset_zero = 0 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit MemOperand(Register rn, int64_t offset = 0); 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit MemOperand(Register rn, int64_t unit, int64_t multiplier, 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OffsetAddend offset_addend = offset_zero); 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t offset() const { return offset_; } 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool OffsetIsInt16Encodable() const { 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return is_int16(offset_); 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t offset_; 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class Assembler; 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Assembler : public AssemblerBase { 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create an assembler. Instructions and relocation information are emitted 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // into a buffer, with the instructions starting from the beginning and the 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // relocation information starting from the end of the buffer. See CodeDesc 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for a detailed comment on the layout (globals.h). 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the provided buffer is NULL, the assembler allocates and grows its own 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // buffer, and buffer_size determines the initial buffer size. The buffer is 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // owned by the assembler and deallocated upon destruction of the assembler. 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the provided buffer is not NULL, the assembler uses the provided buffer 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for code generation and assumes its size to be buffer_size. If the buffer 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is too small, a fatal error occurs. No deallocation of the buffer is done 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // upon destruction of the assembler. 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler(Isolate* isolate, void* buffer, int buffer_size); 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual ~Assembler() { } 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // GetCode emits any pending (non-emitted) code and fills the descriptor 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // desc. GetCode() is idempotent; it returns the same result if no other 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assembler functions are invoked in between GetCode() calls. 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GetCode(CodeDesc* desc); 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Label operations & relative jumps (PPUM Appendix D). 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Takes a branch opcode (cc) and a label (L) and generates 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // either a backward branch or a forward branch and links it 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to the label fixup chain. Usage: 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Label L; // unbound label 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // j(cc, &L); // forward branch to unbound label 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bind(&L); // bind label to the current pc 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // j(cc, &L); // backward branch to bound label 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bind(&L); // illegal: a label may be bound only once 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note: The same Label can be used for forward and backward branches 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // but it may be bound only once. 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bind(Label* L); // Binds an unbound label L to current code position. 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Determines if Label is bound and near enough so that branch instruction 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // can be used to reach it, instead of jump instruction. 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_near(Label* L); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns the branch offset to the given label from the current code 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // position. Links the label to the current position if it is still unbound. 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Manages the jump elimination optimization if the second parameter is true. 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t branch_offset(Label* L, bool jump_elimination_allowed); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t branch_offset_compact(Label* L, bool jump_elimination_allowed); 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t branch_offset21(Label* L, bool jump_elimination_allowed); 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t branch_offset21_compact(Label* L, bool jump_elimination_allowed); 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) { 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t o = branch_offset(L, jump_elimination_allowed); 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((o & 3) == 0); // Assert the offset is aligned. 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return o >> 2; 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t shifted_branch_offset_compact(Label* L, 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool jump_elimination_allowed) { 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t o = branch_offset_compact(L, jump_elimination_allowed); 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((o & 3) == 0); // Assert the offset is aligned. 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return o >> 2; 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t jump_address(Label* L); 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Puts a labels target address at the given position. 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The high 8 bits are set to zero. 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void label_at_put(Label* L, int at_offset); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Read/Modify the code target address in the branch/call instruction at pc. 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Address target_address_at(Address pc); 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void set_target_address_at(Address pc, 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address target, 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ICacheFlushMode icache_flush_mode = 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FLUSH_ICACHE_IF_NEEDED); 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // On MIPS there is no Constant Pool so we skip that parameter. 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(static Address target_address_at(Address pc, 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConstantPoolArray* constant_pool)) { 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return target_address_at(pc); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(static void set_target_address_at(Address pc, 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConstantPoolArray* constant_pool, 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address target, 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ICacheFlushMode icache_flush_mode = 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FLUSH_ICACHE_IF_NEEDED)) { 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch set_target_address_at(pc, target, icache_flush_mode); 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(static Address target_address_at(Address pc, Code* code)) { 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return target_address_at(pc, constant_pool); 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INLINE(static void set_target_address_at(Address pc, 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* code, 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address target, 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ICacheFlushMode icache_flush_mode = 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FLUSH_ICACHE_IF_NEEDED)) { 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch set_target_address_at(pc, constant_pool, target, icache_flush_mode); 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the code target address at a call site from the return address 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of that call in the instruction stream. 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Address target_address_from_return_address(Address pc); 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the code target address of the patch debug break slot 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Address break_address_from_return_address(Address pc); 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void JumpLabelToJumpRegister(Address pc); 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void QuietNaN(HeapObject* nan); 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This sets the branch destination (which gets loaded at the call address). 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is for calls and branches within generated code. The serializer 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // has already deserialized the lui/ori instructions etc. 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static void deserialization_set_special_target_at( 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address instruction_payload, Code* code, Address target) { 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch set_target_address_at( 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instruction_payload - kInstructionsFor64BitConstant * kInstrSize, 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code, 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch target); 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Size of an instruction. 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kInstrSize = sizeof(Instr); 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Difference between address of current opcode and target address offset. 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kBranchPCOffset = 4; 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Here we are patching the address in the LUI/ORI instruction pair. 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // These values are used in the serialization process and must be zero for 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // MIPS platform, as Code, Embedded Object or External-reference pointers 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // are split across two consecutive instructions and don't exist separately 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in the code, so the serializer should not step forwards in memory after 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a target is resolved and written. 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kSpecialTargetSize = 0; 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Number of consecutive instructions used to store 32bit/64bit constant. 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Before jump-optimizations, this constant was used in 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // RelocInfo::target_address_address() function to tell serializer address of 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the instruction that follows LUI/ORI instruction pair. Now, with new jump 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // optimization, where jump-through-register instruction that usually 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // follows LUI/ORI pair is substituted with J/JAL, this constant equals 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to 3 instructions (LUI+ORI+J/JAL/JR/JALR). 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kInstructionsFor32BitConstant = 3; 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kInstructionsFor64BitConstant = 5; 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Distance between the instruction referring to the address of the call 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // target and the return address. 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kCallTargetAddressOffset = 6 * kInstrSize; 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Distance between start of patched return sequence and the emitted address 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to jump to. 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kPatchReturnSequenceAddressOffset = 0; 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Distance between start of patched debug break slot and the emitted address 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to jump to. 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Difference between address of current opcode and value read from pc 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // register. 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kPcLoadDelta = 4; 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kPatchDebugBreakSlotReturnOffset = 6 * kInstrSize; 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Number of instructions used for the JS return sequence. The constant is 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // used by the debugger to patch the JS return sequence. 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kJSReturnSequenceInstructions = 7; 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kDebugBreakSlotInstructions = 6; 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kDebugBreakSlotLength = 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDebugBreakSlotInstructions * kInstrSize; 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // --------------------------------------------------------------------------- 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Code generation. 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Insert the smallest number of nop instructions 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // possible to align the pc offset to a multiple 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of m. m must be a power of 2 (>= 4). 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Align(int m); 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Aligns code to something that's optimal for a jump target for the platform. 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CodeTargetAlign(); 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Different nop operations are used by the code generator to detect certain 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // states of the generated code. 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum NopMarkerTypes { 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NON_MARKING_NOP = 0, 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DEBUG_BREAK_NOP, 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // IC markers. 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PROPERTY_ACCESS_INLINED, 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PROPERTY_ACCESS_INLINED_CONTEXT, 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE, 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Helper values. 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LAST_CODE_MARKER, 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED, 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Code aging 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CODE_AGE_MARKER_NOP = 6, 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CODE_AGE_SEQUENCE_NOP 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Type == 0 is the default non-marking nop. For mips this is a 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sll(zero_reg, zero_reg, 0). We use rt_reg == at for non-zero 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // marking, to avoid conflict with ssnop and ehb instructions. 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void nop(unsigned int type = 0) { 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(type < 32); 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register nop_rt_reg = (type == 0) ? zero_reg : at; 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sll(zero_reg, nop_rt_reg, type, true); 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // --------Branch-and-jump-instructions---------- 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We don't use likely variant of instructions. 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void b(int16_t offset); 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void b(Label* L) { b(branch_offset(L, false)>>2); } 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bal(int16_t offset); 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bal(Label* L) { bal(branch_offset(L, false)>>2); } 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void beq(Register rs, Register rt, int16_t offset); 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void beq(Register rs, Register rt, Label* L) { 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch beq(rs, rt, branch_offset(L, false) >> 2); 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgez(Register rs, int16_t offset); 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgezc(Register rt, int16_t offset); 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgezc(Register rt, Label* L) { 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bgezc(rt, branch_offset_compact(L, false)>>2); 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgeuc(Register rs, Register rt, int16_t offset); 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgeuc(Register rs, Register rt, Label* L) { 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bgeuc(rs, rt, branch_offset_compact(L, false)>>2); 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgec(Register rs, Register rt, int16_t offset); 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgec(Register rs, Register rt, Label* L) { 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bgec(rs, rt, branch_offset_compact(L, false)>>2); 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgezal(Register rs, int16_t offset); 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgezalc(Register rt, int16_t offset); 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgezalc(Register rt, Label* L) { 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bgezalc(rt, branch_offset_compact(L, false)>>2); 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgezall(Register rs, int16_t offset); 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgezall(Register rs, Label* L) { 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bgezall(rs, branch_offset(L, false)>>2); 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgtz(Register rs, int16_t offset); 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgtzc(Register rt, int16_t offset); 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgtzc(Register rt, Label* L) { 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bgtzc(rt, branch_offset_compact(L, false)>>2); 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void blez(Register rs, int16_t offset); 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void blezc(Register rt, int16_t offset); 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void blezc(Register rt, Label* L) { 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch blezc(rt, branch_offset_compact(L, false)>>2); 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bltz(Register rs, int16_t offset); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bltzc(Register rt, int16_t offset); 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bltzc(Register rt, Label* L) { 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bltzc(rt, branch_offset_compact(L, false)>>2); 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bltuc(Register rs, Register rt, int16_t offset); 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bltuc(Register rs, Register rt, Label* L) { 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bltuc(rs, rt, branch_offset_compact(L, false)>>2); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bltc(Register rs, Register rt, int16_t offset); 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bltc(Register rs, Register rt, Label* L) { 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bltc(rs, rt, branch_offset_compact(L, false)>>2); 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bltzal(Register rs, int16_t offset); 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void blezalc(Register rt, int16_t offset); 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void blezalc(Register rt, Label* L) { 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch blezalc(rt, branch_offset_compact(L, false)>>2); 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bltzalc(Register rt, int16_t offset); 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bltzalc(Register rt, Label* L) { 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bltzalc(rt, branch_offset_compact(L, false)>>2); 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgtzalc(Register rt, int16_t offset); 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bgtzalc(Register rt, Label* L) { 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bgtzalc(rt, branch_offset_compact(L, false)>>2); 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void beqzalc(Register rt, int16_t offset); 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void beqzalc(Register rt, Label* L) { 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch beqzalc(rt, branch_offset_compact(L, false)>>2); 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void beqc(Register rs, Register rt, int16_t offset); 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void beqc(Register rs, Register rt, Label* L) { 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch beqc(rs, rt, branch_offset_compact(L, false)>>2); 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void beqzc(Register rs, int32_t offset); 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void beqzc(Register rs, Label* L) { 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch beqzc(rs, branch_offset21_compact(L, false)>>2); 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bnezalc(Register rt, int16_t offset); 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bnezalc(Register rt, Label* L) { 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bnezalc(rt, branch_offset_compact(L, false)>>2); 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bnec(Register rs, Register rt, int16_t offset); 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bnec(Register rs, Register rt, Label* L) { 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bnec(rs, rt, branch_offset_compact(L, false)>>2); 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bnezc(Register rt, int32_t offset); 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bnezc(Register rt, Label* L) { 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bnezc(rt, branch_offset21_compact(L, false)>>2); 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bne(Register rs, Register rt, int16_t offset); 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bne(Register rs, Register rt, Label* L) { 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bne(rs, rt, branch_offset(L, false)>>2); 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bovc(Register rs, Register rt, int16_t offset); 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bovc(Register rs, Register rt, Label* L) { 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bovc(rs, rt, branch_offset_compact(L, false)>>2); 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bnvc(Register rs, Register rt, int16_t offset); 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bnvc(Register rs, Register rt, Label* L) { 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bnvc(rs, rt, branch_offset_compact(L, false)>>2); 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Never use the int16_t b(l)cond version with a branch offset 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instead of using the Label* version. 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits. 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void j(int64_t target); 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void jal(int64_t target); 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void jalr(Register rs, Register rd = ra); 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void jr(Register target); 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void j_or_jr(int64_t target, Register rs); 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void jal_or_jalr(int64_t target, Register rs); 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -------Data-processing-instructions--------- 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Arithmetic. 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void addu(Register rd, Register rs, Register rt); 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void subu(Register rd, Register rs, Register rt); 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void div(Register rs, Register rt); 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void divu(Register rs, Register rt); 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ddiv(Register rs, Register rt); 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ddivu(Register rs, Register rt); 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void div(Register rd, Register rs, Register rt); 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void divu(Register rd, Register rs, Register rt); 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ddiv(Register rd, Register rs, Register rt); 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ddivu(Register rd, Register rs, Register rt); 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mod(Register rd, Register rs, Register rt); 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void modu(Register rd, Register rs, Register rt); 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmod(Register rd, Register rs, Register rt); 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmodu(Register rd, Register rs, Register rt); 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mul(Register rd, Register rs, Register rt); 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void muh(Register rd, Register rs, Register rt); 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mulu(Register rd, Register rs, Register rt); 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void muhu(Register rd, Register rs, Register rt); 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mult(Register rs, Register rt); 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void multu(Register rs, Register rt); 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmul(Register rd, Register rs, Register rt); 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmuh(Register rd, Register rs, Register rt); 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmulu(Register rd, Register rs, Register rt); 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmuhu(Register rd, Register rs, Register rt); 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void daddu(Register rd, Register rs, Register rt); 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsubu(Register rd, Register rs, Register rt); 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmult(Register rs, Register rt); 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmultu(Register rs, Register rt); 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void addiu(Register rd, Register rs, int32_t j); 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void daddiu(Register rd, Register rs, int32_t j); 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Logical. 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void and_(Register rd, Register rs, Register rt); 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void or_(Register rd, Register rs, Register rt); 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void xor_(Register rd, Register rs, Register rt); 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void nor(Register rd, Register rs, Register rt); 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void andi(Register rd, Register rs, int32_t j); 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ori(Register rd, Register rs, int32_t j); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void xori(Register rd, Register rs, int32_t j); 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lui(Register rd, int32_t j); 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void aui(Register rs, Register rt, int32_t j); 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void daui(Register rs, Register rt, int32_t j); 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dahi(Register rs, int32_t j); 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dati(Register rs, int32_t j); 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Shifts. 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and may cause problems in normal code. coming_from_nop makes sure this 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // doesn't happen. 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false); 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sllv(Register rd, Register rt, Register rs); 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void srl(Register rd, Register rt, uint16_t sa); 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void srlv(Register rd, Register rt, Register rs); 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sra(Register rt, Register rd, uint16_t sa); 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void srav(Register rt, Register rd, Register rs); 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void rotr(Register rd, Register rt, uint16_t sa); 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void rotrv(Register rd, Register rt, Register rs); 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsll(Register rd, Register rt, uint16_t sa); 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsllv(Register rd, Register rt, Register rs); 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsrl(Register rd, Register rt, uint16_t sa); 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsrlv(Register rd, Register rt, Register rs); 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void drotr(Register rd, Register rt, uint16_t sa); 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void drotrv(Register rd, Register rt, Register rs); 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsra(Register rt, Register rd, uint16_t sa); 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsrav(Register rd, Register rt, Register rs); 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsll32(Register rt, Register rd, uint16_t sa); 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsrl32(Register rt, Register rd, uint16_t sa); 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsra32(Register rt, Register rd, uint16_t sa); 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ------------Memory-instructions------------- 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lb(Register rd, const MemOperand& rs); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lbu(Register rd, const MemOperand& rs); 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lh(Register rd, const MemOperand& rs); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lhu(Register rd, const MemOperand& rs); 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lw(Register rd, const MemOperand& rs); 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lwu(Register rd, const MemOperand& rs); 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lwl(Register rd, const MemOperand& rs); 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lwr(Register rd, const MemOperand& rs); 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sb(Register rd, const MemOperand& rs); 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sh(Register rd, const MemOperand& rs); 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sw(Register rd, const MemOperand& rs); 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void swl(Register rd, const MemOperand& rs); 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void swr(Register rd, const MemOperand& rs); 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldl(Register rd, const MemOperand& rs); 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldr(Register rd, const MemOperand& rs); 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sdl(Register rd, const MemOperand& rs); 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sdr(Register rd, const MemOperand& rs); 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ld(Register rd, const MemOperand& rs); 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sd(Register rd, const MemOperand& rs); 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------Prefetch-------------------- 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void pref(int32_t hint, const MemOperand& rs); 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -------------Misc-instructions-------------- 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Break / Trap instructions. 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void break_(uint32_t code, bool break_as_stop = false); 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void stop(const char* msg, uint32_t code = kMaxStopCode); 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void tge(Register rs, Register rt, uint16_t code); 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void tgeu(Register rs, Register rt, uint16_t code); 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void tlt(Register rs, Register rt, uint16_t code); 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void tltu(Register rs, Register rt, uint16_t code); 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void teq(Register rs, Register rt, uint16_t code); 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void tne(Register rs, Register rt, uint16_t code); 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move from HI/LO register. 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mfhi(Register rd); 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mflo(Register rd); 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set on less than. 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void slt(Register rd, Register rs, Register rt); 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sltu(Register rd, Register rs, Register rt); 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void slti(Register rd, Register rs, int32_t j); 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sltiu(Register rd, Register rs, int32_t j); 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional move. 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void movz(Register rd, Register rs, Register rt); 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void movn(Register rd, Register rs, Register rt); 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void movt(Register rd, Register rs, uint16_t cc = 0); 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void movf(Register rd, Register rs, uint16_t cc = 0); 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sel(SecondaryField fmt, FPURegister fd, FPURegister ft, 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fs, uint8_t sel); 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void seleqz(Register rs, Register rt, Register rd); 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void seleqz(SecondaryField fmt, FPURegister fd, FPURegister ft, 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fs); 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void selnez(Register rs, Register rt, Register rd); 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void selnez(SecondaryField fmt, FPURegister fd, FPURegister ft, 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fs); 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bit twiddling. 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void clz(Register rd, Register rs); 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ins_(Register rt, Register rs, uint16_t pos, uint16_t size); 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ext_(Register rt, Register rs, uint16_t pos, uint16_t size); 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // --------Coprocessor-instructions---------------- 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load, store, and move. 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lwc1(FPURegister fd, const MemOperand& src); 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldc1(FPURegister fd, const MemOperand& src); 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void swc1(FPURegister fs, const MemOperand& dst); 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sdc1(FPURegister fs, const MemOperand& dst); 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mtc1(Register rt, FPURegister fs); 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mthc1(Register rt, FPURegister fs); 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmtc1(Register rt, FPURegister fs); 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mfc1(Register rt, FPURegister fs); 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mfhc1(Register rt, FPURegister fs); 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmfc1(Register rt, FPURegister fs); 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ctc1(Register rt, FPUControlRegister fs); 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cfc1(Register rt, FPUControlRegister fs); 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Arithmetic. 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void add_d(FPURegister fd, FPURegister fs, FPURegister ft); 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sub_d(FPURegister fd, FPURegister fs, FPURegister ft); 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mul_d(FPURegister fd, FPURegister fs, FPURegister ft); 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft); 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void div_d(FPURegister fd, FPURegister fs, FPURegister ft); 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void abs_d(FPURegister fd, FPURegister fs); 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mov_d(FPURegister fd, FPURegister fs); 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void neg_d(FPURegister fd, FPURegister fs); 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sqrt_d(FPURegister fd, FPURegister fs); 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conversion. 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cvt_w_s(FPURegister fd, FPURegister fs); 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cvt_w_d(FPURegister fd, FPURegister fs); 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void trunc_w_s(FPURegister fd, FPURegister fs); 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void trunc_w_d(FPURegister fd, FPURegister fs); 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void round_w_s(FPURegister fd, FPURegister fs); 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void round_w_d(FPURegister fd, FPURegister fs); 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void floor_w_s(FPURegister fd, FPURegister fs); 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void floor_w_d(FPURegister fd, FPURegister fs); 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ceil_w_s(FPURegister fd, FPURegister fs); 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ceil_w_d(FPURegister fd, FPURegister fs); 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cvt_l_s(FPURegister fd, FPURegister fs); 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cvt_l_d(FPURegister fd, FPURegister fs); 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void trunc_l_s(FPURegister fd, FPURegister fs); 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void trunc_l_d(FPURegister fd, FPURegister fs); 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void round_l_s(FPURegister fd, FPURegister fs); 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void round_l_d(FPURegister fd, FPURegister fs); 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void floor_l_s(FPURegister fd, FPURegister fs); 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void floor_l_d(FPURegister fd, FPURegister fs); 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ceil_l_s(FPURegister fd, FPURegister fs); 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ceil_l_d(FPURegister fd, FPURegister fs); 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void min(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs); 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mina(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs); 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void max(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs); 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void maxa(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs); 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cvt_s_w(FPURegister fd, FPURegister fs); 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cvt_s_l(FPURegister fd, FPURegister fs); 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cvt_s_d(FPURegister fd, FPURegister fs); 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cvt_d_w(FPURegister fd, FPURegister fs); 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cvt_d_l(FPURegister fd, FPURegister fs); 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cvt_d_s(FPURegister fd, FPURegister fs); 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditions and branches for MIPSr6. 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cmp(FPUCondition cond, SecondaryField fmt, 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fd, FPURegister ft, FPURegister fs); 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bc1eqz(int16_t offset, FPURegister ft); 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bc1eqz(Label* L, FPURegister ft) { 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bc1eqz(branch_offset(L, false)>>2, ft); 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bc1nez(int16_t offset, FPURegister ft); 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bc1nez(Label* L, FPURegister ft) { 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bc1nez(branch_offset(L, false)>>2, ft); 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditions and branches for non MIPSr6. 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void c(FPUCondition cond, SecondaryField fmt, 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister ft, FPURegister fs, uint16_t cc = 0); 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bc1f(int16_t offset, uint16_t cc = 0); 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bc1f(Label* L, uint16_t cc = 0) { 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bc1f(branch_offset(L, false)>>2, cc); 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bc1t(int16_t offset, uint16_t cc = 0); 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bc1t(Label* L, uint16_t cc = 0) { 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bc1t(branch_offset(L, false)>>2, cc); 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcmp(FPURegister src1, const double src2, FPUCondition cond); 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the code size generated from label to here. 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int SizeOfCodeGeneratedSince(Label* label) { 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return pc_offset() - label->pos(); 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the number of instructions generated from label to here. 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int InstructionsGeneratedSince(Label* label) { 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return SizeOfCodeGeneratedSince(label) / kInstrSize; 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Class for scoping postponing the trampoline pool generation. 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class BlockTrampolinePoolScope { 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) { 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assem_->StartBlockTrampolinePool(); 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ~BlockTrampolinePoolScope() { 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assem_->EndBlockTrampolinePool(); 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler* assem_; 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope); 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Class for postponing the assembly buffer growth. Typically used for 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sequences of instructions that must be emitted as a unit, before 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // buffer growth (and relocation) can occur. 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This blocking scope is not nestable. 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class BlockGrowBufferScope { 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) { 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assem_->StartBlockGrowBuffer(); 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ~BlockGrowBufferScope() { 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assem_->EndBlockGrowBuffer(); 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler* assem_; 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope); 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Debugging. 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mark address of the ExitJSFrame code. 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordJSReturn(); 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mark address of a debug break slot. 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordDebugBreakSlot(); 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record the AST id of the CallIC being compiled, so that it can be placed 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in the relocation information. 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetRecordedAstId(TypeFeedbackId ast_id) { 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(recorded_ast_id_.IsNone()); 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch recorded_ast_id_ = ast_id; 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackId RecordedAstId() { 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!recorded_ast_id_.IsNone()); 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return recorded_ast_id_; 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); } 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record a comment relocation entry that can be used by a disassembler. 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use --code-comments to enable. 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordComment(const char* msg); 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int RelocateInternalReference(byte* pc, intptr_t pc_delta); 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Writes a single byte or word of data in the code stream. Used for 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // inline tables, e.g., jump-tables. 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void db(uint8_t data); 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dd(uint32_t data); 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emits the address of the code stub's first instruction. 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void emit_code_stub_address(Code* stub); 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PositionsRecorder* positions_recorder() { return &positions_recorder_; } 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Postpone the generation of the trampoline pool for the specified number of 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instructions. 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void BlockTrampolinePoolFor(int instructions); 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if there is less than kGap bytes available in the buffer. 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If this is the case, we need to grow the buffer before emitting 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // an instruction or relocation information. 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; } 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the number of bytes available in the buffer. 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int available_space() const { return reloc_info_writer.pos() - pc_; } 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Read/patch instructions. 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void instr_at_put(byte* pc, Instr instr) { 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *reinterpret_cast<Instr*>(pc) = instr; 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } 1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void instr_at_put(int pos, Instr instr) { 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if an instruction is a branch of some kind. 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsBranch(Instr instr); 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsBeq(Instr instr); 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsBne(Instr instr); 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsJump(Instr instr); 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsJ(Instr instr); 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsLui(Instr instr); 1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsOri(Instr instr); 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsJal(Instr instr); 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsJr(Instr instr); 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsJalr(Instr instr); 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsNop(Instr instr, unsigned int type); 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsPop(Instr instr); 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsPush(Instr instr); 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsLwRegFpOffset(Instr instr); 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsSwRegFpOffset(Instr instr); 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsLwRegFpNegOffset(Instr instr); 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsSwRegFpNegOffset(Instr instr); 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Register GetRtReg(Instr instr); 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Register GetRsReg(Instr instr); 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Register GetRdReg(Instr instr); 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetRt(Instr instr); 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetRtField(Instr instr); 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetRs(Instr instr); 1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetRsField(Instr instr); 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetRd(Instr instr); 1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetRdField(Instr instr); 1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetSa(Instr instr); 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetSaField(Instr instr); 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetOpcodeField(Instr instr); 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetFunction(Instr instr); 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetFunctionField(Instr instr); 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetImmediate16(Instr instr); 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static uint32_t GetLabelConst(Instr instr); 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int32_t GetBranchOffset(Instr instr); 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsLw(Instr instr); 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int16_t GetLwOffset(Instr instr); 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr SetLwOffset(Instr instr, int16_t offset); 1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsSw(Instr instr); 1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr SetSwOffset(Instr instr, int16_t offset); 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsAddImmediate(Instr instr); 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr SetAddImmediateOffset(Instr instr, int16_t offset); 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsAndImmediate(Instr instr); 1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsEmittedConstant(Instr instr); 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CheckTrampolinePool(); 1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate a constant pool of the correct size for the generated code. 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate the constant pool for the generated code. 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void PopulateConstantPool(ConstantPoolArray* constant_pool); 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected: 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Relocation for a type-recording IC has the AST id added to it. This 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // member variable is a way to pass the information from the call site to 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the relocation info. 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackId recorded_ast_id_; 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t buffer_space() const { return reloc_info_writer.pos() - pc_; } 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Decode branch instruction at pos and return branch target pos. 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t target_at(int64_t pos); 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Patch branch instruction at pos to branch to given branch target pos. 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void target_at_put(int64_t pos, int64_t target_pos); 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Say if we need to relocate with this mode. 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool MustUseReg(RelocInfo::Mode rmode); 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record reloc info for current pc_. 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Block the emission of the trampoline pool before pc_offset. 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void BlockTrampolinePoolBefore(int pc_offset) { 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (no_trampoline_pool_before_ < pc_offset) 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch no_trampoline_pool_before_ = pc_offset; 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void StartBlockTrampolinePool() { 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch trampoline_pool_blocked_nesting_++; 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EndBlockTrampolinePool() { 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch trampoline_pool_blocked_nesting_--; 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_trampoline_pool_blocked() const { 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return trampoline_pool_blocked_nesting_ > 0; 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool has_exception() const { 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return internal_trampoline_exception_; 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi); 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_trampoline_emitted() const { 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return trampoline_emitted_; 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Temporarily block automatic assembly buffer growth. 1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void StartBlockGrowBuffer() { 1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!block_buffer_growth_); 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch block_buffer_growth_ = true; 1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EndBlockGrowBuffer() { 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(block_buffer_growth_); 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch block_buffer_growth_ = false; 1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_buffer_growth_blocked() const { 1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return block_buffer_growth_; 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Buffer size and constant pool distance are checked together at regular 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // intervals of kBufferCheckInterval emitted bytes. 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kBufferCheckInterval = 1*KB/2; 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Code generation. 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The relocation writer's position is at least kGap bytes below the end of 1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the generated instructions. This is so that multi-instruction sequences do 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // not have to check for overflow. The same is true for writes of large 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // relocation info entries. 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kGap = 32; 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Repeated checking whether the trampoline pool should be emitted is rather 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // expensive. By default we only check again once a number of instructions 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // has been generated. 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kCheckConstIntervalInst = 32; 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int next_buffer_check_; // pc offset of next buffer check. 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emission of the trampoline pool may be blocked in some code sequences. 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int trampoline_pool_blocked_nesting_; // Block emission if this is not zero. 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int no_trampoline_pool_before_; // Block emission before this pc offset. 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Keep track of the last emitted pool to guarantee a maximal distance. 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int last_trampoline_pool_end_; // pc offset of the end of the last pool. 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Automatic growth of the assembly buffer may be blocked for some sequences. 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool block_buffer_growth_; // Block growth when true. 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Relocation information generation. 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Each relocation is encoded as a variable size value. 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfoWriter reloc_info_writer; 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The bound position, before this we cannot do instruction elimination. 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int last_bound_pos_; 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Code emission. 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void CheckBuffer(); 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GrowBuffer(); 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void emit(Instr x); 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void emit(uint64_t x); 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void CheckTrampolinePoolQuick(); 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Instruction generation. 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have 3 different kind of encoding layout on MIPS. 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // However due to many different types of objects encoded in the same fields 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we have quite a few aliases for each mode. 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Using the same structure to refer to Register and FPURegister would spare a 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // few aliases, but mixing both does not look clean to me. 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Anyway we could surely implement this differently. 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenInstrRegister(Opcode opcode, 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rs, 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rt, 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rd, 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint16_t sa = 0, 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SecondaryField func = NULLSF); 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenInstrRegister(Opcode opcode, 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rs, 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rt, 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint16_t msb, 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint16_t lsb, 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SecondaryField func); 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenInstrRegister(Opcode opcode, 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SecondaryField fmt, 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister ft, 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fs, 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fd, 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SecondaryField func = NULLSF); 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenInstrRegister(Opcode opcode, 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fr, 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister ft, 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fs, 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fd, 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SecondaryField func = NULLSF); 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenInstrRegister(Opcode opcode, 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SecondaryField fmt, 1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rt, 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fs, 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister fd, 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SecondaryField func = NULLSF); 1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenInstrRegister(Opcode opcode, 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SecondaryField fmt, 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rt, 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPUControlRegister fs, 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SecondaryField func = NULLSF); 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenInstrImmediate(Opcode opcode, 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rs, 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rt, 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t j); 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenInstrImmediate(Opcode opcode, 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rs, 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SecondaryField SF, 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t j); 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenInstrImmediate(Opcode opcode, 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register r1, 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPURegister r2, 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t j); 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenInstrJump(Opcode opcode, 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t address); 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Helpers. 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadRegPlusOffsetToAt(const MemOperand& src); 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Labels. 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void print(Label* L); 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bind_to(Label* L, int pos); 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void next(Label* L); 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // One trampoline consists of: 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - space for trampoline slots, 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - space for labels. 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Space for trampoline slots is equal to slot_count * 2 * kInstrSize. 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Space for trampoline slots preceeds space for labels. Each label is of one 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction size, so total amount for labels is equal to 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // label_count * kInstrSize. 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class Trampoline { 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Trampoline() { 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch start_ = 0; 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_slot_ = 0; 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch free_slot_count_ = 0; 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch end_ = 0; 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Trampoline(int start, int slot_count) { 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch start_ = start; 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_slot_ = start; 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch free_slot_count_ = slot_count; 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch end_ = start + slot_count * kTrampolineSlotsSize; 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int start() { 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return start_; 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int end() { 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return end_; 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int take_slot() { 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int trampoline_slot = kInvalidSlotPos; 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (free_slot_count_ <= 0) { 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have run out of space on trampolines. 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure we fail in debug mode, so we become aware of each case 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // when this happens. 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(0); 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Internal exception will be caught. 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch trampoline_slot = next_slot_; 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch free_slot_count_--; 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_slot_ += kTrampolineSlotsSize; 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return trampoline_slot; 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int start_; 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int end_; 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int next_slot_; 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int free_slot_count_; 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t get_trampoline_entry(int32_t pos); 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int unbound_labels_count_; 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If trampoline is emitted, generated code is becoming large. As this is 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // already a slow case which can possibly break our code generation for the 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // extreme case, we use this information to trigger different mode of 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // branch instruction generation, where we use jump instructions rather 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // than regular branch instructions. 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool trampoline_emitted_; 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kTrampolineSlotsSize = 6 * kInstrSize; 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kInvalidSlotPos = -1; 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Trampoline trampoline_; 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool internal_trampoline_exception_; 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class RegExpMacroAssemblerMIPS; 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class RelocInfo; 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class CodePatcher; 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class BlockTrampolinePoolScope; 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PositionsRecorder positions_recorder_; 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class PositionsRecorder; 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class EnsureSpace; 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass EnsureSpace BASE_EMBEDDED { 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit EnsureSpace(Assembler* assembler) { 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assembler->CheckBuffer(); 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} } // namespace v8::internal 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_ARM_ASSEMBLER_MIPS_H_ 1417