1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright (c) 1994-2006 Sun Microsystems Inc.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// All Rights Reserved.
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Redistribution and use in source and binary forms, with or without
5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// modification, are permitted provided that the following conditions
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// are met:
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// - Redistributions of source code must retain the above copyright notice,
9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// this list of conditions and the following disclaimer.
10958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// - Redistribution in binary form must reproduce the above copyright
12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// notice, this list of conditions and the following disclaimer in the
13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// documentation and/or other materials provided with the
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// distribution.
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// - Neither the name of Sun Microsystems or the names of contributors may
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// be used to endorse or promote products derived from this software without
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// specific prior written permission.
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// OF THE POSSIBILITY OF SUCH DAMAGE.
32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// The original source code covered by the above license above has been
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// modified significantly by Google Inc.
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// A light-weight PPC Assembler
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Generates user mode instructions for the PPC architecture up
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#ifndef V8_PPC_ASSEMBLER_PPC_H_
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define V8_PPC_ASSEMBLER_PPC_H_
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include <stdio.h>
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include <vector>
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/assembler.h"
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ppc/constants-ppc.h"
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
49109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if V8_HOST_ARCH_PPC && \
50109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    (V8_OS_AIX || (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN))
51109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define ABI_USES_FUNCTION_DESCRIPTORS 1
52109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else
53109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define ABI_USES_FUNCTION_DESCRIPTORS 0
54109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif
55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
56109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64
57109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define ABI_PASSES_HANDLES_IN_REGS 1
58109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else
59109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define ABI_PASSES_HANDLES_IN_REGS 0
60109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
62109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if !V8_HOST_ARCH_PPC || !V8_TARGET_ARCH_PPC64 || V8_TARGET_LITTLE_ENDIAN
63109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 1
64109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else
65109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 0
66109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif
67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if !V8_HOST_ARCH_PPC || (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN)
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ABI_CALL_VIA_IP 1
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#else
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ABI_CALL_VIA_IP 0
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64
75109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define ABI_TOC_REGISTER 2
76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else
77109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define ABI_TOC_REGISTER 13
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC
81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// clang-format off
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define GENERAL_REGISTERS(V)                              \
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r0)  V(sp)  V(r2)  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)  \
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r8)  V(r9)  V(r10) V(r11) V(ip) V(r13) V(r14) V(r15)  \
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r24) V(r25) V(r26) V(r27) V(r28) V(r29) V(r30) V(fp)
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if V8_EMBEDDED_CONSTANT_POOL
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ALLOCATABLE_GENERAL_REGISTERS(V)                  \
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)                       \
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r8)  V(r9)  V(r10) V(r14) V(r15)                      \
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r24) V(r25) V(r26) V(r27) V(r30)
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#else
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ALLOCATABLE_GENERAL_REGISTERS(V)                  \
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)                       \
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r8)  V(r9)  V(r10) V(r14) V(r15)                      \
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r24) V(r25) V(r26) V(r27) V(r28) V(r30)
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DOUBLE_REGISTERS(V)                               \
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
112bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#define FLOAT_REGISTERS DOUBLE_REGISTERS
113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define SIMD128_REGISTERS DOUBLE_REGISTERS
114bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)         \
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d15)               \
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// clang-format on
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// CPU Registers.
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// 1) We would prefer to use an enum, but enum values are assignment-
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// compatible with int, which has caused code-generation bugs.
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// 2) We would prefer to use a class instead of a struct but we don't like
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the register initialization to depend on the particular initialization
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// order (which appears to be different on OS X, Linux, and Windows for the
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// installed versions of C++ we tried). Using a struct permits C-style
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// "initialization". Also, the Register objects cannot be const as this
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// forces initialization stubs in MSVC, making us dependent on initialization
133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// order.
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// 3) By not using an enum, we are possibly preventing the compiler from
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// doing certain constant folds, which may significantly reduce the
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// code generated for some assembly instructions (because they boil down
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// to a few constants). If this is a problem, we could change the code
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// such that we use an enum in optimized mode, and the struct in debug
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// mode. This way we get the compile-time error checking in debug mode
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// and best performance in optimized code.
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstruct Register {
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum Code {
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define REGISTER_CODE(R) kCode_##R,
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GENERAL_REGISTERS(REGISTER_CODE)
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef REGISTER_CODE
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        kAfterLast,
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    kCode_no_reg = -1
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kNumRegisters = Code::kAfterLast;
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define REGISTER_COUNT(R) 1 +
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kNumAllocatable =
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0;
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef REGISTER_COUNT
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define REGISTER_BIT(R) 1 << kCode_##R |
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const RegList kAllocatable =
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ALLOCATABLE_GENERAL_REGISTERS(REGISTER_BIT)0;
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef REGISTER_BIT
163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static Register from_code(int code) {
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(code >= 0);
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(code < kNumRegisters);
167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register r = {code};
168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return r;
169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is(Register reg) const { return reg_code == reg.reg_code; }
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int code() const {
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(is_valid());
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reg_code;
175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int bit() const {
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(is_valid());
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 1 << reg_code;
179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void set_code(int code) {
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    reg_code = code;
182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(is_valid());
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if V8_TARGET_LITTLE_ENDIAN
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMantissaOffset = 0;
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kExponentOffset = 4;
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#else
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMantissaOffset = 4;
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kExponentOffset = 0;
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Unfortunately we can't make this private in a struct.
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int reg_code;
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochGENERAL_REGISTERS(DECLARE_REGISTER)
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef DECLARE_REGISTER
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register no_reg = {Register::kCode_no_reg};
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Aliases
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kLithiumScratch = r11;        // lithium scratch.
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kConstantPoolRegister = r28;  // Constant pool.
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kRootRegister = r29;          // Roots array pointer.
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register cp = r30;                     // JavaScript context pointer.
207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
20813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstatic const bool kSimpleFPAliasing = true;
20962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic const bool kSimdMaskRegisters = false;
21013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Double word FP register.
212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstruct DoubleRegister {
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum Code {
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define REGISTER_CODE(R) kCode_##R,
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DOUBLE_REGISTERS(REGISTER_CODE)
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef REGISTER_CODE
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        kAfterLast,
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    kCode_no_reg = -1
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kNumRegisters = Code::kAfterLast;
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMaxNumRegisters = kNumRegisters;
223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int code() const {
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(is_valid());
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reg_code;
229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int bit() const {
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(is_valid());
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 1 << reg_code;
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static DoubleRegister from_code(int code) {
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DoubleRegister r = {code};
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return r;
238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int reg_code;
241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
243bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochtypedef DoubleRegister FloatRegister;
244bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
245bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// TODO(ppc) Define SIMD registers.
246bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochtypedef DoubleRegister Simd128Register;
247bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DECLARE_REGISTER(R) \
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const DoubleRegister R = {DoubleRegister::kCode_##R};
250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochDOUBLE_REGISTERS(DECLARE_REGISTER)
251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef DECLARE_REGISTER
252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register no_dreg = {Register::kCode_no_reg};
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Aliases for double registers.  Defined using #define instead of
255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// "static const DoubleRegister&" because Clang complains otherwise when a
256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// compilation unit that includes this header doesn't use the variables.
257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define kFirstCalleeSavedDoubleReg d14
258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define kLastCalleeSavedDoubleReg d31
259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define kDoubleRegZero d14
260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define kScratchDoubleReg d13
261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister ToRegister(int num);
263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Coprocessor register
265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstruct CRegister {
266109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bool is_valid() const { return 0 <= reg_code && reg_code < 8; }
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is(CRegister creg) const { return reg_code == creg.reg_code; }
268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int code() const {
269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(is_valid());
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reg_code;
271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int bit() const {
273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(is_valid());
274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 1 << reg_code;
275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Unfortunately we can't make this private in a struct.
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int reg_code;
279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst CRegister no_creg = {-1};
283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst CRegister cr0 = {0};
285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst CRegister cr1 = {1};
286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst CRegister cr2 = {2};
287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst CRegister cr3 = {3};
288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst CRegister cr4 = {4};
289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst CRegister cr5 = {5};
290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst CRegister cr6 = {6};
291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst CRegister cr7 = {7};
292109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// -----------------------------------------------------------------------------
294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Machine instruction Operands
295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64;
298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else
299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32;
300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Class Operand represents a shifter operand in data processing instructions
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass Operand BASE_EMBEDDED {
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // immediate
306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(explicit Operand(intptr_t immediate,
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                          RelocInfo::Mode rmode = kRelocInfo_NONEPTR));
308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(static Operand Zero()) { return Operand(static_cast<intptr_t>(0)); }
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(explicit Operand(const ExternalReference& f));
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit Operand(Handle<Object> handle);
311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(explicit Operand(Smi* value));
312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // rm
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(explicit Operand(Register rm));
315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return true if this is a register operand.
317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(bool is_reg() const);
318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool must_output_reloc_info(const Assembler* assembler) const;
320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline intptr_t immediate() const {
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!rm_.is_valid());
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return imm_;
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register rm() const { return rm_; }
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register rm_;
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  intptr_t imm_;  // valid if rm_ == no_reg
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  RelocInfo::Mode rmode_;
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class Assembler;
334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class MacroAssembler;
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Class MemOperand represents a memory operand in load and store instructions
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// On PowerPC we have base register + 16bit signed value
340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Alternatively we can have a 16bit signed value immediate
341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass MemOperand BASE_EMBEDDED {
342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit MemOperand(Register rn, int32_t offset = 0);
344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit MemOperand(Register ra, Register rb);
346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int32_t offset() const {
348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(rb_.is(no_reg));
349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return offset_;
350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // PowerPC - base register
353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register ra() const {
354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!ra_.is(no_reg));
355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return ra_;
356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register rb() const {
359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(offset_ == 0 && !rb_.is(no_reg));
360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return rb_;
361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register ra_;     // base
365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int32_t offset_;  // offset
366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register rb_;     // index
367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class Assembler;
369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass DeferredRelocInfo {
373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DeferredRelocInfo() {}
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : position_(position), rmode_(rmode), data_(data) {}
377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int position() const { return position_; }
379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RelocInfo::Mode rmode() const { return rmode_; }
380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t data() const { return data_; }
381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int position_;
384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RelocInfo::Mode rmode_;
385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t data_;
386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass Assembler : public AssemblerBase {
390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Create an assembler. Instructions and relocation information are emitted
392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // into a buffer, with the instructions starting from the beginning and the
393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // relocation information starting from the end of the buffer. See CodeDesc
394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // for a detailed comment on the layout (globals.h).
395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //
396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If the provided buffer is NULL, the assembler allocates and grows its own
397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // buffer, and buffer_size determines the initial buffer size. The buffer is
398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // owned by the assembler and deallocated upon destruction of the assembler.
399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //
400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If the provided buffer is not NULL, the assembler uses the provided buffer
401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // for code generation and assumes its size to be buffer_size. If the buffer
402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // is too small, a fatal error occurs. No deallocation of the buffer is done
403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // upon destruction of the assembler.
404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Assembler(Isolate* isolate, void* buffer, int buffer_size);
405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  virtual ~Assembler() {}
406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // GetCode emits any pending (non-emitted) code and fills the descriptor
408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // desc. GetCode() is idempotent; it returns the same result if no other
409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Assembler functions are invoked in between GetCode() calls.
410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void GetCode(CodeDesc* desc);
411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Label operations & relative jumps (PPUM Appendix D)
413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //
414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Takes a branch opcode (cc) and a label (L) and generates
415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // either a backward branch or a forward branch and links it
416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // to the label fixup chain. Usage:
417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //
418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Label L;    // unbound label
419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // j(cc, &L);  // forward branch to unbound label
420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // bind(&L);   // bind label to the current pc
421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // j(cc, &L);  // backward branch to bound label
422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // bind(&L);   // illegal: a label may be bound only once
423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //
424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Note: The same Label can be used for forward and backward branches
425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // but it may be bound only once.
426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bind(Label* L);  // binds an unbound label L to the current code position
428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Links a label at the current pc_offset().  If already bound, returns the
430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // bound position.  If already linked, returns the position of the prior link.
431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Otherwise, returns the current pc_offset().
432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int link(Label* L);
433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Determines if Label is bound and near enough so that a single
435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // branch instruction can be used to reach it.
436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool is_near(Label* L, Condition cond);
437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Returns the branch offset to the given label from the current code position
439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Links the label to the current position if it is still unbound
440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int branch_offset(Label* L) {
441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (L->is_unused() && !trampoline_emitted_) {
442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TrackBranch();
443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return link(L) - pc_offset();
445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Puts a labels target address at the given position.
448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The high 8 bits are set to zero.
449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void label_at_put(Label* L, int at_offset);
450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(static bool IsConstantPoolLoadStart(
452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Address pc, ConstantPoolEntry::Access* access = nullptr));
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(static bool IsConstantPoolLoadEnd(
454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Address pc, ConstantPoolEntry::Access* access = nullptr));
455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(static int GetConstantPoolOffset(Address pc,
456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          ConstantPoolEntry::Access access,
457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          ConstantPoolEntry::Type type));
458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(void PatchConstantPoolAccessInstruction(
459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int pc_offset, int offset, ConstantPoolEntry::Access access,
460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ConstantPoolEntry::Type type));
461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return the address in the constant pool of the code target address used by
463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the branch/call instruction at pc, or the object in a mov.
464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(static Address target_constant_pool_address_at(
465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Address pc, Address constant_pool, ConstantPoolEntry::Access access,
466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ConstantPoolEntry::Type type));
467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Read/Modify the code target address in the branch/call instruction at pc.
469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(static Address target_address_at(Address pc, Address constant_pool));
470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(static void set_target_address_at(
471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address pc, Address constant_pool, Address target,
472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
47362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  INLINE(static Address target_address_at(Address pc, Code* code));
474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(static void set_target_address_at(
475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address pc, Code* code, Address target,
47662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return the code target address at a call site from the return address
479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // of that call in the instruction stream.
480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline static Address target_address_from_return_address(Address pc);
481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Given the address of the beginning of a call, return the address
483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // in the instruction stream that the call will return to.
484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(static Address return_address_from_call_start(Address pc));
485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // This sets the branch destination.
487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // This is for calls and branches within generated code.
488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline static void deserialization_set_special_target_at(
489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address instruction_payload, Code* code,
490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Address target);
491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // This sets the internal reference at the pc.
493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline static void deserialization_set_target_internal_reference_at(
494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address pc, Address target,
495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Size of an instruction.
498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kInstrSize = sizeof(Instr);
499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Here we are patching the address in the LUI/ORI instruction pair.
501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // These values are used in the serialization process and must be zero for
502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // PPC platform, as Code, Embedded Object or External-reference pointers
503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // are split across two consecutive instructions and don't exist separately
504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // in the code, so the serializer should not step forwards in memory after
505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // a target is resolved and written.
506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kSpecialTargetSize = 0;
507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Number of instructions to load an address via a mov sequence.
509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMovInstructionsConstantPool = 1;
511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kMovInstructionsNoConstantPool = 5;
512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if defined(V8_PPC_TAGGING_OPT)
513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kTaggedLoadInstructions = 1;
514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else
515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kTaggedLoadInstructions = 2;
516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else
518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMovInstructionsConstantPool = 1;
519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMovInstructionsNoConstantPool = 2;
520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kTaggedLoadInstructions = 1;
521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMovInstructions = FLAG_enable_embedded_constant_pool
523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          ? kMovInstructionsConstantPool
524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          : kMovInstructionsNoConstantPool;
525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Distance between the instruction referring to the address of the call
527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // target and the return address.
528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Call sequence is a FIXED_SEQUENCE:
530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // mov     r8, @ call address
531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // mtlr    r8
532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // blrl
533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //                      @ return address
534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kCallTargetAddressOffset =
535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      (kMovInstructions + 2) * kInstrSize;
536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Distance between start of patched debug break slot and the emitted address
538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // to jump to.
539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Patched debug break slot code is a FIXED_SEQUENCE:
540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //   mov r0, <address>
541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //   mtlr r0
542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //   blrl
543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // This is the length of the code sequence from SetDebugBreakAtSlot()
546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // FIXED_SEQUENCE
547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kDebugBreakSlotInstructions =
548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      kMovInstructionsNoConstantPool + 2;
549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kDebugBreakSlotLength =
550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      kDebugBreakSlotInstructions * kInstrSize;
551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) {
553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return ((cr.code() * CRWIDTH) + crbit);
554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // ---------------------------------------------------------------------------
557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Code generation
558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Insert the smallest number of nop instructions
560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // possible to align the pc offset to a multiple
561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // of m. m must be a power of 2 (>= 4).
562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void Align(int m);
563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Insert the smallest number of zero bytes possible to align the pc offset
564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to a mulitple of m. m must be a power of 2 (>= 2).
565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DataAlign(int m);
566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Aligns code to something that's optimal for a jump target for the platform.
567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CodeTargetAlign();
568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Branch instructions
570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bclr(BOfield bo, int condition_bit, LKBit lk);
571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void blr();
572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK);
573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void b(int branch_offset, LKBit lk);
574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bcctr(BOfield bo, int condition_bit, LKBit lk);
576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bctr();
577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bctrl();
578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Convenience branch instructions using labels
580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void b(Label* L, LKBit lk = LeaveLK) { b(branch_offset(L), lk); }
581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline CRegister cmpi_optimization(CRegister cr) {
583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check whether the branch is preceeded by an optimizable cmpi against 0.
584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // The cmpi can be deleted if it is also preceeded by an instruction that
585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // sets the register used by the compare and supports a dot form.
586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    unsigned int sradi_mask = kOpcodeMask | kExt2OpcodeVariant2Mask;
587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    unsigned int srawi_mask = kOpcodeMask | kExt2OpcodeMask;
588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int pos = pc_offset();
589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int cmpi_pos = pc_offset() - kInstrSize;
590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (cmpi_pos > 0 && optimizable_cmpi_pos_ == cmpi_pos &&
592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        cmpi_cr_.code() == cr.code() && last_bound_pos_ != pos) {
593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int xpos = cmpi_pos - kInstrSize;
594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int xinstr = instr_at(xpos);
595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int cmpi_ra = (instr_at(cmpi_pos) & 0x1f0000) >> 16;
596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // ra is at the same bit position for the three cases below.
597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int ra = (xinstr & 0x1f0000) >> 16;
598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (cmpi_ra == ra) {
599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if ((xinstr & sradi_mask) == (EXT2 | SRADIX)) {
600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cr = cr0;
601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          instr_at_put(xpos, xinstr | SetRC);
602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          pc_ -= kInstrSize;
603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if ((xinstr & srawi_mask) == (EXT2 | SRAWIX)) {
604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cr = cr0;
605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          instr_at_put(xpos, xinstr | SetRC);
606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          pc_ -= kInstrSize;
607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if ((xinstr & kOpcodeMask) == ANDIx) {
608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cr = cr0;
609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          pc_ -= kInstrSize;
610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // nothing to do here since andi. records.
611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // didn't match one of the above, must keep cmpwi.
613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return cr;
616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bc_short(Condition cond, Label* L, CRegister cr = cr7,
619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                LKBit lk = LeaveLK) {
620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(cond != al);
621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(cr.code() >= 0 && cr.code() <= 7);
622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cr = cmpi_optimization(cr);
624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int b_offset = branch_offset(L);
626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (cond) {
628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case eq:
629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk);
630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case ne:
632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk);
633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case gt:
635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        bc(b_offset, BT, encode_crbit(cr, CR_GT), lk);
636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case le:
638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        bc(b_offset, BF, encode_crbit(cr, CR_GT), lk);
639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case lt:
641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        bc(b_offset, BT, encode_crbit(cr, CR_LT), lk);
642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case ge:
644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        bc(b_offset, BF, encode_crbit(cr, CR_LT), lk);
645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case unordered:
647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        bc(b_offset, BT, encode_crbit(cr, CR_FU), lk);
648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case ordered:
650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        bc(b_offset, BF, encode_crbit(cr, CR_FU), lk);
651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case overflow:
653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        bc(b_offset, BT, encode_crbit(cr, CR_SO), lk);
654958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case nooverflow:
656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        bc(b_offset, BF, encode_crbit(cr, CR_SO), lk);
657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UNIMPLEMENTED();
660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bclr(Condition cond, CRegister cr = cr7, LKBit lk = LeaveLK) {
664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(cond != al);
665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(cr.code() >= 0 && cr.code() <= 7);
666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cr = cmpi_optimization(cr);
668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (cond) {
670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case eq:
671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bclr(BT, encode_crbit(cr, CR_EQ), lk);
672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case ne:
674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bclr(BF, encode_crbit(cr, CR_EQ), lk);
675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case gt:
677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bclr(BT, encode_crbit(cr, CR_GT), lk);
678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case le:
680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bclr(BF, encode_crbit(cr, CR_GT), lk);
681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case lt:
683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bclr(BT, encode_crbit(cr, CR_LT), lk);
684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case ge:
686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bclr(BF, encode_crbit(cr, CR_LT), lk);
687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case unordered:
689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bclr(BT, encode_crbit(cr, CR_FU), lk);
690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case ordered:
692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bclr(BF, encode_crbit(cr, CR_FU), lk);
693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case overflow:
695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bclr(BT, encode_crbit(cr, CR_SO), lk);
696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case nooverflow:
698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bclr(BF, encode_crbit(cr, CR_SO), lk);
699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UNIMPLEMENTED();
702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void isel(Register rt, Register ra, Register rb, int cb);
706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void isel(Condition cond, Register rt, Register ra, Register rb,
707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            CRegister cr = cr7) {
708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(cond != al);
709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(cr.code() >= 0 && cr.code() <= 7);
710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cr = cmpi_optimization(cr);
712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (cond) {
714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case eq:
715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isel(rt, ra, rb, encode_crbit(cr, CR_EQ));
716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case ne:
718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isel(rt, rb, ra, encode_crbit(cr, CR_EQ));
719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case gt:
721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isel(rt, ra, rb, encode_crbit(cr, CR_GT));
722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case le:
724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isel(rt, rb, ra, encode_crbit(cr, CR_GT));
725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case lt:
727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isel(rt, ra, rb, encode_crbit(cr, CR_LT));
728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case ge:
730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isel(rt, rb, ra, encode_crbit(cr, CR_LT));
731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case unordered:
733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isel(rt, ra, rb, encode_crbit(cr, CR_FU));
734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case ordered:
736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isel(rt, rb, ra, encode_crbit(cr, CR_FU));
737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case overflow:
739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isel(rt, ra, rb, encode_crbit(cr, CR_SO));
740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case nooverflow:
742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isel(rt, rb, ra, encode_crbit(cr, CR_SO));
743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UNIMPLEMENTED();
746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void b(Condition cond, Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (cond == al) {
751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      b(L, lk);
752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return;
753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if ((L->is_bound() && is_near(L, cond)) || !is_trampoline_emitted()) {
756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      bc_short(cond, L, cr, lk);
757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return;
758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
760958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Label skip;
761958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Condition neg_cond = NegateCondition(cond);
762958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    bc_short(neg_cond, &skip, cr);
763958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(L, lk);
764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    bind(&skip);
765958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
766958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
767958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bne(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(ne, L, cr, lk);
769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void beq(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(eq, L, cr, lk);
772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void blt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(lt, L, cr, lk);
775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bge(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(ge, L, cr, lk);
778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ble(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(le, L, cr, lk);
781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bgt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(gt, L, cr, lk);
784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bunordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(unordered, L, cr, lk);
787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(ordered, L, cr, lk);
790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(overflow, L, cr, lk);
793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    b(nooverflow, L, cr, lk);
796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Decrement CTR; branch if CTR != 0
799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bdnz(Label* L, LKBit lk = LeaveLK) {
800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bc(branch_offset(L), DCBNZ, 0, lk);
801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Data-processing instructions
804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           RCBit r = LeaveRC);
807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
8083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void subc(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
8093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            RCBit r = LeaveRC);
8103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void sube(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
8113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            RCBit r = LeaveRC);
812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
8133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void subfic(Register dst, Register src, const Operand& imm);
814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           RCBit r = LeaveRC);
817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            RCBit r = LeaveRC);
8203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void adde(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
8213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            RCBit r = LeaveRC);
8223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void addze(Register dst, Register src1, OEBit o = LeaveOE, RCBit r = LeaveRC);
823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             RCBit r = LeaveRC);
826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mulhw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mulhwu(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void divw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            RCBit r = LeaveRC);
832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void divwu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             RCBit r = LeaveRC);
83462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void modsw(Register rt, Register ra, Register rb);
83562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void moduw(Register rt, Register ra, Register rb);
836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void addi(Register dst, Register src, const Operand& imm);
838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void addis(Register dst, Register src, const Operand& imm);
839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void addic(Register dst, Register src, const Operand& imm);
840958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void and_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
842958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void andc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
843958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void andi(Register ra, Register rs, const Operand& imm);
844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void andis(Register ra, Register rs, const Operand& imm);
845958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void nor(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
846958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void notx(Register dst, Register src, RCBit r = LeaveRC);
847958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ori(Register dst, Register src, const Operand& imm);
848958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void oris(Register dst, Register src, const Operand& imm);
849958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void orx(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void orc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
851958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void xori(Register dst, Register src, const Operand& imm);
852958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void xoris(Register ra, Register rs, const Operand& imm);
853958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void xor_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
854958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cmpi(Register src1, const Operand& src2, CRegister cr = cr7);
855958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cmpli(Register src1, const Operand& src2, CRegister cr = cr7);
856958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cmpwi(Register src1, const Operand& src2, CRegister cr = cr7);
857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cmplwi(Register src1, const Operand& src2, CRegister cr = cr7);
858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void li(Register dst, const Operand& src);
859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lis(Register dst, const Operand& imm);
860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mr(Register dst, Register src);
861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lbz(Register dst, const MemOperand& src);
863958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lbzx(Register dst, const MemOperand& src);
864958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lbzux(Register dst, const MemOperand& src);
865958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lhz(Register dst, const MemOperand& src);
866958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lhzx(Register dst, const MemOperand& src);
867958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lhzux(Register dst, const MemOperand& src);
868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void lha(Register dst, const MemOperand& src);
869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void lhax(Register dst, const MemOperand& src);
870958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lwz(Register dst, const MemOperand& src);
871958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lwzu(Register dst, const MemOperand& src);
872958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lwzx(Register dst, const MemOperand& src);
873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lwzux(Register dst, const MemOperand& src);
874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lwa(Register dst, const MemOperand& src);
875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void lwax(Register dst, const MemOperand& src);
876f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void ldbrx(Register dst, const MemOperand& src);
877f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void lwbrx(Register dst, const MemOperand& src);
878f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void lhbrx(Register dst, const MemOperand& src);
879958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stb(Register dst, const MemOperand& src);
880958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stbx(Register dst, const MemOperand& src);
881958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stbux(Register dst, const MemOperand& src);
882958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void sth(Register dst, const MemOperand& src);
883958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void sthx(Register dst, const MemOperand& src);
884958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void sthux(Register dst, const MemOperand& src);
885958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stw(Register dst, const MemOperand& src);
886958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stwu(Register dst, const MemOperand& src);
887958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stwx(Register rs, const MemOperand& src);
888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stwux(Register rs, const MemOperand& src);
889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
890958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void extsb(Register rs, Register ra, RCBit r = LeaveRC);
891958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void extsh(Register rs, Register ra, RCBit r = LeaveRC);
892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void extsw(Register rs, Register ra, RCBit r = LeaveRC);
893958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
894958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void neg(Register rt, Register ra, OEBit o = LeaveOE, RCBit c = LeaveRC);
895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
896958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
897958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ld(Register rd, const MemOperand& src);
898958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ldx(Register rd, const MemOperand& src);
899958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ldu(Register rd, const MemOperand& src);
900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ldux(Register rd, const MemOperand& src);
901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void std(Register rs, const MemOperand& src);
902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stdx(Register rs, const MemOperand& src);
903958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stdu(Register rs, const MemOperand& src);
904958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stdux(Register rs, const MemOperand& src);
905958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
906958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rldcl(Register ra, Register rs, Register rb, int mb, RCBit r = LeaveRC);
908958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC);
909958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
910958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
911958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
912958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void clrrdi(Register dst, Register src, const Operand& val,
913958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              RCBit rc = LeaveRC);
914958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void clrldi(Register dst, Register src, const Operand& val,
915958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              RCBit rc = LeaveRC);
916958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void sradi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
917958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void srd(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
918958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void sld(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
919958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void srad(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
920958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rotld(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
921958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rotldi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rotrdi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
923958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cntlzd_(Register dst, Register src, RCBit rc = LeaveRC);
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void popcntd(Register dst, Register src);
925958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mulld(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
926958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             RCBit r = LeaveRC);
927958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void divd(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
928958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            RCBit r = LeaveRC);
929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void divdu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             RCBit r = LeaveRC);
93162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void modsd(Register rt, Register ra, Register rb);
93262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void modud(Register rt, Register ra, Register rb);
933958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
935958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rlwinm(Register ra, Register rs, int sh, int mb, int me,
936958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              RCBit rc = LeaveRC);
937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rlwimi(Register ra, Register rs, int sh, int mb, int me,
938958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              RCBit rc = LeaveRC);
939958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rlwnm(Register ra, Register rs, Register rb, int mb, int me,
940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             RCBit rc = LeaveRC);
941958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
942958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
943958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void clrrwi(Register dst, Register src, const Operand& val,
944958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              RCBit rc = LeaveRC);
945958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void clrlwi(Register dst, Register src, const Operand& val,
946958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              RCBit rc = LeaveRC);
947958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void srawi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
948958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void srw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
949958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void slw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
950958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void sraw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
951958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rotlw(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
952958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rotlwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
953958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void rotrwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cntlzw_(Register dst, Register src, RCBit rc = LeaveRC);
956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void popcntw(Register dst, Register src);
957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
958958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void subi(Register dst, Register src1, const Operand& src2);
959958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
960958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cmp(Register src1, Register src2, CRegister cr = cr7);
961958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cmpl(Register src1, Register src2, CRegister cr = cr7);
962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cmpw(Register src1, Register src2, CRegister cr = cr7);
963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cmplw(Register src1, Register src2, CRegister cr = cr7);
964958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
965958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mov(Register dst, const Operand& src);
966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bitwise_mov(Register dst, intptr_t value);
967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bitwise_mov32(Register dst, int32_t value);
968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bitwise_add32(Register dst, Register src, int32_t value);
969958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
970958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load the position of the label relative to the generated code object
971958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // pointer in a register.
972958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mov_label_offset(Register dst, Label* label);
973958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // dst = base + label position + delta
975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void add_label_offset(Register dst, Register base, Label* label,
976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        int delta = 0);
977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the address of the label in a register and associate with an
979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // internal reference relocation.
980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mov_label_addr(Register dst, Label* label);
981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Emit the address of the label (i.e. a jump table entry) and associate with
983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // an internal reference relocation.
984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void emit_label_addr(Label* label);
985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Multiply instructions
987958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mul(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           RCBit r = LeaveRC);
989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Miscellaneous arithmetic instructions
991958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Special register access
993958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void crxor(int bt, int ba, int bb);
994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void crclr(int bt) { crxor(bt, bt, bt); }
995958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void creqv(int bt, int ba, int bb);
996958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void crset(int bt) { creqv(bt, bt, bt); }
997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mflr(Register dst);
998958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mtlr(Register src);
999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mtctr(Register src);
1000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mtxer(Register src);
1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mcrfs(CRegister cr, FPSCRBit bit);
1002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mfcr(Register dst);
1003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
1004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mffprd(Register dst, DoubleRegister src);
1005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mffprwz(Register dst, DoubleRegister src);
1006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mtfprd(DoubleRegister dst, Register src);
1007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mtfprwz(DoubleRegister dst, Register src);
1008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mtfprwa(DoubleRegister dst, Register src);
1009958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
1010958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1011958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void function_descriptor();
1012958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Exception-generating instructions and debugging support
1014958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stop(const char* msg, Condition cond = al,
1015958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int32_t code = kDefaultStopCode, CRegister cr = cr7);
1016958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1017958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bkpt(uint32_t imm16);  // v5 and above
1018958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void dcbf(Register ra, Register rb);
1020958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void sync();
1021958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lwsync();
1022958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void icbi(Register ra, Register rb);
1023958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void isync();
1024958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1025958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Support for floating point
1026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lfd(const DoubleRegister frt, const MemOperand& src);
1027958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lfdu(const DoubleRegister frt, const MemOperand& src);
1028958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lfdx(const DoubleRegister frt, const MemOperand& src);
1029958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lfdux(const DoubleRegister frt, const MemOperand& src);
1030958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lfs(const DoubleRegister frt, const MemOperand& src);
1031958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lfsu(const DoubleRegister frt, const MemOperand& src);
1032958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lfsx(const DoubleRegister frt, const MemOperand& src);
1033958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void lfsux(const DoubleRegister frt, const MemOperand& src);
1034958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stfd(const DoubleRegister frs, const MemOperand& src);
1035958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stfdu(const DoubleRegister frs, const MemOperand& src);
1036958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stfdx(const DoubleRegister frs, const MemOperand& src);
1037958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stfdux(const DoubleRegister frs, const MemOperand& src);
1038958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stfs(const DoubleRegister frs, const MemOperand& src);
1039958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stfsu(const DoubleRegister frs, const MemOperand& src);
1040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stfsx(const DoubleRegister frs, const MemOperand& src);
1041958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void stfsux(const DoubleRegister frs, const MemOperand& src);
1042958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1043958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fadd(const DoubleRegister frt, const DoubleRegister fra,
1044958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            const DoubleRegister frb, RCBit rc = LeaveRC);
1045958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fsub(const DoubleRegister frt, const DoubleRegister fra,
1046958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            const DoubleRegister frb, RCBit rc = LeaveRC);
1047958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fdiv(const DoubleRegister frt, const DoubleRegister fra,
1048958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            const DoubleRegister frb, RCBit rc = LeaveRC);
1049958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fmul(const DoubleRegister frt, const DoubleRegister fra,
1050958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            const DoubleRegister frc, RCBit rc = LeaveRC);
1051958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fcmpu(const DoubleRegister fra, const DoubleRegister frb,
1052958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             CRegister cr = cr7);
1053958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fmr(const DoubleRegister frt, const DoubleRegister frb,
1054958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           RCBit rc = LeaveRC);
1055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fctiwz(const DoubleRegister frt, const DoubleRegister frb);
1056958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fctiw(const DoubleRegister frt, const DoubleRegister frb);
1057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void frin(const DoubleRegister frt, const DoubleRegister frb,
1058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            RCBit rc = LeaveRC);
1059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void friz(const DoubleRegister frt, const DoubleRegister frb,
1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            RCBit rc = LeaveRC);
1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void frip(const DoubleRegister frt, const DoubleRegister frb,
1062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            RCBit rc = LeaveRC);
1063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void frim(const DoubleRegister frt, const DoubleRegister frb,
1064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            RCBit rc = LeaveRC);
1065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void frsp(const DoubleRegister frt, const DoubleRegister frb,
1066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            RCBit rc = LeaveRC);
1067958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fcfid(const DoubleRegister frt, const DoubleRegister frb,
1068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             RCBit rc = LeaveRC);
1069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void fcfidu(const DoubleRegister frt, const DoubleRegister frb,
1070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              RCBit rc = LeaveRC);
1071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void fcfidus(const DoubleRegister frt, const DoubleRegister frb,
1072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               RCBit rc = LeaveRC);
1073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void fcfids(const DoubleRegister frt, const DoubleRegister frb,
1074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              RCBit rc = LeaveRC);
1075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fctid(const DoubleRegister frt, const DoubleRegister frb,
1076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             RCBit rc = LeaveRC);
1077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fctidz(const DoubleRegister frt, const DoubleRegister frb,
1078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              RCBit rc = LeaveRC);
1079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void fctidu(const DoubleRegister frt, const DoubleRegister frb,
1080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              RCBit rc = LeaveRC);
1081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void fctiduz(const DoubleRegister frt, const DoubleRegister frb,
1082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               RCBit rc = LeaveRC);
1083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fsel(const DoubleRegister frt, const DoubleRegister fra,
1084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            const DoubleRegister frc, const DoubleRegister frb,
1085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            RCBit rc = LeaveRC);
1086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fneg(const DoubleRegister frt, const DoubleRegister frb,
1087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            RCBit rc = LeaveRC);
1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mtfsb0(FPSCRBit bit, RCBit rc = LeaveRC);
1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mtfsb1(FPSCRBit bit, RCBit rc = LeaveRC);
1090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
1091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mffs(const DoubleRegister frt, RCBit rc = LeaveRC);
1092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0,
1093958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             RCBit rc = LeaveRC);
1094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fsqrt(const DoubleRegister frt, const DoubleRegister frb,
1095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             RCBit rc = LeaveRC);
1096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fabs(const DoubleRegister frt, const DoubleRegister frb,
1097958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            RCBit rc = LeaveRC);
1098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fmadd(const DoubleRegister frt, const DoubleRegister fra,
1099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             const DoubleRegister frc, const DoubleRegister frb,
1100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             RCBit rc = LeaveRC);
1101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void fmsub(const DoubleRegister frt, const DoubleRegister fra,
1102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             const DoubleRegister frc, const DoubleRegister frb,
1103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             RCBit rc = LeaveRC);
1104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
110562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Support for VSX instructions
110662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
110762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void xsadddp(const DoubleRegister frt, const DoubleRegister fra,
110862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               const DoubleRegister frb);
110962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void xssubdp(const DoubleRegister frt, const DoubleRegister fra,
111062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               const DoubleRegister frb);
111162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void xsdivdp(const DoubleRegister frt, const DoubleRegister fra,
111262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               const DoubleRegister frb);
111362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void xsmuldp(const DoubleRegister frt, const DoubleRegister fra,
111462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               const DoubleRegister frc);
111562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Pseudo instructions
1117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Different nop operations are used by the code generator to detect certain
1119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // states of the generated code.
1120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  enum NopMarkerTypes {
1121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    NON_MARKING_NOP = 0,
1122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    GROUP_ENDING_NOP,
1123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DEBUG_BREAK_NOP,
1124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // IC markers.
1125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PROPERTY_ACCESS_INLINED,
1126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PROPERTY_ACCESS_INLINED_CONTEXT,
1127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Helper values.
1129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    LAST_CODE_MARKER,
1130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  };
1132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void nop(int type = 0);  // 0 is the default non-marking type.
1134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void push(Register src) {
1136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
1137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    stdu(src, MemOperand(sp, -kPointerSize));
1138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else
1139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    stwu(src, MemOperand(sp, -kPointerSize));
1140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
1141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void pop(Register dst) {
1144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
1145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ld(dst, MemOperand(sp));
1146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else
1147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    lwz(dst, MemOperand(sp));
1148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
1149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    addi(sp, sp, Operand(kPointerSize));
1150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void pop() { addi(sp, sp, Operand(kPointerSize)); }
1153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Jump unconditionally to given label.
1155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void jmp(Label* L) { b(L); }
1156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check the code size generated from label to here.
1158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int SizeOfCodeGeneratedSince(Label* label) {
1159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return pc_offset() - label->pos();
1160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check the number of instructions generated from label to here.
1163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int InstructionsGeneratedSince(Label* label) {
1164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return SizeOfCodeGeneratedSince(label) / kInstrSize;
1165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Class for scoping postponing the trampoline pool generation.
1168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class BlockTrampolinePoolScope {
1169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   public:
1170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
1171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      assem_->StartBlockTrampolinePool();
1172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); }
1174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   private:
1176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Assembler* assem_;
1177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
1179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  };
1180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Class for scoping disabling constant pool entry merging
1182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class BlockConstantPoolEntrySharingScope {
1183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch   public:
1184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    explicit BlockConstantPoolEntrySharingScope(Assembler* assem)
1185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        : assem_(assem) {
1186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      assem_->StartBlockConstantPoolEntrySharing();
1187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ~BlockConstantPoolEntrySharingScope() {
1189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      assem_->EndBlockConstantPoolEntrySharing();
1190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch   private:
1193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler* assem_;
1194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope);
1196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
1197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Debugging
1199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Mark address of a debug break slot.
1201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RecordDebugBreakSlot(RelocInfo::Mode mode);
1202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Record the AST id of the CallIC being compiled, so that it can be placed
1204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // in the relocation information.
1205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void SetRecordedAstId(TypeFeedbackId ast_id) {
1206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Causes compiler to fail
1207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // DCHECK(recorded_ast_id_.IsNone());
1208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    recorded_ast_id_ = ast_id;
1209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  TypeFeedbackId RecordedAstId() {
1212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Causes compiler to fail
1213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // DCHECK(!recorded_ast_id_.IsNone());
1214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return recorded_ast_id_;
1215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Record a comment relocation entry that can be used by a disassembler.
1220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Use --code-comments to enable.
1221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void RecordComment(const char* msg);
1222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Record a deoptimization reason that can be used by a log or cpu profiler.
1224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Use --trace-deopt to enable.
1225c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
1226c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                         int id);
1227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Writes a single byte or word of data in the code stream.  Used
1229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // for inline tables, e.g., jump-tables.
1230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void db(uint8_t data);
1231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void dd(uint32_t data);
1232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dq(uint64_t data);
1233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dp(uintptr_t data);
1234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Read/patch instructions
1236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instr_at_put(int pos, Instr instr) {
1238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static void instr_at_put(byte* pc, Instr instr) {
1242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    *reinterpret_cast<Instr*>(pc) = instr;
1243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static Condition GetCondition(Instr instr);
1245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsLis(Instr instr);
1247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsLi(Instr instr);
1248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsAddic(Instr instr);
1249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsOri(Instr instr);
1250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsBranch(Instr instr);
1252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static Register GetRA(Instr instr);
1253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static Register GetRB(Instr instr);
1254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
1255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3,
1256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                 Instr instr4, Instr instr5);
1257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else
1258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool Is32BitLoadIntoR12(Instr instr1, Instr instr2);
1259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
1260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsCmpRegister(Instr instr);
1262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsCmpImmediate(Instr instr);
1263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsRlwinm(Instr instr);
1264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static bool IsAndi(Instr instr);
1265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
1266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsRldicl(Instr instr);
1267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
1268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsCrSet(Instr instr);
1269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static Register GetCmpImmediateRegister(Instr instr);
1270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static int GetCmpImmediateRawImmediate(Instr instr);
1271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Postpone the generation of the trampoline pool for the specified number of
1274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // instructions.
1275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void BlockTrampolinePoolFor(int instructions);
1276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CheckTrampolinePool();
1277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // For mov.  Return the number of actual instructions required to
1279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // load the operand into a register.  This can be anywhere from
1280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // one (constant pool small section) to five instructions (full
1281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 64-bit sequence).
1282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
1283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The value returned is only valid as long as no entries are added to the
1284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // constant pool between this call and the actual instruction being emitted.
1285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int instructions_required_for_mov(Register dst, const Operand& src) const;
1286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Decide between using the constant pool vs. a mov immediate sequence.
1288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool use_constant_pool_for_mov(Register dst, const Operand& src,
1289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 bool canOptimize) const;
1290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The code currently calls CheckBuffer() too often. This has the side
1292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // effect of randomly growing the buffer in the middle of multi-instruction
1293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // sequences.
1294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //
1295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // This function allows outside callers to check and grow the buffer
1296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EnsureSpaceFor(int space_needed);
1297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int EmitConstantPool() { return constant_pool_builder_.Emit(this); }
1299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool ConstantPoolAccessIsInOverflow() const {
1301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           ConstantPoolEntry::OVERFLOWED;
1303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label* ConstantPoolPosition() {
1306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return constant_pool_builder_.EmittedPosition();
1307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EmitRelocations();
1310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier protected:
1312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Relocation for a type-recording IC has the AST id added to it.  This
1313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // member variable is a way to pass the information from the call site to
1314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the relocation info.
1315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  TypeFeedbackId recorded_ast_id_;
1316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Decode instruction(s) at pos and return backchain to previous
1320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // label reference or kEndOfChain.
1321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int target_at(int pos);
1322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Patch instruction(s) at pos to target target_pos (e.g. branch)
1324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void target_at_put(int pos, int target_pos, bool* is_branch = nullptr);
1325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Record reloc info for current pc_
1327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ConstantPoolEntry::Access ConstantPoolAddEntry(RelocInfo::Mode rmode,
1329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                 intptr_t value) {
1330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bool sharing_ok = RelocInfo::IsNone(rmode) ||
1331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      !(serializer_enabled() || rmode < RelocInfo::CELL ||
1332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        is_constant_pool_entry_sharing_blocked());
1333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok);
1334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ConstantPoolEntry::Access ConstantPoolAddEntry(double value) {
1336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return constant_pool_builder_.AddEntry(pc_offset(), value);
1337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Block the emission of the trampoline pool before pc_offset.
1340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void BlockTrampolinePoolBefore(int pc_offset) {
1341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (no_trampoline_pool_before_ < pc_offset)
1342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      no_trampoline_pool_before_ = pc_offset;
1343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; }
1346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EndBlockTrampolinePool() {
1347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int count = --trampoline_pool_blocked_nesting_;
1348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (count == 0) CheckTrampolinePoolQuick();
1349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool is_trampoline_pool_blocked() const {
1351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return trampoline_pool_blocked_nesting_ > 0;
1352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void StartBlockConstantPoolEntrySharing() {
1355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    constant_pool_entry_sharing_blocked_nesting_++;
1356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EndBlockConstantPoolEntrySharing() {
1358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    constant_pool_entry_sharing_blocked_nesting_--;
1359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_constant_pool_entry_sharing_blocked() const {
1361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return constant_pool_entry_sharing_blocked_nesting_ > 0;
1362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool has_exception() const { return internal_trampoline_exception_; }
1365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool is_trampoline_emitted() const { return trampoline_emitted_; }
1367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
1369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Code generation
1370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The relocation writer's position is at least kGap bytes below the end of
1371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the generated instructions. This is so that multi-instruction sequences do
1372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // not have to check for overflow. The same is true for writes of large
1373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // relocation info entries.
1374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kGap = 32;
1375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Repeated checking whether the trampoline pool should be emitted is rather
1377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // expensive. By default we only check again once a number of instructions
1378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // has been generated.
1379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int next_trampoline_check_;  // pc offset of next buffer check.
1380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Emission of the trampoline pool may be blocked in some code sequences.
1382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
1383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int no_trampoline_pool_before_;  // Block emission before this pc offset.
1384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Do not share constant pool entries.
1386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int constant_pool_entry_sharing_blocked_nesting_;
1387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Relocation info generation
1389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Each relocation is encoded as a variable size value
1390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  RelocInfoWriter reloc_info_writer;
1392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  std::vector<DeferredRelocInfo> relocations_;
1393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The bound position, before this we cannot do instruction elimination.
1395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int last_bound_pos_;
1396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Optimizable cmpi information.
1397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int optimizable_cmpi_pos_;
1398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CRegister cmpi_cr_;
1399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ConstantPoolBuilder constant_pool_builder_;
1401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Code emission
1403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void CheckBuffer();
1404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GrowBuffer(int needed = 0);
1405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void emit(Instr x);
1406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void TrackBranch();
1407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void UntrackBranch();
1408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void CheckTrampolinePoolQuick();
1409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Instruction generation
1411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra,
1412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              DoubleRegister frb, RCBit r);
1413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void d_form(Instr instr, Register rt, Register ra, const intptr_t val,
1414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              bool signed_disp);
1415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void x_form(Instr instr, Register ra, Register rs, Register rb, RCBit r);
1416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o,
1417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               RCBit r);
141862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void xx3_form(Instr instr, DoubleRegister t, DoubleRegister a,
141962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                DoubleRegister b);
1420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit,
1421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               RCBit r);
1422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit,
1423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                RCBit r);
1424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Labels
1426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void print(Label* L);
1427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int max_reach_from(int pos);
1428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void bind_to(Label* L, int pos);
1429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void next(Label* L);
1430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class Trampoline {
1432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   public:
1433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Trampoline() {
1434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      next_slot_ = 0;
1435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      free_slot_count_ = 0;
1436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Trampoline(int start, int slot_count) {
1438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      next_slot_ = start;
1439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      free_slot_count_ = slot_count;
1440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int take_slot() {
1442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int trampoline_slot = kInvalidSlotPos;
1443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (free_slot_count_ <= 0) {
1444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // We have run out of space on trampolines.
1445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Make sure we fail in debug mode, so we become aware of each case
1446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // when this happens.
1447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DCHECK(0);
1448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Internal exception will be caught.
1449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
1450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        trampoline_slot = next_slot_;
1451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        free_slot_count_--;
1452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        next_slot_ += kTrampolineSlotsSize;
1453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return trampoline_slot;
1455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   private:
1458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int next_slot_;
1459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int free_slot_count_;
1460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  };
1461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int32_t get_trampoline_entry();
1463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int tracked_branch_count_;
1464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If trampoline is emitted, generated code is becoming large. As
1465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // this is already a slow case which can possibly break our code
1466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // generation for the extreme case, we use this information to
1467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // trigger different mode of branch instruction generation, where we
1468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // no longer use a single branch instruction.
1469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool trampoline_emitted_;
1470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kTrampolineSlotsSize = kInstrSize;
1471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kMaxCondBranchReach = (1 << (16 - 1)) - 1;
1472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kMaxBlockTrampolineSectionSize = 64 * kInstrSize;
1473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kInvalidSlotPos = -1;
1474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Trampoline trampoline_;
1476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool internal_trampoline_exception_;
1477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class RegExpMacroAssemblerPPC;
1479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class RelocInfo;
1480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class CodePatcher;
1481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class BlockTrampolinePoolScope;
1482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class EnsureSpace;
1483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
1484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass EnsureSpace BASE_EMBEDDED {
1487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
1488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
1490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
1491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
1492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif  // V8_PPC_ASSEMBLER_PPC_H_
1494