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