1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright (c) 1994-2006 Sun Microsystems Inc. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// All Rights Reserved. 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are met: 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistributions of source code must retain the above copyright notice, 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// this list of conditions and the following disclaimer. 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistribution in binary form must reproduce the above copyright 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer in the 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// documentation and/or other materials provided with the 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// distribution. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Neither the name of Sun Microsystems or the names of contributors may 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be used to endorse or promote products derived from this software without 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// specific prior written permission. 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THE POSSIBILITY OF SUCH DAMAGE. 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// The original source code covered by the above license above has been 34d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// modified significantly by Google Inc. 35692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A light-weight ARM Assembler 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generates user mode instructions for the ARM architecture up to version 5 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_ARM_ASSEMBLER_ARM_H_ 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_ARM_ASSEMBLER_ARM_H_ 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdio.h> 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "assembler.h" 441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "constants-arm.h" 45d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "serialize.h" 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CPU Registers. 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1) We would prefer to use an enum, but enum values are assignment- 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// compatible with int, which has caused code-generation bugs. 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 2) We would prefer to use a class instead of a struct but we don't like 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the register initialization to depend on the particular initialization 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order (which appears to be different on OS X, Linux, and Windows for the 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// installed versions of C++ we tried). Using a struct permits C-style 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "initialization". Also, the Register objects cannot be const as this 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forces initialization stubs in MSVC, making us dependent on initialization 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order. 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 3) By not using an enum, we are possibly preventing the compiler from 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// doing certain constant folds, which may significantly reduce the 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// code generated for some assembly instructions (because they boil down 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to a few constants). If this is a problem, we could change the code 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// such that we use an enum in optimized mode, and the struct in debug 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mode. This way we get the compile-time error checking in debug mode 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and best performance in optimized code. 709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Core register 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct Register { 73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const int kNumRegisters = 16; 74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const int kNumAllocatableRegisters = 8; 75257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kSizeInBytes = 4; 76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static int ToAllocationIndex(Register reg) { 789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(reg.code() < kNumAllocatableRegisters); 79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return reg.code(); 80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static Register FromAllocationIndex(int index) { 83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(index >= 0 && index < kNumAllocatableRegisters); 84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return from_code(index); 85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const char* AllocationIndexToString(int index) { 88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(index >= 0 && index < kNumAllocatableRegisters); 89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const char* const names[] = { 90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "r0", 91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "r1", 92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "r2", 93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "r3", 94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "r4", 95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "r5", 96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "r6", 97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "r7", 98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch }; 99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return names[index]; 100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static Register from_code(int code) { 103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register r = { code }; 104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return r; 105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 1080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is(Register reg) const { return code_ == reg.code_; } 1090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int code() const { 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_; 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int bit() const { 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 << code_; 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void set_code(int code) { 119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke code_ = code; 120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(is_valid()); 121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unfortunately we can't make this private in a struct. 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code_; 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// These constants are used in several locations, including static initializers 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_no_reg_Code = -1; 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r0_Code = 0; 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r1_Code = 1; 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r2_Code = 2; 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r3_Code = 3; 1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r4_Code = 4; 1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r5_Code = 5; 1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r6_Code = 6; 1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r7_Code = 7; 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r8_Code = 8; 1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r9_Code = 9; 1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r10_Code = 10; 1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_fp_Code = 11; 1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_ip_Code = 12; 1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_sp_Code = 13; 1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_lr_Code = 14; 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_pc_Code = 15; 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register no_reg = { kRegister_no_reg_Code }; 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r0 = { kRegister_r0_Code }; 1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r1 = { kRegister_r1_Code }; 1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r2 = { kRegister_r2_Code }; 1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r3 = { kRegister_r3_Code }; 1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r4 = { kRegister_r4_Code }; 1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r5 = { kRegister_r5_Code }; 1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r6 = { kRegister_r6_Code }; 1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r7 = { kRegister_r7_Code }; 1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Used as context register. 1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r8 = { kRegister_r8_Code }; 1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Used as lithium codegen scratch register. 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r9 = { kRegister_r9_Code }; 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Used as roots register. 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r10 = { kRegister_r10_Code }; 1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register fp = { kRegister_fp_Code }; 1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register ip = { kRegister_ip_Code }; 1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register sp = { kRegister_sp_Code }; 1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register lr = { kRegister_lr_Code }; 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register pc = { kRegister_pc_Code }; 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 168e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 169e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Single word VFP register. 170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestruct SwVfpRegister { 1710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is_valid() const { return 0 <= code_ && code_ < 32; } 1720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is(SwVfpRegister reg) const { return code_ == reg.code_; } 1730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int code() const { 174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(is_valid()); 175e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return code_; 176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int bit() const { 178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(is_valid()); 179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return 1 << code_; 180e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void split_code(int* vm, int* m) const { 18280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(is_valid()); 18380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen *m = code_ & 0x1; 18480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen *vm = code_ >> 1; 18580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int code_; 188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}; 189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Double word VFP register. 192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestruct DwVfpRegister { 193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const int kNumRegisters = 16; 1943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // A few double registers are reserved: one as a scratch register and one to 1953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // hold 0.0, that does not fit in the immediate field of vmov instructions. 1963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // d14: 0.0 1973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // d15: scratch register. 1983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const int kNumReservedRegisters = 2; 1993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const int kNumAllocatableRegisters = kNumRegisters - 2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch kNumReservedRegisters; 201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 202692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch inline static int ToAllocationIndex(DwVfpRegister reg); 203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static DwVfpRegister FromAllocationIndex(int index) { 205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(index >= 0 && index < kNumAllocatableRegisters); 206692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch return from_code(index); 207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const char* AllocationIndexToString(int index) { 210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(index >= 0 && index < kNumAllocatableRegisters); 211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const char* const names[] = { 2123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch "d0", 213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d1", 214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d2", 215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d3", 216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d4", 217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d5", 218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d6", 219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d7", 220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d8", 221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d9", 222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d10", 223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d11", 224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "d12", 2253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch "d13" 226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch }; 227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return names[index]; 228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static DwVfpRegister from_code(int code) { 231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DwVfpRegister r = { code }; 232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return r; 233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Supporting d0 to d15, can be later extended to d31. 2360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is_valid() const { return 0 <= code_ && code_ < 16; } 2370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is(DwVfpRegister reg) const { return code_ == reg.code_; } 2380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen SwVfpRegister low() const { 2393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch SwVfpRegister reg; 2403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch reg.code_ = code_ * 2; 2413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 2423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(reg.is_valid()); 2433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch return reg; 2443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 2450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen SwVfpRegister high() const { 2463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch SwVfpRegister reg; 2473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch reg.code_ = (code_ * 2) + 1; 2483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 2493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(reg.is_valid()); 2503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch return reg; 2513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 2520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int code() const { 253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(is_valid()); 254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return code_; 255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int bit() const { 257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(is_valid()); 258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return 1 << code_; 259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void split_code(int* vm, int* m) const { 26180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(is_valid()); 26280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen *m = (code_ & 0x10) >> 4; 26380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen *vm = code_ & 0x0F; 26480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int code_; 267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}; 268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochtypedef DwVfpRegister DoubleRegister; 271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Support for the VFP registers s0 to s31 (d0 to d15). 274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Note that "s(N):s(N+1)" is the same as "d(N/2)". 2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s0 = { 0 }; 2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s1 = { 1 }; 2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s2 = { 2 }; 2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s3 = { 3 }; 2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s4 = { 4 }; 2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s5 = { 5 }; 2816ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s6 = { 6 }; 2826ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s7 = { 7 }; 2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s8 = { 8 }; 2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s9 = { 9 }; 2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s10 = { 10 }; 2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s11 = { 11 }; 2876ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s12 = { 12 }; 2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s13 = { 13 }; 2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s14 = { 14 }; 2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s15 = { 15 }; 2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s16 = { 16 }; 2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s17 = { 17 }; 2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s18 = { 18 }; 2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s19 = { 19 }; 2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s20 = { 20 }; 2966ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s21 = { 21 }; 2976ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s22 = { 22 }; 2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s23 = { 23 }; 2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s24 = { 24 }; 3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s25 = { 25 }; 3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s26 = { 26 }; 3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s27 = { 27 }; 3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s28 = { 28 }; 3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s29 = { 29 }; 3056ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s30 = { 30 }; 3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst SwVfpRegister s31 = { 31 }; 3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochconst DwVfpRegister no_dreg = { -1 }; 3096ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d0 = { 0 }; 3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d1 = { 1 }; 3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d2 = { 2 }; 3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d3 = { 3 }; 3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d4 = { 4 }; 3146ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d5 = { 5 }; 3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d6 = { 6 }; 3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d7 = { 7 }; 3176ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d8 = { 8 }; 3186ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d9 = { 9 }; 3196ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d10 = { 10 }; 3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d11 = { 11 }; 3216ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d12 = { 12 }; 3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d13 = { 13 }; 3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d14 = { 14 }; 3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst DwVfpRegister d15 = { 15 }; 325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Aliases for double registers. Defined using #define instead of 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// "static const DwVfpRegister&" because Clang complains otherwise when a 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// compilation unit that includes this header doesn't use the variables. 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define kFirstCalleeSavedDoubleReg d8 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define kLastCalleeSavedDoubleReg d15 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define kDoubleRegZero d14 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define kScratchDoubleReg d15 3337d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Coprocessor register 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct CRegister { 3370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is_valid() const { return 0 <= code_ && code_ < 16; } 3380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is(CRegister creg) const { return code_ == creg.code_; } 3390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int code() const { 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_; 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int bit() const { 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 << code_; 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unfortunately we can't make this private in a struct. 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code_; 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister no_creg = { -1 }; 3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr0 = { 0 }; 3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr1 = { 1 }; 3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr2 = { 2 }; 3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr3 = { 3 }; 3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr4 = { 4 }; 3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr5 = { 5 }; 3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr6 = { 6 }; 3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr7 = { 7 }; 3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr8 = { 8 }; 3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr9 = { 9 }; 3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr10 = { 10 }; 3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr11 = { 11 }; 3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr12 = { 12 }; 3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr13 = { 13 }; 3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr14 = { 14 }; 3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst CRegister cr15 = { 15 }; 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Coprocessor number 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Coprocessor { 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p0 = 0, 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p1 = 1, 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p2 = 2, 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p3 = 3, 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p4 = 4, 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p5 = 5, 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p6 = 6, 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p7 = 7, 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p8 = 8, 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p9 = 9, 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p10 = 10, 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p11 = 11, 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p12 = 12, 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p13 = 13, 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p14 = 14, 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p15 = 15 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Operands 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Class Operand represents a shifter operand in data processing instructions 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Operand BASE_EMBEDDED { 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // immediate 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(explicit Operand(int32_t immediate, 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode = RelocInfo::NONE)); 40369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch INLINE(static Operand Zero()) { 40469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return Operand(static_cast<int32_t>(0)); 40569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(explicit Operand(const ExternalReference& f)); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Operand(Handle<Object> handle); 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(explicit Operand(Smi* value)); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rm 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(explicit Operand(Register rm)); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rm <shift_op> shift_imm 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Operand(Register rm, ShiftOp shift_op, int shift_imm); 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rm <shift_op> rs 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Operand(Register rm, ShiftOp shift_op, Register rs); 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return true if this is a register operand. 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(bool is_reg() const); 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Return true if this operand fits in one instruction so that no 42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // 2-instruction solution with a load into the ip register is necessary. If 42444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // the instruction this operand is used for is a MOV or MVN instruction the 42544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // actual instruction to use is required for this calculation. For other 42644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // instructions instr is ignored. 42744f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool is_single_instruction(Instr instr = 0) const; 4283e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu bool must_use_constant_pool() const; 4299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen inline int32_t immediate() const { 4319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ASSERT(!rm_.is_valid()); 4329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return imm32_; 4339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rm() const { return rm_; } 43650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Register rs() const { return rs_; } 43750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ShiftOp shift_op() const { return shift_op_; } 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rm_; 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rs_; 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ShiftOp shift_op_; 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm32_; // valid if rm_ == no_reg 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode_; 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class Assembler; 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Class MemOperand represents a memory operand in load and store instructions 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MemOperand BASE_EMBEDDED { 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [rn +/- offset] Offset/NegOffset 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [rn +/- offset]! PreIndex/NegPreIndex 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [rn], +/- offset PostIndex/NegPostIndex 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset is any signed 32-bit value; offset is first loaded to register ip if 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // it does not fit the addressing mode (12-bit unsigned and sign bit) 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset); 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [rn +/- rm] Offset/NegOffset 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [rn +/- rm]! PreIndex/NegPreIndex 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [rn], +/- rm PostIndex/NegPostIndex 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit MemOperand(Register rn, Register rm, AddrMode am = Offset); 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit MemOperand(Register rn, Register rm, 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ShiftOp shift_op, int shift_imm, AddrMode am = Offset); 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen void set_offset(int32_t offset) { 47325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ASSERT(rm_.is(no_reg)); 47425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen offset_ = offset; 47525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 47625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch uint32_t offset() const { 47825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ASSERT(rm_.is(no_reg)); 47925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return offset_; 48025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 48125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register rn() const { return rn_; } 483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register rm() const { return rm_; } 4843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddrMode am() const { return am_; } 48525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bool OffsetIsUint12Encodable() const { 487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_); 488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 489e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rn_; // base 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rm_; // register offset 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t offset_; // valid if rm_ == no_reg 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ShiftOp shift_op_; 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddrMode am_; // bits P, U, and W 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class Assembler; 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// CpuFeatures keeps track of which features are supported by the target CPU. 502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Supported features must be enabled by a Scope before use. 5038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass CpuFeatures : public AllStatic { 504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Detect features of the target CPU. Set safe defaults if the serializer 506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // is enabled (snapshots must be portable). 5078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static void Probe(); 508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check whether a feature is supported by the target CPU. 5108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static bool IsSupported(CpuFeature f) { 5118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(initialized_); 512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (f == VFP3 && !FLAG_enable_vfp3) return false; 513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return (supported_ & (1u << f)) != 0; 514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG 517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check whether a feature is currently enabled. 5188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static bool IsEnabled(CpuFeature f) { 5198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(initialized_); 5208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Isolate* isolate = Isolate::UncheckedCurrent(); 5218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (isolate == NULL) { 5228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // When no isolate is available, work as if we're running in 5238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // release mode. 5248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return IsSupported(f); 5258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features()); 5278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return (enabled & (1u << f)) != 0; 528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 5298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif 530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Enable a specified feature within a scope. 532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block class Scope BASE_EMBEDDED { 533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG 5343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 5368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch explicit Scope(CpuFeature f) { 5378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch unsigned mask = 1u << f; 5388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(CpuFeatures::IsSupported(f)); 539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!Serializer::enabled() || 5408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch (CpuFeatures::found_by_runtime_probing_ & mask) == 0); 5418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch isolate_ = Isolate::UncheckedCurrent(); 5428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch old_enabled_ = 0; 5438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (isolate_ != NULL) { 5448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features()); 5458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch isolate_->set_enabled_cpu_features(old_enabled_ | mask); 5468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ~Scope() { 5498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_); 5508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (isolate_ != NULL) { 5518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch isolate_->set_enabled_cpu_features(old_enabled_); 5528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 5543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private: 55644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate_; 5578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch unsigned old_enabled_; 558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#else 5593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block explicit Scope(CpuFeature f) {} 562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block }; 564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch class TryForceFeatureScope BASE_EMBEDDED { 5668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public: 5678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch explicit TryForceFeatureScope(CpuFeature f) 5688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : old_supported_(CpuFeatures::supported_) { 5698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CanForce()) { 5708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CpuFeatures::supported_ |= (1u << f); 5718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 57344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ~TryForceFeatureScope() { 5758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CanForce()) { 5768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CpuFeatures::supported_ = old_supported_; 5778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private: 5818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static bool CanForce() { 5828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // It's only safe to temporarily force support of CPU features 5838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // when there's only a single isolate, which is guaranteed when 5848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // the serializer is enabled. 5858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Serializer::enabled(); 5868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const unsigned old_supported_; 5898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch }; 5908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private: 5928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG 5938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static bool initialized_; 5948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif 5958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static unsigned supported_; 5968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static unsigned found_by_runtime_probing_; 59744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 59844f0eee88ff00398ff7f715fab053374d808c90dSteve Block DISALLOW_COPY_AND_ASSIGN(CpuFeatures); 599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockextern const Instr kMovLrPc; 6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockextern const Instr kLdrPCMask; 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockextern const Instr kLdrPCPattern; 6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockextern const Instr kBlxRegMask; 6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockextern const Instr kBlxRegPattern; 6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochextern const Instr kBlxIp; 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kMovMvnMask; 6109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kMovMvnPattern; 6119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kMovMvnFlip; 6129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 6139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kMovLeaveCCMask; 6149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kMovLeaveCCPattern; 6159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kMovwMask; 6169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kMovwPattern; 6179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kMovwLeaveCCFlip; 6189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 6199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kCmpCmnMask; 6209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kCmpCmnPattern; 6219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kCmpCmnFlip; 6229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kAddSubFlip; 6239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenextern const Instr kAndBicFlip; 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 62744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass Assembler : public AssemblerBase { 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create an assembler. Instructions and relocation information are emitted 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // into a buffer, with the instructions starting from the beginning and the 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocation information starting from the end of the buffer. See CodeDesc 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for a detailed comment on the layout (globals.h). 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the provided buffer is NULL, the assembler allocates and grows its own 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // buffer, and buffer_size determines the initial buffer size. The buffer is 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // owned by the assembler and deallocated upon destruction of the assembler. 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the provided buffer is not NULL, the assembler uses the provided buffer 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for code generation and assumes its size to be buffer_size. If the buffer 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is too small, a fatal error occurs. No deallocation of the buffer is done 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // upon destruction of the assembler. 6428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Assembler(Isolate* isolate, void* buffer, int buffer_size); 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Assembler(); 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Overrides the default provided by FLAG_debug_code. 64644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void set_emit_debug_code(bool value) { emit_debug_code_ = value; } 64744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GetCode emits any pending (non-emitted) code and fills the descriptor 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // desc. GetCode() is idempotent; it returns the same result if no other 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assembler functions are invoked in between GetCode() calls. 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GetCode(CodeDesc* desc); 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Label operations & relative jumps (PPUM Appendix D) 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Takes a branch opcode (cc) and a label (L) and generates 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // either a backward branch or a forward branch and links it 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the label fixup chain. Usage: 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Label L; // unbound label 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // j(cc, &L); // forward branch to unbound label 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bind(&L); // bind label to the current pc 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // j(cc, &L); // backward branch to bound label 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bind(&L); // illegal: a label may be bound only once 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Note: The same Label can be used for forward and backward branches 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // but it may be bound only once. 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bind(Label* L); // binds an unbound label L to the current code position 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the branch offset to the given label from the current code position 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Links the label to the current position if it is still unbound 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Manages the jump elimination optimization if the second parameter is true. 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int branch_offset(Label* L, bool jump_elimination_allowed); 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Puts a labels target address at the given position. 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The high 8 bits are set to zero. 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void label_at_put(Label* L, int at_offset); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the address in the constant pool of the code target address used by 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the branch/call instruction at pc. 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(static Address target_address_address_at(Address pc)); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read/Modify the code target address in the branch/call instruction at pc. 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(static Address target_address_at(Address pc)); 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(static void set_target_address_at(Address pc, Address target)); 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This sets the branch destination (which is in the constant pool on ARM). 688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is for calls and branches within generated code. 6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline static void deserialization_set_special_target_at( 6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address constant_pool_entry, Address target); 691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This sets the branch destination (which is in the constant pool on ARM). 693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is for calls and branches to runtime code. 694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block inline static void set_external_target_at(Address constant_pool_entry, 6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address target); 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Here we are patching the address in the constant pool, not the actual call 698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // instruction. The address in the constant pool is the same size as a 699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // pointer. 7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSpecialTargetSize = kPointerSize; 701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Size of an instruction. 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kInstrSize = sizeof(Instr); 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Distance between the instruction referring to the address of the call 7066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // target and the return address. 7076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef USE_BLX 7086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Call sequence is: 7096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ldr ip, [pc, #...] @ call address 7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // blx ip 7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // @ return address 7126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kCallTargetAddressOffset = 2 * kInstrSize; 7136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else 7146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Call sequence is: 7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // mov lr, pc 7166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ldr pc, [pc, #...] @ call address 7176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // @ return address 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kCallTargetAddressOffset = kInstrSize; 7196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Distance between start of patched return sequence and the emitted address 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to jump to. 7236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef USE_BLX 7247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Patched return sequence is: 7256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ldr ip, [pc, #0] @ emited address and start 7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // blx ip 7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize; 7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else 7297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Patched return sequence is: 7306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // mov lr, pc @ start of sequence 7316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ldr pc, [pc, #-4] @ emited address 7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kPatchReturnSequenceAddressOffset = kInstrSize; 7336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Distance between start of patched debug break slot and the emitted address 7367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // to jump to. 7377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#ifdef USE_BLX 7387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Patched debug break slot code is: 7397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ldr ip, [pc, #0] @ emited address and start 7407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // blx ip 7417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; 7427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#else 7437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Patched debug break slot code is: 7447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // mov lr, pc @ start of sequence 7457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ldr pc, [pc, #-4] @ emited address 7467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kPatchDebugBreakSlotAddressOffset = kInstrSize; 7477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#endif 7487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Difference between address of current opcode and value read from pc 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register. 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kPcLoadDelta = 8; 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kJSReturnSequenceInstructions = 4; 7547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kDebugBreakSlotInstructions = 3; 7557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kDebugBreakSlotLength = 7567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch kDebugBreakSlotInstructions * kInstrSize; 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code generation 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Insert the smallest number of nop instructions 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // possible to align the pc offset to a multiple 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of m. m must be a power of 2 (>= 4). 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Align(int m); 7659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Aligns code to something that's optimal for a jump target for the platform. 7669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void CodeTargetAlign(); 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Branch instructions 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void b(int branch_offset, Condition cond = al); 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bl(int branch_offset, Condition cond = al); 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void blx(int branch_offset); // v5 and above 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void blx(Register target, Condition cond = al); // v5 and above 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bx(Register target, Condition cond = al); // v5 and above, plus v4t 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convenience branch instructions using labels 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void b(Label* L, Condition cond = al) { 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block b(branch_offset(L, cond == al), cond); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); } 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); } 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); } 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Data-processing instructions 7853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(Register dst, Register src1, const Operand& src2, 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void eor(Register dst, Register src1, const Operand& src2, 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sub(Register dst, Register src1, const Operand& src2, 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sub(Register dst, Register src1, Register src2, 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al) { 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sub(dst, src1, Operand(src2), s, cond); 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void rsb(Register dst, Register src1, const Operand& src2, 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void add(Register dst, Register src1, const Operand& src2, 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 8047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void add(Register dst, Register src1, Register src2, 8057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch SBit s = LeaveCC, Condition cond = al) { 8067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch add(dst, src1, Operand(src2), s, cond); 8077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void adc(Register dst, Register src1, const Operand& src2, 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sbc(Register dst, Register src1, const Operand& src2, 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void rsc(Register dst, Register src1, const Operand& src2, 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void tst(Register src1, const Operand& src2, Condition cond = al); 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void tst(Register src1, Register src2, Condition cond = al) { 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tst(src1, Operand(src2), cond); 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void teq(Register src1, const Operand& src2, Condition cond = al); 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(Register src1, const Operand& src2, Condition cond = al); 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(Register src1, Register src2, Condition cond = al) { 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cmp(src1, Operand(src2), cond); 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al); 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmn(Register src1, const Operand& src2, Condition cond = al); 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void orr(Register dst, Register src1, const Operand& src2, 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void orr(Register dst, Register src1, Register src2, 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al) { 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block orr(dst, src1, Operand(src2), s, cond); 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, const Operand& src, 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) { 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(dst, Operand(src), s, cond); 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ARMv7 instructions for loading a 32 bit immediate in two instructions. 8479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // This may actually emit a different mov instruction, but on an ARMv7 it 8489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // is guaranteed to only emit one instruction. 8499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void movw(Register reg, uint32_t immediate, Condition cond = al); 8509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // The constant for movt should be in the range 0-0xffff. 8519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void movt(Register reg, uint32_t immediate, Condition cond = al); 8529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bic(Register dst, Register src1, const Operand& src2, 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mvn(Register dst, const Operand& src, 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Multiply instructions 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mla(Register dst, Register src1, Register src2, Register srcA, 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mul(Register dst, Register src1, Register src2, 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void smlal(Register dstL, Register dstH, Register src1, Register src2, 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void smull(Register dstL, Register dstH, Register src1, Register src2, 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void umlal(Register dstL, Register dstH, Register src1, Register src2, 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void umull(Register dstL, Register dstH, Register src1, Register src2, 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s = LeaveCC, Condition cond = al); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Miscellaneous arithmetic instructions 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void clz(Register dst, Register src, Condition cond = al); // v5 and above 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 88350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Saturating instructions. v6 and above. 88450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 88550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Unsigned saturate. 88650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // 88750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Saturate an optionally shifted signed value to an unsigned range. 88850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // 88950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // usat dst, #satpos, src 89050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // usat dst, #satpos, src, lsl #sh 89150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // usat dst, #satpos, src, asr #sh 89250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // 89350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Register dst will contain: 89450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // 89550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // 0, if s < 0 89650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // (1 << satpos) - 1, if s > ((1 << satpos) - 1) 89750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // s, otherwise 89850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // 89950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // where s is the contents of src after shifting (if used.) 90050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen void usat(Register dst, int satpos, const Operand& src, Condition cond = al); 90150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 9027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Bitfield manipulation instructions. v7 and above. 9037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 9047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void ubfx(Register dst, Register src, int lsb, int width, 9057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Condition cond = al); 9067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 9077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void sbfx(Register dst, Register src, int lsb, int width, 9087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Condition cond = al); 9097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 9107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void bfc(Register dst, int lsb, int width, Condition cond = al); 9117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 9127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void bfi(Register dst, Register src, int lsb, int width, 9137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Condition cond = al); 9147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Status register access instructions 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mrs(Register dst, SRegister s, Condition cond = al); 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al); 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load/Store instructions 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ldr(Register dst, const MemOperand& src, Condition cond = al); 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void str(Register src, const MemOperand& dst, Condition cond = al); 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ldrb(Register dst, const MemOperand& src, Condition cond = al); 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void strb(Register src, const MemOperand& dst, Condition cond = al); 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ldrh(Register dst, const MemOperand& src, Condition cond = al); 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void strh(Register src, const MemOperand& dst, Condition cond = al); 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ldrsb(Register dst, const MemOperand& src, Condition cond = al); 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ldrsh(Register dst, const MemOperand& src, Condition cond = al); 929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void ldrd(Register dst1, 930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register dst2, 931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke const MemOperand& src, Condition cond = al); 932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void strd(Register src1, 933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register src2, 934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke const MemOperand& dst, Condition cond = al); 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load/Store multiple instructions 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al); 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al); 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exception-generating instructions and debugging support 9413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu void stop(const char* msg, 9423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Condition cond = al, 9433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu int32_t code = kDefaultStopCode); 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bkpt(uint32_t imm16); // v5 and above 9463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu void svc(uint32_t imm24, Condition cond = al); 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Coprocessor instructions 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cdp(Coprocessor coproc, int opcode_1, 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, CRegister crn, CRegister crm, 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2, Condition cond = al); 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cdp2(Coprocessor coproc, int opcode_1, 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, CRegister crn, CRegister crm, 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2); // v5 and above 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mcr(Coprocessor coproc, int opcode_1, 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rd, CRegister crn, CRegister crm, 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2 = 0, Condition cond = al); 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mcr2(Coprocessor coproc, int opcode_1, 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rd, CRegister crn, CRegister crm, 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2 = 0); // v5 and above 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mrc(Coprocessor coproc, int opcode_1, 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rd, CRegister crn, CRegister crm, 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2 = 0, Condition cond = al); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mrc2(Coprocessor coproc, int opcode_1, 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rd, CRegister crn, CRegister crm, 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2 = 0); // v5 and above 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src, 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l = Short, Condition cond = al); 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ldc(Coprocessor coproc, CRegister crd, Register base, int option, 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l = Short, Condition cond = al); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src, 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l = Short); // v5 and above 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ldc2(Coprocessor coproc, CRegister crd, Register base, int option, 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l = Short); // v5 and above 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 984d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Support for VFP. 985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // All these APIs support S0 to S31 and D0 to D15. 986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Currently these APIs do not support extended D registers, i.e, D16 to D31. 987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // However, some simple modifications can allow 988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // these APIs to support D16 to D31. 989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 990d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void vldr(const DwVfpRegister dst, 991d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const Register base, 992e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int offset, 993e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const Condition cond = al); 994e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void vldr(const DwVfpRegister dst, 995e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const MemOperand& src, 996d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const Condition cond = al); 9976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void vldr(const SwVfpRegister dst, 9996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const Register base, 1000e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int offset, 1001e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const Condition cond = al); 1002e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void vldr(const SwVfpRegister dst, 1003e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const MemOperand& src, 10046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const Condition cond = al); 10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1006d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void vstr(const DwVfpRegister src, 1007d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const Register base, 1008e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int offset, 1009e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const Condition cond = al); 1010e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void vstr(const DwVfpRegister src, 1011e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const MemOperand& dst, 1012d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const Condition cond = al); 10138defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1014756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void vstr(const SwVfpRegister src, 1015756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const Register base, 1016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int offset, 1017e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const Condition cond = al); 1018e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void vstr(const SwVfpRegister src, 1019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const MemOperand& dst, 1020756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const Condition cond = al); 1021756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 10228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void vldm(BlockAddrMode am, 10238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Register base, 10248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch DwVfpRegister first, 10258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch DwVfpRegister last, 10268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Condition cond = al); 10278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 10288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void vstm(BlockAddrMode am, 10298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Register base, 10308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch DwVfpRegister first, 10318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch DwVfpRegister last, 10328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Condition cond = al); 10338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 10348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void vldm(BlockAddrMode am, 10358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Register base, 10368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SwVfpRegister first, 10378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SwVfpRegister last, 10388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Condition cond = al); 10398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 10408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void vstm(BlockAddrMode am, 10418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Register base, 10428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SwVfpRegister first, 10438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SwVfpRegister last, 10448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Condition cond = al); 10458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 10468defd9ff6930b4e24729971a61cf7469daf119beSteve Block void vmov(const DwVfpRegister dst, 10473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch double imm, 10483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const Condition cond = al); 10493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch void vmov(const SwVfpRegister dst, 10503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const SwVfpRegister src, 10513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const Condition cond = al); 10523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch void vmov(const DwVfpRegister dst, 10538defd9ff6930b4e24729971a61cf7469daf119beSteve Block const DwVfpRegister src, 10548defd9ff6930b4e24729971a61cf7469daf119beSteve Block const Condition cond = al); 1055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void vmov(const DwVfpRegister dst, 1056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const Register src1, 1057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const Register src2, 1058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const Condition cond = al); 1059e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void vmov(const Register dst1, 1060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const Register dst2, 1061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const DwVfpRegister src, 1062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond = al); 1063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void vmov(const SwVfpRegister dst, 1064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src, 1065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond = al); 1066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void vmov(const Register dst, 1067e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const SwVfpRegister src, 1068e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const Condition cond = al); 10696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void vcvt_f64_s32(const DwVfpRegister dst, 10706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const SwVfpRegister src, 10711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block VFPConversionMode mode = kDefaultRoundToZero, 10726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const Condition cond = al); 10736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void vcvt_f32_s32(const SwVfpRegister dst, 10746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const SwVfpRegister src, 10751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block VFPConversionMode mode = kDefaultRoundToZero, 10766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const Condition cond = al); 10776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void vcvt_f64_u32(const DwVfpRegister dst, 10786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const SwVfpRegister src, 10791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block VFPConversionMode mode = kDefaultRoundToZero, 10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const Condition cond = al); 10816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void vcvt_s32_f64(const SwVfpRegister dst, 10826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const DwVfpRegister src, 10831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block VFPConversionMode mode = kDefaultRoundToZero, 10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const Condition cond = al); 10856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void vcvt_u32_f64(const SwVfpRegister dst, 10866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const DwVfpRegister src, 10871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block VFPConversionMode mode = kDefaultRoundToZero, 10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const Condition cond = al); 10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void vcvt_f64_f32(const DwVfpRegister dst, 10906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const SwVfpRegister src, 10911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block VFPConversionMode mode = kDefaultRoundToZero, 10926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const Condition cond = al); 10936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void vcvt_f32_f64(const SwVfpRegister dst, 10946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const DwVfpRegister src, 10951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block VFPConversionMode mode = kDefaultRoundToZero, 10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const Condition cond = al); 1097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 109844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void vneg(const DwVfpRegister dst, 109944f0eee88ff00398ff7f715fab053374d808c90dSteve Block const DwVfpRegister src, 110044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Condition cond = al); 11011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void vabs(const DwVfpRegister dst, 11021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const DwVfpRegister src, 11031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const Condition cond = al); 1104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void vadd(const DwVfpRegister dst, 1105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const DwVfpRegister src1, 1106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const DwVfpRegister src2, 1107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const Condition cond = al); 1108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void vsub(const DwVfpRegister dst, 1109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const DwVfpRegister src1, 1110e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const DwVfpRegister src2, 1111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const Condition cond = al); 1112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void vmul(const DwVfpRegister dst, 1113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const DwVfpRegister src1, 1114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const DwVfpRegister src2, 1115e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const Condition cond = al); 1116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void vdiv(const DwVfpRegister dst, 1117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const DwVfpRegister src1, 1118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const DwVfpRegister src2, 1119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const Condition cond = al); 1120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void vcmp(const DwVfpRegister src1, 1121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const DwVfpRegister src2, 1122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond = al); 1123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void vcmp(const DwVfpRegister src1, 1124756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const double src2, 1125756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const Condition cond = al); 1126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void vmrs(const Register dst, 1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond = al); 112890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner void vmsr(const Register dst, 112990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner const Condition cond = al); 11308defd9ff6930b4e24729971a61cf7469daf119beSteve Block void vsqrt(const DwVfpRegister dst, 11318defd9ff6930b4e24729971a61cf7469daf119beSteve Block const DwVfpRegister src, 11328defd9ff6930b4e24729971a61cf7469daf119beSteve Block const Condition cond = al); 1133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pseudo instructions 11358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 11368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Different nop operations are used by the code generator to detect certain 11378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // states of the generated code. 11388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang enum NopMarkerTypes { 11398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang NON_MARKING_NOP = 0, 11408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang DEBUG_BREAK_NOP, 11418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // IC markers. 11428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang PROPERTY_ACCESS_INLINED, 11438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang PROPERTY_ACCESS_INLINED_CONTEXT, 11448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE, 11458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Helper values. 11468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LAST_CODE_MARKER, 11478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED 11488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang }; 11498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 11508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang void nop(int type = 0); // 0 is the default non-marking type. 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(Register src, Condition cond = al) { 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block str(src, MemOperand(sp, 4, NegPreIndex), cond); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pop(Register dst, Condition cond = al) { 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ldr(dst, MemOperand(sp, 4, PostIndex), cond); 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pop() { 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add(sp, sp, Operand(kPointerSize)); 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump unconditionally to given label. 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(Label* L) { b(L, al); } 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the code size generated from label to here. 11683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int SizeOfCodeGeneratedSince(Label* label) { 11693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return pc_offset() - label->pos(); 11703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 11713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 11723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check the number of instructions generated from label to here. 11733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int InstructionsGeneratedSince(Label* label) { 11743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return SizeOfCodeGeneratedSince(label) / kInstrSize; 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check whether an immediate fits an addressing mode 1 instruction. 1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool ImmediateFitsAddrMode1Instruction(int32_t imm32); 1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Class for scoping postponing the constant pool generation. 11816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block class BlockConstPoolScope { 11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) { 11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block assem_->StartBlockConstPool(); 11856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ~BlockConstPoolScope() { 11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block assem_->EndBlockConstPool(); 11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Assembler* assem_; 11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope); 11946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block }; 11956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugging 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark address of the ExitJSFrame code. 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordJSReturn(); 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Mark address of a debug break slot. 12027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void RecordDebugBreakSlot(); 12037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Record the AST id of the CallIC being compiled, so that it can be placed 1205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // in the relocation information. 12063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void SetRecordedAstId(unsigned ast_id) { 12073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(recorded_ast_id_ == kNoASTId); 12083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch recorded_ast_id_ = ast_id; 12093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 12103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 12113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unsigned RecordedAstId() { 12123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(recorded_ast_id_ != kNoASTId); 12133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return recorded_ast_id_; 12143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 12153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 12163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void ClearRecordedAstId() { recorded_ast_id_ = kNoASTId; } 1217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Record a comment relocation entry that can be used by a disassembler. 1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Use --code-comments to enable. 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordComment(const char* msg); 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1222b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Writes a single byte or word of data in the code stream. Used 1223b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // for inline tables, e.g., jump-tables. The constant pool should be 1224b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // emitted before any use of db and dd to ensure that constant pools 1225b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // are not emitted as part of the tables generated. 1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void db(uint8_t data); 1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void dd(uint32_t data); 1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int pc_offset() const { return pc_ - buffer_; } 12303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 12313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu PositionsRecorder* positions_recorder() { return &positions_recorder_; } 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read/patch instructions 12343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } 12353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void instr_at_put(int pos, Instr instr) { 12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } 12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static void instr_at_put(byte* pc, Instr instr) { 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<Instr*>(pc) = instr; 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static Condition GetCondition(Instr instr); 12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static bool IsBranch(Instr instr); 12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static int GetBranchOffset(Instr instr); 12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static bool IsLdrRegisterImmediate(Instr instr); 12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static int GetLdrRegisterImmediateOffset(Instr instr); 12476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset); 124850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen static bool IsStrRegisterImmediate(Instr instr); 124950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen static Instr SetStrRegisterImmediateOffset(Instr instr, int offset); 125050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen static bool IsAddRegisterImmediate(Instr instr); 125150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen static Instr SetAddRegisterImmediateOffset(Instr instr, int offset); 1252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke static Register GetRd(Instr instr); 12531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static Register GetRn(Instr instr); 12541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static Register GetRm(Instr instr); 1255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke static bool IsPush(Instr instr); 1256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke static bool IsPop(Instr instr); 1257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke static bool IsStrRegFpOffset(Instr instr); 1258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke static bool IsLdrRegFpOffset(Instr instr); 1259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke static bool IsStrRegFpNegOffset(Instr instr); 1260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke static bool IsLdrRegFpNegOffset(Instr instr); 12618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang static bool IsLdrPcImmediateOffset(Instr instr); 12621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static bool IsTstImmediate(Instr instr); 12631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static bool IsCmpRegister(Instr instr); 12641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static bool IsCmpImmediate(Instr instr); 12651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static Register GetCmpImmediateRegister(Instr instr); 12661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static int GetCmpImmediateRawImmediate(Instr instr); 12678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang static bool IsNop(Instr instr, int type = NON_MARKING_NOP); 12686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Constants in pools are accessed via pc relative addressing, which can 1270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // reach +/-4KB thereby defining a maximum distance between the instruction 12713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // and the accessed constant. 12723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const int kMaxDistToPool = 4*KB; 12733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const int kMaxNumPendingRelocInfo = kMaxDistToPool/kInstrSize; 1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 12753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Postpone the generation of the constant pool for the specified number of 12763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // instructions. 12773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void BlockConstPoolFor(int instructions); 12783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 12793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if is time to emit a constant pool. 1280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void CheckConstPool(bool force_emit, bool require_jump); 12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block protected: 1283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Relocation for a type-recording IC has the AST id added to it. This 1284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // member variable is a way to pass the information from the call site to 1285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the relocation info. 12863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unsigned recorded_ast_id_; 1287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 128844f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool emit_debug_code() const { return emit_debug_code_; } 128944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int buffer_space() const { return reloc_info_writer.pos() - pc_; } 12916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Decode branch instruction at pos and return branch target pos 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int target_at(int pos); 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch branch instruction at pos to branch to given branch target pos 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void target_at_put(int pos, int target_pos); 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Prevent contant pool emission until EndBlockConstPool is called. 12993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Call to this function can be nested but must be followed by an equal 13003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // number of call to EndBlockConstpool. 13016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void StartBlockConstPool() { 13023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (const_pool_blocked_nesting_++ == 0) { 13033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Prevent constant pool checks happening by setting the next check to 13043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // the biggest possible offset. 13053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_buffer_check_ = kMaxInt; 13063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 13076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 13093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Resume constant pool emission. Need to be called as many time as 13103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // StartBlockConstPool to have an effect. 13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void EndBlockConstPool() { 13123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (--const_pool_blocked_nesting_ == 0) { 13133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check the constant pool hasn't been blocked for too long. 13143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT((num_pending_reloc_info_ == 0) || 13153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch (pc_offset() < (first_const_pool_use_ + kMaxDistToPool))); 13163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Two cases: 13173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // * no_const_pool_before_ >= next_buffer_check_ and the emission is 13183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // still blocked 13193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // * no_const_pool_before_ < next_buffer_check_ and the next emit will 13203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // trigger a check. 13213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_buffer_check_ = no_const_pool_before_; 13223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 13233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 13243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 13253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_const_pool_blocked() const { 13263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return (const_pool_blocked_nesting_ > 0) || 13273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch (pc_offset() < no_const_pool_before_); 13286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code buffer: 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The buffer into which code and relocation info are generated. 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* buffer_; 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int buffer_size_; 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // True if the assembler owns the buffer, false if buffer is external. 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool own_buffer_; 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int next_buffer_check_; // pc offset of next buffer check 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code generation 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The relocation writer's position is at least kGap bytes below the end of 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the generated instructions. This is so that multi-instruction sequences do 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // not have to check for overflow. The same is true for writes of large 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocation info entries. 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kGap = 32; 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* pc_; // the program counter; moves forward 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Constant pool generation 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pools are emitted in the instruction stream, preferably after unconditional 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // jumps or after returns from functions (in dead code locations). 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If a long code sequence does not contain unconditional jumps, it is 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary to emit the constant pool before the pool gets too far from the 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // location it is accessed from. In this case, we emit a jump over the emitted 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // constant pool. 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Constants in the pool may be addresses of functions that gets relocated; 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // if so, a relocation info entry is associated to the constant pool entry. 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Repeated checking whether the constant pool should be emitted is rather 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // expensive. By default we only check again once a number of instructions 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // has been generated. That also means that the sizing of the buffers is not 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // an exact science, and that we rely on some slop to not overrun buffers. 13623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const int kCheckPoolIntervalInst = 32; 13633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize; 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Average distance beetween a constant pool and the first instruction 13673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // accessing the constant pool. Longer distance should result in less I-cache 13683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // pollution. 13693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // In practice the distance will be smaller since constant pool emission is 13703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // forced after function return and sometimes after unconditional branches. 13713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const int kAvgDistToPool = kMaxDistToPool - kCheckPoolInterval; 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Emission of the constant pool may be blocked in some code sequences. 13746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int const_pool_blocked_nesting_; // Block emission if this is not zero. 13756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int no_const_pool_before_; // Block emission before this pc offset. 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Keep track of the first instruction requiring a constant pool entry 13783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // since the previous constant pool was emitted. 13793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int first_const_pool_use_; 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Relocation info generation 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Each relocation is encoded as a variable size value 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfoWriter reloc_info_writer; 13853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Relocation info records are also used during code generation as temporary 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // containers for constants and code target addresses until they are emitted 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the constant pool. These pending relocation info records are temporarily 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stored in a separate buffer until a constant pool is emitted. 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If every instruction in a long sequence is accessing the pool, we need one 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // pending relocation entry per instruction. 13923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 13933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // the buffer of pending relocation info 13943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo]; 13953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // number of pending reloc info entries in the buffer 13963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_pending_reloc_info_; 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The bound position, before this we cannot do instruction elimination. 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int last_bound_pos_; 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code emission 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void CheckBuffer(); 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GrowBuffer(); 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit(Instr x); 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction generation 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addrmod2(Instr instr, Register rd, const MemOperand& x); 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addrmod3(Instr instr, Register rd, const MemOperand& x); 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addrmod4(Instr instr, Register rn, RegList rl); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addrmod5(Instr instr, CRegister crd, const MemOperand& x); 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Labels 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void print(Label* L); 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bind_to(Label* L, int pos); 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void link_to(Label* L, Label* appendix); 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void next(Label* L); 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Record reloc info for current pc_ 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class RegExpMacroAssemblerARM; 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class RelocInfo; 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class CodePatcher; 14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block friend class BlockConstPoolScope; 14263e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 14273e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu PositionsRecorder positions_recorder_; 142844f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool emit_debug_code_; 14293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu friend class PositionsRecorder; 14303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu friend class EnsureSpace; 14313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu}; 14323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 14333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 14343e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuclass EnsureSpace BASE_EMBEDDED { 14353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu public: 14363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu explicit EnsureSpace(Assembler* assembler) { 14373e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu assembler->CheckBuffer(); 14383e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_ARM_ASSEMBLER_ARM_H_ 1445