1ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Copyright 2013, ARM Limited
2ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// All rights reserved.
3ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
4ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Redistribution and use in source and binary forms, with or without
5ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// modification, are permitted provided that the following conditions are met:
6ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
7ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions of source code must retain the above copyright notice,
8ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer.
9ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions in binary form must reproduce the above copyright notice,
10ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer in the documentation
11ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     and/or other materials provided with the distribution.
12ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Neither the name of ARM Limited nor the names of its contributors may be
13ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     used to endorse or promote products derived from this software without
14ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     specific prior written permission.
15ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
16ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
27ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/macro-assembler-a64.h"
28ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlnamespace vixl {
29ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
301123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid MacroAssembler::B(Label* label, BranchType type, Register reg, int bit) {
311123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((reg.Is(NoReg) || (type >= kBranchTypeFirstUsingReg)) &&
321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              ((bit == -1) || (type >= kBranchTypeFirstUsingBit)));
331123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    B(static_cast<Condition>(type), label);
351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    switch (type) {
371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      case always:        B(label);              break;
381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      case never:         break;
391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      case reg_zero:      Cbz(reg, label);       break;
401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      case reg_not_zero:  Cbnz(reg, label);      break;
411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      case reg_bit_clear: Tbz(reg, bit, label);  break;
421123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      case reg_bit_set:   Tbnz(reg, bit, label); break;
431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      default:
441123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        VIXL_UNREACHABLE();
451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
49ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::And(const Register& rd,
50ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
51f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
521123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
53f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, AND);
54f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
55f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
56f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
57f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Ands(const Register& rd,
58f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
59f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
61f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, ANDS);
62ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
63ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
64ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
65ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Tst(const Register& rn,
66ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
671123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
68f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Ands(AppropriateZeroRegFor(rn), rn, operand);
69ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
70ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
71ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
72ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Bic(const Register& rd,
73ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
74f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
751123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
76f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, BIC);
77f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
78f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
79f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
80f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Bics(const Register& rd,
81f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
82f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
84f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, BICS);
85ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
86ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
87ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
88ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Orr(const Register& rd,
89ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
90ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
911123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
92ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, ORR);
93ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
94ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
95ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
96ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Orn(const Register& rd,
97ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
98ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, ORN);
101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Eor(const Register& rd,
105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
1071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, EOR);
109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Eon(const Register& rd,
113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
1151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, EON);
117ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::LogicalMacro(const Register& rd,
121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  const Register& rn,
122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  const Operand& operand,
123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  LogicalOp op) {
1241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  UseScratchRegisterScope temps(this);
1251123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    int64_t immediate = operand.immediate();
128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    unsigned reg_size = rd.size();
1291123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(rd.Is64Bits() || is_uint32(immediate));
130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the operation is NOT, invert the operation and immediate.
132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if ((op & NOT) == NOT) {
133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      op = static_cast<LogicalOp>(op & ~NOT);
134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      immediate = ~immediate;
135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd.Is32Bits()) {
136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        immediate &= kWRegMask;
137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Special cases for all set or all clear immediates.
141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (immediate == 0) {
142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      switch (op) {
143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case AND:
144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, 0);
145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case ORR:  // Fall through.
147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case EOR:
148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, rn);
149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case ANDS:  // Fall through.
151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case BICS:
152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        default:
1541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl          VIXL_UNREACHABLE();
155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    } else if ((rd.Is64Bits() && (immediate == -1)) ||
1571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl               (rd.Is32Bits() && (immediate == 0xffffffff))) {
158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      switch (op) {
159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case AND:
160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, rn);
161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case ORR:
163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, immediate);
164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case EOR:
166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mvn(rd, rn);
167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case ANDS:  // Fall through.
169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case BICS:
170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        default:
1721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl          VIXL_UNREACHABLE();
173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    unsigned n, imm_s, imm_r;
177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Immediate can be encoded in the instruction.
179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Immediate can't be encoded: synthesize using move immediate.
1821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      Register temp = temps.AcquireSameSizeAs(rn);
183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      Mov(temp, immediate);
184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd.Is(sp)) {
185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // If rd is the stack pointer we cannot use it as the destination
186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // register so we use the temp register as an intermediate again.
187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        Logical(temp, rn, Operand(temp), op);
188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        Mov(sp, temp);
189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        Logical(rd, rn, Operand(temp), op);
191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
1941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(operand.reg().size() <= rd.size());
195ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub extended supports shift <= 4. We want to support exactly the
196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // same modes here.
1971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(operand.shift_amount() <= 4);
1981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(operand.reg().Is64Bits() ||
199ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
2001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    temps.Exclude(operand.reg());
2021123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register temp = temps.AcquireSameSizeAs(rn);
203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    EmitExtendShift(temp, operand.reg(), operand.extend(),
204ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                    operand.shift_amount());
205ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Logical(rd, rn, Operand(temp), op);
206ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
207ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The operand can be encoded in the instruction.
2081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(operand.IsShiftedRegister());
209ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Logical(rd, rn, operand, op);
210ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
211ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
212ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
213ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
214f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Mov(const Register& rd,
215f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand,
216f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         DiscardMoveMode discard_mode) {
2171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
218ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
219ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Call the macro assembler for generic immediates.
220ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Mov(rd, operand.immediate());
221ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
222ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit a shift instruction if moving a shifted register. This operation
223ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // could also be achieved using an orr instruction (like orn used by Mvn),
224ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // but using a shift instruction makes the disassembly clearer.
225ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    EmitShift(rd, operand.reg(), operand.shift(), operand.shift_amount());
226ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
227ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit an extend instruction if moving an extended register. This handles
228ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // extend with post-shift operations, too.
229ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    EmitExtendShift(rd, operand.reg(), operand.extend(),
230ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                    operand.shift_amount());
231ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
232ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Otherwise, emit a register move only if the registers are distinct, or
233f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // if they are not X registers.
234f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    //
235f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // Note that mov(w0, w0) is not a no-op because it clears the top word of
236f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // x0. A flag is provided (kDiscardForSameWReg) if a move between the same W
237f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // registers is not required to clear the top word of the X register. In
238f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // this case, the instruction is discarded.
239f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    //
240ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the sp is an operand, add #0 is emitted, otherwise, orr #0.
241f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    if (!rd.Is(operand.reg()) || (rd.Is32Bits() &&
242f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                                  (discard_mode == kDontDiscardForSameWReg))) {
243ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mov(rd, operand.reg());
244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
245ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
246ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
247ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
248ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
249ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Mvn(const Register& rd, const Operand& operand) {
2501123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
251ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
252ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Call the macro assembler for generic immediates.
253ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Mvn(rd, operand.immediate());
254ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
2551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    UseScratchRegisterScope temps(this);
2561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    temps.Exclude(operand.reg());
2571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
258ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit two instructions for the extend case. This differs from Mov, as
259ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the extend and invert can't be achieved in one instruction.
2601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register temp = temps.AcquireSameSizeAs(rd);
261ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    EmitExtendShift(temp, operand.reg(), operand.extend(),
262ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                    operand.shift_amount());
263ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mvn(rd, Operand(temp));
264ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
265ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Otherwise, register and shifted register cases can be handled by the
266ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // assembler directly, using orn.
267ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mvn(rd, operand);
268ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
269ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
270ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
271ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
272ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Mov(const Register& rd, uint64_t imm) {
2731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
2741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(is_uint32(imm) || is_int32(imm) || rd.Is64Bits());
275ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
276ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Immediates on Aarch64 can be produced using an initial value, and zero to
277ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // three move keep operations.
278ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //
279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Initial values can be generated with:
280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //  1. 64-bit move zero (movz).
281f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  //  2. 32-bit move inverted (movn).
282f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  //  3. 64-bit move inverted.
283ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //  4. 32-bit orr immediate.
284ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //  5. 64-bit orr immediate.
285f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  // Move-keep may then be used to modify each of the 16-bit half words.
286ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //
287ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // The code below supports all five initial value generators, and
288f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  // applying move-keep operations to move-zero and move-inverted initial
289f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  // values.
290ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
291ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = rd.size();
292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned n, imm_s, imm_r;
293ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (IsImmMovz(imm, reg_size) && !rd.IsSP()) {
294f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // Immediate can be represented in a move zero instruction. Movz can't
295f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // write to the stack pointer.
296ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    movz(rd, imm);
297ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (IsImmMovn(imm, reg_size) && !rd.IsSP()) {
298ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Immediate can be represented in a move negative instruction. Movn can't
299ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // write to the stack pointer.
300ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    movn(rd, rd.Is64Bits() ? ~imm : (~imm & kWRegMask));
301ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) {
302ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Immediate can be represented in a logical orr instruction.
3031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(!rd.IsZero());
304ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LogicalImmediate(rd, AppropriateZeroRegFor(rd), n, imm_s, imm_r, ORR);
305ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
306ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Generic immediate case. Imm will be represented by
307ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    //   [imm3, imm2, imm1, imm0], where each imm is 16 bits.
308f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // A move-zero or move-inverted is generated for the first non-zero or
309f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // non-0xffff immX, and a move-keep for subsequent non-zero immX.
310f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
311f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    uint64_t ignored_halfword = 0;
312f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    bool invert_move = false;
313f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // If the number of 0xffff halfwords is greater than the number of 0x0000
314f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // halfwords, it's more efficient to use move-inverted.
315f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    if (CountClearHalfWords(~imm, reg_size) >
316f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        CountClearHalfWords(imm, reg_size)) {
3171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      ignored_halfword = 0xffff;
318f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      invert_move = true;
319f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    }
320ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
321f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // Mov instructions can't move values into the stack pointer, so set up a
322f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // temporary register, if needed.
3231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    UseScratchRegisterScope temps(this);
3241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register temp = rd.IsSP() ? temps.AcquireSameSizeAs(rd) : rd;
325ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
326f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // Iterate through the halfwords. Use movn/movz for the first non-ignored
327f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // halfword, and movk for subsequent halfwords.
3281123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT((reg_size % 16) == 0);
329ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    bool first_mov_done = false;
330ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    for (unsigned i = 0; i < (temp.size() / 16); i++) {
3311123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      uint64_t imm16 = (imm >> (16 * i)) & 0xffff;
332f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      if (imm16 != ignored_halfword) {
333ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        if (!first_mov_done) {
334f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl          if (invert_move) {
3351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl            movn(temp, ~imm16 & 0xffff, 16 * i);
336f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl          } else {
337f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl            movz(temp, imm16, 16 * i);
338f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl          }
339ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          first_mov_done = true;
340ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else {
341ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          // Construct a wider constant.
342ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          movk(temp, imm16, 16 * i);
343ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
344ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
345ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
346ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
3471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(first_mov_done);
348f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
349f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // Move the temporary if the original destination register was the stack
350f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // pointer.
351ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (rd.IsSP()) {
352ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mov(rd, temp);
353ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
354f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
355f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
356ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
357f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
358f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlunsigned MacroAssembler::CountClearHalfWords(uint64_t imm, unsigned reg_size) {
3591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((reg_size % 8) == 0);
360f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  int count = 0;
361f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  for (unsigned i = 0; i < (reg_size / 16); i++) {
362f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    if ((imm & 0xffff) == 0) {
363f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      count++;
364f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    }
365f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    imm >>= 16;
366ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
367f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  return count;
368ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
369ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
370ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
371f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl// The movn instruction can generate immediates containing an arbitrary 16-bit
372ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// value, with remaining bits set, eg. 0x00001234, 0x0000123400000000.
373ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool MacroAssembler::IsImmMovz(uint64_t imm, unsigned reg_size) {
3741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
375f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  return CountClearHalfWords(imm, reg_size) >= ((reg_size / 16) - 1);
376ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
377ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
378ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
379ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// The movn instruction can generate immediates containing an arbitrary 16-bit
380ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// value, with remaining bits set, eg. 0xffff1234, 0xffff1234ffffffff.
381ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool MacroAssembler::IsImmMovn(uint64_t imm, unsigned reg_size) {
382ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return IsImmMovz(~imm, reg_size);
383ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
384ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
385ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
386ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ccmp(const Register& rn,
387ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const Operand& operand,
388ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          StatusFlags nzcv,
389ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          Condition cond) {
3901123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
391f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (operand.IsImmediate() && (operand.immediate() < 0)) {
392f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, -operand.immediate(), nzcv, cond, CCMN);
393f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
394f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
395f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
396ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
397ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
398ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
399ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ccmn(const Register& rn,
400ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const Operand& operand,
401ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          StatusFlags nzcv,
402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          Condition cond) {
4031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
404f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (operand.IsImmediate() && (operand.immediate() < 0)) {
405f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, -operand.immediate(), nzcv, cond, CCMP);
406f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
407f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
408f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
409ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
410ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
411ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
412ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::ConditionalCompareMacro(const Register& rn,
413ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             const Operand& operand,
414ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             StatusFlags nzcv,
415ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             Condition cond,
416ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             ConditionalCompareOp op) {
4171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
418ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((operand.IsShiftedRegister() && (operand.shift_amount() == 0)) ||
419ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      (operand.IsImmediate() && IsImmConditionalCompare(operand.immediate()))) {
420ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The immediate can be encoded in the instruction, or the operand is an
421ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // unshifted register: call the assembler.
422ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    ConditionalCompare(rn, operand, nzcv, cond, op);
423ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
4241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    UseScratchRegisterScope temps(this);
425ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The operand isn't directly supported by the instruction: perform the
426ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // operation on a temporary register.
4271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register temp = temps.AcquireSameSizeAs(rn);
428f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Mov(temp, operand);
429f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompare(rn, temp, nzcv, cond, op);
430f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
431f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
432f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
433f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
434f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Csel(const Register& rd,
435f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
436f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand,
437f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          Condition cond) {
4381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
4391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(!rd.IsZero());
4401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(!rn.IsZero());
4411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
442f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (operand.IsImmediate()) {
443f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // Immediate argument. Handle special cases of 0, 1 and -1 using zero
444f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // register.
445f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    int64_t imm = operand.immediate();
446f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Register zr = AppropriateZeroRegFor(rn);
447f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    if (imm == 0) {
448f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      csel(rd, rn, zr, cond);
449f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    } else if (imm == 1) {
450f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      csinc(rd, rn, zr, cond);
451f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    } else if (imm == -1) {
452f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      csinv(rd, rn, zr, cond);
453ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
4541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      UseScratchRegisterScope temps(this);
4551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      Register temp = temps.AcquireSameSizeAs(rn);
456f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      Mov(temp, operand.immediate());
457f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      csel(rd, rn, temp, cond);
458ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
459f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else if (operand.IsShiftedRegister() && (operand.shift_amount() == 0)) {
460f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // Unshifted register argument.
461f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    csel(rd, rn, operand.reg(), cond);
462f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
463f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // All other arguments.
4641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    UseScratchRegisterScope temps(this);
4651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register temp = temps.AcquireSameSizeAs(rn);
466f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Mov(temp, operand);
467f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    csel(rd, rn, temp, cond);
468ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
469ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
470ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
471ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
472ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Add(const Register& rd,
473ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
474f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
4751123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
476ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate() && (operand.immediate() < 0)) {
477f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    AddSubMacro(rd, rn, -operand.immediate(), LeaveFlags, SUB);
478ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
479f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    AddSubMacro(rd, rn, operand, LeaveFlags, ADD);
480f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
481f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
482f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
483f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
484f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Adds(const Register& rd,
485f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
486f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
4871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
488f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (operand.IsImmediate() && (operand.immediate() < 0)) {
489f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    AddSubMacro(rd, rn, -operand.immediate(), SetFlags, SUB);
490f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
491f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    AddSubMacro(rd, rn, operand, SetFlags, ADD);
492ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
493ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
494ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
495ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
496ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Sub(const Register& rd,
497ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
498f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
4991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
500f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (operand.IsImmediate() && (operand.immediate() < 0)) {
501f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    AddSubMacro(rd, rn, -operand.immediate(), LeaveFlags, ADD);
502f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
503f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    AddSubMacro(rd, rn, operand, LeaveFlags, SUB);
504f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
505f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
506f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
507f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
508f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Subs(const Register& rd,
509f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
510f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
5111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
512ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate() && (operand.immediate() < 0)) {
513f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    AddSubMacro(rd, rn, -operand.immediate(), SetFlags, ADD);
514ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
515f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    AddSubMacro(rd, rn, operand, SetFlags, SUB);
516ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
517ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
518ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
519ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
520ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Cmn(const Register& rn, const Operand& operand) {
5211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
522f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Adds(AppropriateZeroRegFor(rn), rn, operand);
523ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
524ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
525ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
526ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Cmp(const Register& rn, const Operand& operand) {
5271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
528f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Subs(AppropriateZeroRegFor(rn), rn, operand);
529ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
530ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
531ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
5321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid MacroAssembler::Fcmp(const FPRegister& fn, double value) {
5331123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
5341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (value != 0.0) {
5351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    UseScratchRegisterScope temps(this);
5361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    FPRegister tmp = temps.AcquireSameSizeAs(fn);
5371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Fmov(tmp, value);
5381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    fcmp(fn, tmp);
5391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
5401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    fcmp(fn, value);
5411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
5421123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
5431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
5441123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
5451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid MacroAssembler::Fmov(FPRegister fd, double imm) {
5461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
5471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (fd.Is32Bits()) {
5481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Fmov(fd, static_cast<float>(imm));
5491123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return;
5501123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
5511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
5521123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(fd.Is64Bits());
5531123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (IsImmFP64(imm)) {
5541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    fmov(fd, imm);
5551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
5561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    fmov(fd, xzr);
5571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
5581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    ldr(fd, imm);
5591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
5601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
5611123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
5621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
5631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid MacroAssembler::Fmov(FPRegister fd, float imm) {
5641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
5651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (fd.Is64Bits()) {
5661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Fmov(fd, static_cast<double>(imm));
5671123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return;
5681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
5691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
5701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(fd.Is32Bits());
5711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (IsImmFP32(imm)) {
5721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    fmov(fd, imm);
5731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
5741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    fmov(fd, wzr);
5751123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
5761123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    ldr(fd, imm);
5771123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
5781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
5791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
5801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
5811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
582ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Neg(const Register& rd,
583f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
5841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
585ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
586ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Mov(rd, -operand.immediate());
587ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
588f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Sub(rd, AppropriateZeroRegFor(rd), operand);
589ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
590ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
591ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
592ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
593f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Negs(const Register& rd,
594f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
5951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
596f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Subs(rd, AppropriateZeroRegFor(rd), operand);
597f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
598f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
599f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
600ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::AddSubMacro(const Register& rd,
601ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 const Register& rn,
602ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 const Operand& operand,
603ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 FlagsUpdate S,
604ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 AddSubOp op) {
605f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (operand.IsZero() && rd.Is(rn) && rd.Is64Bits() && rn.Is64Bits() &&
606f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      (S == LeaveFlags)) {
607f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // The instruction would be a nop. Avoid generating useless code.
608f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
609f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
610f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
611ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((operand.IsImmediate() && !IsImmAddSub(operand.immediate())) ||
612ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      (rn.IsZero() && !operand.IsShiftedRegister())                ||
613ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
6141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    UseScratchRegisterScope temps(this);
6151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register temp = temps.AcquireSameSizeAs(rn);
616ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Mov(temp, operand);
617ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSub(rd, rn, temp, S, op);
618ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
619ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSub(rd, rn, operand, S, op);
620ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
621ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
622ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
623ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
624ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Adc(const Register& rd,
625ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
626f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
6271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
628f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, ADC);
629f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
630f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
631f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
632f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Adcs(const Register& rd,
633f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
634f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
6351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
636f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, SetFlags, ADC);
637ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
638ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
639ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
640ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Sbc(const Register& rd,
641ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
642f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
6431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
644f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, SBC);
645f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
646f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
647f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
648f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Sbcs(const Register& rd,
649f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
650f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
6511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
652f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, SetFlags, SBC);
653ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
654ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
655ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
656ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ngc(const Register& rd,
657f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
6581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
659ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register zr = AppropriateZeroRegFor(rd);
660f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Sbc(rd, zr, operand);
661f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
662f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
663f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
664f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Ngcs(const Register& rd,
665f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
6661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
667f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Register zr = AppropriateZeroRegFor(rd);
668f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Sbcs(rd, zr, operand);
669ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
670ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
671ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
672ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::AddSubWithCarryMacro(const Register& rd,
673ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const Register& rn,
674ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const Operand& operand,
675ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          FlagsUpdate S,
676ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          AddSubWithCarryOp op) {
6771123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(rd.size() == rn.size());
6781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  UseScratchRegisterScope temps(this);
679ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
680ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate() ||
681ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
682ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (immediate or ROR shifted register.)
6831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register temp = temps.AcquireSameSizeAs(rn);
684ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Mov(temp, operand);
685ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
686ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
687ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (shifted register).
6881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(operand.reg().size() == rd.size());
6891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(operand.shift() != ROR);
6901123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(is_uintn(rd.size() == kXRegSize ? kXRegSizeLog2 : kWRegSizeLog2,
691ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                    operand.shift_amount()));
6921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    temps.Exclude(operand.reg());
6931123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register temp = temps.AcquireSameSizeAs(rn);
694ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    EmitShift(temp, operand.reg(), operand.shift(), operand.shift_amount());
695ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
696ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
697ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (extended register).
6981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(operand.reg().size() <= rd.size());
699ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub extended supports a shift <= 4. We want to support exactly the
700ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // same modes.
7011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(operand.shift_amount() <= 4);
7021123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(operand.reg().Is64Bits() ||
703ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
7041123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    temps.Exclude(operand.reg());
7051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register temp = temps.AcquireSameSizeAs(rn);
706ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    EmitExtendShift(temp, operand.reg(), operand.extend(),
707ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                    operand.shift_amount());
708ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
709ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
710ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The addressing mode is directly supported by the instruction.
711ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, operand, S, op);
712ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
713ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
714ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
715ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
716ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#define DEFINE_FUNCTION(FN, REGTYPE, REG, OP)                         \
717ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) {  \
718ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStoreMacro(REG, addr, OP);                                      \
719ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
720ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlLS_MACRO_LIST(DEFINE_FUNCTION)
721ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#undef DEFINE_FUNCTION
722ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
723ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::LoadStoreMacro(const CPURegister& rt,
724ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    const MemOperand& addr,
725ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    LoadStoreOp op) {
726ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t offset = addr.offset();
727ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LSDataSize size = CalcLSDataSize(op);
728ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
729ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Check if an immediate offset fits in the immediate field of the
730ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // appropriate instruction. If not, emit two instructions to perform
731ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the operation.
732ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (addr.IsImmediateOffset() && !IsImmLSScaled(offset, size) &&
733ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      !IsImmLSUnscaled(offset)) {
734ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Immediate offset that can't be encoded using unsigned or unscaled
735ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // addressing modes.
7361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    UseScratchRegisterScope temps(this);
7371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register temp = temps.AcquireSameSizeAs(addr.base());
738ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Mov(temp, addr.offset());
739ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LoadStore(rt, MemOperand(addr.base(), temp), op);
740ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (addr.IsPostIndex() && !IsImmLSUnscaled(offset)) {
741ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Post-index beyond unscaled addressing range.
742ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LoadStore(rt, MemOperand(addr.base()), op);
743ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Add(addr.base(), addr.base(), Operand(offset));
744ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (addr.IsPreIndex() && !IsImmLSUnscaled(offset)) {
745ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Pre-index beyond unscaled addressing range.
746ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Add(addr.base(), addr.base(), Operand(offset));
747ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LoadStore(rt, MemOperand(addr.base()), op);
748ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
749ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Encodable in one load/store instruction.
750ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LoadStore(rt, addr, op);
751ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
752ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
753ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
754ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
755ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Push(const CPURegister& src0, const CPURegister& src1,
756ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const CPURegister& src2, const CPURegister& src3) {
7571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
7581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
7591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(src0.IsValid());
760ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
761ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid();
762ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int size = src0.SizeInBytes();
763ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
764ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(count, size);
765ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushHelper(count, size, src0, src1, src2, src3);
766ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
767ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
768ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
769ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Pop(const CPURegister& dst0, const CPURegister& dst1,
770ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const CPURegister& dst2, const CPURegister& dst3) {
771ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // It is not valid to pop into the same register more than once in one
772ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // instruction, not even into the zero register.
7731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
7741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(!AreAliased(dst0, dst1, dst2, dst3));
7751123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
7761123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(dst0.IsValid());
777ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
778ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid();
779ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int size = dst0.SizeInBytes();
780ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
781ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPop(count, size);
782ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopHelper(count, size, dst0, dst1, dst2, dst3);
783ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
784ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
785ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
786ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushCPURegList(CPURegList registers) {
787ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int size = registers.RegisterSizeInBytes();
788ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
789ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(registers.Count(), size);
790ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push up to four registers at a time because if the current stack pointer is
791ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // sp and reg_size is 32, registers must be pushed in blocks of four in order
792ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // to maintain the 16-byte alignment for sp.
7931123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
794ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (!registers.IsEmpty()) {
795ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    int count_before = registers.Count();
796ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& src0 = registers.PopHighestIndex();
797ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& src1 = registers.PopHighestIndex();
798ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& src2 = registers.PopHighestIndex();
799ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& src3 = registers.PopHighestIndex();
800ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    int count = count_before - registers.Count();
801ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(count, size, src0, src1, src2, src3);
802ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
803ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
804ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
805ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
806ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopCPURegList(CPURegList registers) {
807ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int size = registers.RegisterSizeInBytes();
808ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
809ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPop(registers.Count(), size);
810ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Pop up to four registers at a time because if the current stack pointer is
811ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // sp and reg_size is 32, registers must be pushed in blocks of four in order
812ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // to maintain the 16-byte alignment for sp.
8131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
814ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (!registers.IsEmpty()) {
815ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    int count_before = registers.Count();
816ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst0 = registers.PopLowestIndex();
817ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst1 = registers.PopLowestIndex();
818ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst2 = registers.PopLowestIndex();
819ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst3 = registers.PopLowestIndex();
820ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    int count = count_before - registers.Count();
821ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PopHelper(count, size, dst0, dst1, dst2, dst3);
822ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
823ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
824ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
825ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
826ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushMultipleTimes(int count, Register src) {
8271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
828ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int size = src.SizeInBytes();
829ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
830ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(count, size);
831ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push up to four registers at a time if possible because if the current
832ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // stack pointer is sp and the register size is 32, registers must be pushed
833ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // in blocks of four in order to maintain the 16-byte alignment for sp.
834ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (count >= 4) {
835ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(4, size, src, src, src, src);
836ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 4;
837ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
838ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (count >= 2) {
839ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(2, size, src, src, NoReg, NoReg);
840ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 2;
841ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
842ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (count == 1) {
843ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(1, size, src, NoReg, NoReg, NoReg);
844ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 1;
845ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
8461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(count == 0);
847ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
848ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
849ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
850ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushHelper(int count, int size,
851ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src0,
852ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src1,
853ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src2,
854ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src3) {
855ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally modify scratch or debug registers.
856ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  InstructionAccurateScope scope(this);
857ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
8581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
8591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(size == src0.SizeInBytes());
860ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
861ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // When pushing multiple registers, the store order is chosen such that
862ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push(a, b) is equivalent to Push(a) followed by Push(b).
863ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (count) {
864ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 1:
8651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT(src1.IsNone() && src2.IsNone() && src3.IsNone());
866ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      str(src0, MemOperand(StackPointer(), -1 * size, PreIndex));
867ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
868ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 2:
8691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT(src2.IsNone() && src3.IsNone());
870ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src1, src0, MemOperand(StackPointer(), -2 * size, PreIndex));
871ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
872ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 3:
8731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT(src3.IsNone());
874ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src2, src1, MemOperand(StackPointer(), -3 * size, PreIndex));
875ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      str(src0, MemOperand(StackPointer(), 2 * size));
876ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
877ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 4:
878ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Skip over 4 * size, then fill in the gap. This allows four W registers
879ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // to be pushed using sp, whilst maintaining 16-byte alignment for sp at
880ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // all times.
881ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src3, src2, MemOperand(StackPointer(), -4 * size, PreIndex));
882ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src1, src0, MemOperand(StackPointer(), 2 * size));
883ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
884ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
8851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNREACHABLE();
886ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
887ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
888ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
889ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
890ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopHelper(int count, int size,
891ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst0,
892ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst1,
893ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst2,
894ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst3) {
895ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally modify scratch or debug registers.
896ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  InstructionAccurateScope scope(this);
897ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
8981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
8991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(size == dst0.SizeInBytes());
900ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
901ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // When popping multiple registers, the load order is chosen such that
902ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Pop(a, b) is equivalent to Pop(a) followed by Pop(b).
903ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (count) {
904ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 1:
9051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT(dst1.IsNone() && dst2.IsNone() && dst3.IsNone());
906ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldr(dst0, MemOperand(StackPointer(), 1 * size, PostIndex));
907ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
908ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 2:
9091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT(dst2.IsNone() && dst3.IsNone());
910ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 2 * size, PostIndex));
911ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
912ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 3:
9131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT(dst3.IsNone());
914ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldr(dst2, MemOperand(StackPointer(), 2 * size));
915ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 3 * size, PostIndex));
916ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
917ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 4:
918ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Load the higher addresses first, then load the lower addresses and skip
919ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // the whole block in the second instruction. This allows four W registers
920ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // to be popped using sp, whilst maintaining 16-byte alignment for sp at
921ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // all times.
922ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size));
923ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex));
924ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
925ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
9261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNREACHABLE();
927ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
928ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
929ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
930ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
931ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrepareForPush(int count, int size) {
932ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (sp.Is(StackPointer())) {
933ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the current stack pointer is sp, then it must be aligned to 16 bytes
934ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // on entry and the total size of the specified registers must also be a
935ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // multiple of 16 bytes.
9361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT((count * size) % 16 == 0);
937ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
938ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Even if the current stack pointer is not the system stack pointer (sp),
939ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the system stack pointer will still be modified in order to comply with
940ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // ABI rules about accessing memory below the system stack pointer.
941ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    BumpSystemStackPointer(count * size);
942ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
943ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
944ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
945ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
946ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrepareForPop(int count, int size) {
947ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  USE(count);
948ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  USE(size);
949ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (sp.Is(StackPointer())) {
950ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the current stack pointer is sp, then it must be aligned to 16 bytes
951ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // on entry and the total size of the specified registers must also be a
952ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // multiple of 16 bytes.
9531123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT((count * size) % 16 == 0);
954ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
955ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
956ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
957ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Poke(const Register& src, const Operand& offset) {
9581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
959ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset.IsImmediate()) {
9601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(offset.immediate() >= 0);
961ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
962ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
963ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Str(src, MemOperand(StackPointer(), offset));
964ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
965ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
966ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
967ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Peek(const Register& dst, const Operand& offset) {
9681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
969ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset.IsImmediate()) {
9701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(offset.immediate() >= 0);
971ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
972ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
973ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Ldr(dst, MemOperand(StackPointer(), offset));
974ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
975ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
976ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
977ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Claim(const Operand& size) {
9781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
979f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
980f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (size.IsZero()) {
981f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
982f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
983f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
984ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (size.IsImmediate()) {
9851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(size.immediate() > 0);
986ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (sp.Is(StackPointer())) {
9871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT((size.immediate() % 16) == 0);
988ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
989ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
990ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
991ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!sp.Is(StackPointer())) {
992ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    BumpSystemStackPointer(size);
993ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
994ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
995ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Sub(StackPointer(), StackPointer(), size);
996ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
997ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
998ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
999ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Drop(const Operand& size) {
10001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
1001f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1002f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (size.IsZero()) {
1003f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
1004f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1005f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1006ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (size.IsImmediate()) {
10071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(size.immediate() > 0);
1008ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (sp.Is(StackPointer())) {
10091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT((size.immediate() % 16) == 0);
1010ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1011ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1012ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1013ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Add(StackPointer(), StackPointer(), size);
1014ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1015ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1016ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1017ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushCalleeSavedRegisters() {
1018ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that the macro-assembler doesn't use any scratch registers.
1019ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  InstructionAccurateScope scope(this);
1020ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1021ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // This method must not be called unless the current stack pointer is sp.
10221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(sp.Is(StackPointer()));
1023ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1024ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MemOperand tos(sp, -2 * kXRegSizeInBytes, PreIndex);
1025ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1026ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x29, x30, tos);
1027ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x27, x28, tos);
1028ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x25, x26, tos);
1029ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x23, x24, tos);
1030ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x21, x22, tos);
1031ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x19, x20, tos);
1032ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1033ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  stp(d14, d15, tos);
1034ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  stp(d12, d13, tos);
1035ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  stp(d10, d11, tos);
1036ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  stp(d8, d9, tos);
1037ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1038ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1039ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1040ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopCalleeSavedRegisters() {
1041ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that the macro-assembler doesn't use any scratch registers.
1042ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  InstructionAccurateScope scope(this);
1043ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1044ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // This method must not be called unless the current stack pointer is sp.
10451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(sp.Is(StackPointer()));
1046ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1047ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MemOperand tos(sp, 2 * kXRegSizeInBytes, PostIndex);
1048ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1049ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  ldp(d8, d9, tos);
1050ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  ldp(d10, d11, tos);
1051ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  ldp(d12, d13, tos);
1052ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  ldp(d14, d15, tos);
1053ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1054ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x19, x20, tos);
1055ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x21, x22, tos);
1056ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x23, x24, tos);
1057ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x25, x26, tos);
1058ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x27, x28, tos);
1059ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x29, x30, tos);
1060ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1061ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1062ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::BumpSystemStackPointer(const Operand& space) {
10631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(!sp.Is(StackPointer()));
1064ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // TODO: Several callers rely on this not using scratch registers, so we use
1065ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the assembler directly here. However, this means that large immediate
1066ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // values of 'space' cannot be handled.
1067ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  InstructionAccurateScope scope(this);
1068ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  sub(sp, StackPointer(), space);
1069ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1070ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1071ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1072ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// This is the main Printf implementation. All callee-saved registers are
1073ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// preserved, but NZCV and the caller-saved registers may be clobbered.
1074ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrintfNoPreserve(const char * format,
1075ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg0,
1076ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg1,
1077ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg2,
1078ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg3) {
1079ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We cannot handle a caller-saved stack pointer. It doesn't make much sense
1080ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // in most cases anyway, so this restriction shouldn't be too serious.
10811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(!kCallerSaved.IncludesAliasOf(StackPointer()));
10821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1083ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // The provided arguments, and their proper PCS registers.
1084ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  CPURegister args[kPrintfMaxArgCount] = {arg0, arg1, arg2, arg3};
1085ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  CPURegister pcs[kPrintfMaxArgCount];
1086ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1087ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  int arg_count = kPrintfMaxArgCount;
1088ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1089ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // The PCS varargs registers for printf. Note that x0 is used for the printf
1090ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // format string.
1091ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  static const CPURegList kPCSVarargs =
1092ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      CPURegList(CPURegister::kRegister, kXRegSize, 1, arg_count);
1093ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  static const CPURegList kPCSVarargsFP =
1094ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      CPURegList(CPURegister::kFPRegister, kDRegSize, 0, arg_count - 1);
1095ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1096ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // We can use caller-saved registers as scratch values, except for the
1097ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // arguments and the PCS registers where they might need to go.
10981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  UseScratchRegisterScope temps(this);
1099ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  temps.Include(kCallerSaved);
1100ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  temps.Include(kCallerSavedFP);
1101ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  temps.Exclude(kPCSVarargs);
1102ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  temps.Exclude(kPCSVarargsFP);
11031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  temps.Exclude(arg0, arg1, arg2, arg3);
1104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1105ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Copies of the arg lists that we can iterate through.
1106ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  CPURegList pcs_varargs = kPCSVarargs;
1107ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  CPURegList pcs_varargs_fp = kPCSVarargsFP;
1108ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1109ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Place the arguments. There are lots of clever tricks and optimizations we
1110ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // could use here, but Printf is a debug tool so instead we just try to keep
1111ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // it simple: Move each input that isn't already in the right place to a
1112ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // scratch register, then move everything back.
1113ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  for (unsigned i = 0; i < kPrintfMaxArgCount; i++) {
1114ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Work out the proper PCS register for this argument.
1115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (args[i].IsRegister()) {
1116ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      pcs[i] = pcs_varargs.PopLowestIndex().X();
1117ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // We might only need a W register here. We need to know the size of the
1118ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // argument so we can properly encode it for the simulator call.
1119ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (args[i].Is32Bits()) pcs[i] = pcs[i].W();
1120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else if (args[i].IsFPRegister()) {
1121ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // In C, floats are always cast to doubles for varargs calls.
1122ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      pcs[i] = pcs_varargs_fp.PopLowestIndex().D();
1123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
1124ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      VIXL_ASSERT(args[i].IsNone());
1125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      arg_count = i;
1126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1129ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // If the argument is already in the right place, leave it where it is.
1130ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    if (args[i].Aliases(pcs[i])) continue;
1131ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1132ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Otherwise, if the argument is in a PCS argument register, allocate an
1133ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // appropriate scratch register and then move it out of the way.
1134ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    if (kPCSVarargs.IncludesAliasOf(args[i]) ||
1135ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        kPCSVarargsFP.IncludesAliasOf(args[i])) {
1136ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (args[i].IsRegister()) {
1137ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        Register old_arg = Register(args[i]);
1138ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        Register new_arg = temps.AcquireSameSizeAs(old_arg);
1139ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        Mov(new_arg, old_arg);
1140ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        args[i] = new_arg;
1141ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      } else {
1142ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        FPRegister old_arg = FPRegister(args[i]);
1143ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        FPRegister new_arg = temps.AcquireSameSizeAs(old_arg);
1144ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        Fmov(new_arg, old_arg);
1145ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        args[i] = new_arg;
1146ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      }
1147ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
1148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1150ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Do a second pass to move values into their final positions and perform any
1151ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // conversions that may be required.
1152ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  for (int i = 0; i < arg_count; i++) {
1153ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_ASSERT(pcs[i].type() == args[i].type());
1154ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    if (pcs[i].IsRegister()) {
1155ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      Mov(Register(pcs[i]), Register(args[i]), kDiscardForSameWReg);
1156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
1157ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      VIXL_ASSERT(pcs[i].IsFPRegister());
1158ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (pcs[i].size() == args[i].size()) {
1159ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        Fmov(FPRegister(pcs[i]), FPRegister(args[i]));
1160ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      } else {
1161ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        Fcvt(FPRegister(pcs[i]), FPRegister(args[i]));
1162ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      }
1163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Load the format string into x0, as per the procedure-call standard.
1167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //
1168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // To make the code as portable as possible, the format string is encoded
1169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // directly in the instruction stream. It might be cleaner to encode it in a
1170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // literal pool, but since Printf is usually used for debugging, it is
1171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // beneficial for it to be minimally dependent on other features.
1172ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  temps.Exclude(x0);
1173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Label format_address;
1174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Adr(x0, &format_address);
1175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Emit the format string directly in the instruction stream.
1177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  { BlockLiteralPoolScope scope(this);
1178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Label after_data;
1179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    B(&after_data);
1180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bind(&format_address);
1181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    EmitStringData(format);
1182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Unreachable();
1183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bind(&after_data);
1184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We don't pass any arguments on the stack, but we still need to align the C
1187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // stack pointer to a 16-byte boundary for PCS compliance.
1188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!sp.Is(StackPointer())) {
1189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bic(sp, StackPointer(), 0xf);
1190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Actually call printf. This part needs special handling for the simulator,
1193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // since the system printf function will use a different instruction set and
1194ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the procedure-call standard will not be compatible.
1195ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#ifdef USE_SIMULATOR
1196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  { InstructionAccurateScope scope(this, kPrintfLength / kInstructionSize);
1197ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    hlt(kPrintfOpcode);
1198ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    dc32(arg_count);          // kPrintfArgCountOffset
1199ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1200ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Determine the argument pattern.
1201ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    uint32_t arg_pattern_list = 0;
1202ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    for (int i = 0; i < arg_count; i++) {
1203ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      uint32_t arg_pattern;
1204ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (pcs[i].IsRegister()) {
1205ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        arg_pattern = pcs[i].Is32Bits() ? kPrintfArgW : kPrintfArgX;
1206ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      } else {
1207ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        VIXL_ASSERT(pcs[i].Is64Bits());
1208ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        arg_pattern = kPrintfArgD;
1209ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      }
1210ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      VIXL_ASSERT(arg_pattern < (1 << kPrintfArgPatternBits));
1211ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i));
1212ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
1213ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    dc32(arg_pattern_list);   // kPrintfArgPatternListOffset
1214ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1215ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#else
12161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register tmp = temps.AcquireX();
12171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Mov(tmp, reinterpret_cast<uintptr_t>(printf));
12181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Blr(tmp);
1219ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#endif
1220ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1221ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1222ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1223ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Printf(const char * format,
1224ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                            CPURegister arg0,
1225ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                            CPURegister arg1,
1226ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                            CPURegister arg2,
1227ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                            CPURegister arg3) {
1228ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // We can only print sp if it is the current stack pointer.
1229ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  if (!sp.Is(StackPointer())) {
1230ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_ASSERT(!sp.Aliases(arg0));
1231ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_ASSERT(!sp.Aliases(arg1));
1232ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_ASSERT(!sp.Aliases(arg2));
1233ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_ASSERT(!sp.Aliases(arg3));
1234ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  }
1235ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
12361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // Make sure that the macro assembler doesn't try to use any of our arguments
12371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // as scratch registers.
12381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  UseScratchRegisterScope exclude_all(this);
12391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  exclude_all.ExcludeAll();
12401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1241ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Preserve all caller-saved registers as well as NZCV.
1242ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // If sp is the stack pointer, PushCPURegList asserts that the size of each
1243ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // list is a multiple of 16 bytes.
1244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushCPURegList(kCallerSaved);
1245ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushCPURegList(kCallerSavedFP);
1246ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
12471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  { UseScratchRegisterScope temps(this);
12481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // We can use caller-saved registers as scratch values (except for argN).
1249ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    temps.Include(kCallerSaved);
1250ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    temps.Include(kCallerSavedFP);
12511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    temps.Exclude(arg0, arg1, arg2, arg3);
12521123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1253ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // If any of the arguments are the current stack pointer, allocate a new
1254ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // register for them, and adjust the value to compensate for pushing the
1255ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // caller-saved registers.
1256ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    bool arg0_sp = StackPointer().Aliases(arg0);
1257ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    bool arg1_sp = StackPointer().Aliases(arg1);
1258ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    bool arg2_sp = StackPointer().Aliases(arg2);
1259ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    bool arg3_sp = StackPointer().Aliases(arg3);
1260ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    if (arg0_sp || arg1_sp || arg2_sp || arg3_sp) {
1261ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // Allocate a register to hold the original stack pointer value, to pass
1262ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // to PrintfNoPreserve as an argument.
1263ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      Register arg_sp = temps.AcquireX();
1264ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      Add(arg_sp, StackPointer(),
1265ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl          kCallerSaved.TotalSizeInBytes() + kCallerSavedFP.TotalSizeInBytes());
1266ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (arg0_sp) arg0 = Register(arg_sp.code(), arg0.size());
1267ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (arg1_sp) arg1 = Register(arg_sp.code(), arg1.size());
1268ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (arg2_sp) arg2 = Register(arg_sp.code(), arg2.size());
1269ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (arg3_sp) arg3 = Register(arg_sp.code(), arg3.size());
1270ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
1271ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
12721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Preserve NZCV.
12731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Register tmp = temps.AcquireX();
12741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Mrs(tmp, NZCV);
12751123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Push(tmp, xzr);
1276ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    temps.Release(tmp);
12771123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
12781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    PrintfNoPreserve(format, arg0, arg1, arg2, arg3);
12791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1280ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Restore NZCV.
1281ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    tmp = temps.AcquireX();
12821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Pop(xzr, tmp);
12831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    Msr(NZCV, tmp);
1284ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    temps.Release(tmp);
12851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
1286ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1287ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopCPURegList(kCallerSavedFP);
1288ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopCPURegList(kCallerSaved);
1289ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1290ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1291ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Trace(TraceParameters parameters, TraceCommand command) {
12921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
1293ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1294ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#ifdef USE_SIMULATOR
1295ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // The arguments to the trace pseudo instruction need to be contiguous in
1296ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // memory, so make sure we don't try to emit a literal pool.
1297ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  InstructionAccurateScope scope(this, kTraceLength / kInstructionSize);
1298ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1299ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Label start;
1300ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bind(&start);
1301ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1302ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Refer to instructions-a64.h for a description of the marker and its
1303ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // arguments.
1304ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  hlt(kTraceOpcode);
1305ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
13061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceParamsOffset);
1307ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  dc32(parameters);
1308ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
13091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceCommandOffset);
1310ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  dc32(command);
1311ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#else
1312ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Emit nothing on real hardware.
1313ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  USE(parameters);
1314ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  USE(command);
1315ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#endif
1316ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1317ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1318ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1319ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Log(TraceParameters parameters) {
13201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(allow_macro_instructions_);
1321ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1322ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#ifdef USE_SIMULATOR
1323ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // The arguments to the log pseudo instruction need to be contiguous in
1324ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // memory, so make sure we don't try to emit a literal pool.
1325ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  InstructionAccurateScope scope(this, kLogLength / kInstructionSize);
1326ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1327ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Label start;
1328ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bind(&start);
1329ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1330ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Refer to instructions-a64.h for a description of the marker and its
1331ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // arguments.
1332ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  hlt(kLogOpcode);
1333ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
13341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kLogParamsOffset);
1335ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  dc32(parameters);
1336ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#else
1337ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Emit nothing on real hardware.
1338ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  USE(parameters);
1339ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#endif
1340ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1341ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1342578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1343578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::EnableInstrumentation() {
13441123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(!isprint(InstrumentStateEnable));
1345578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
1346578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, InstrumentStateEnable);
1347578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1348578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1349578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1350578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::DisableInstrumentation() {
13511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(!isprint(InstrumentStateDisable));
1352578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
1353578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, InstrumentStateDisable);
1354578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1355578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1356578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1357578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
13581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(strlen(marker_name) == 2);
1359578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1360578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // We allow only printable characters in the marker names. Unprintable
1361578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // characters are reserved for controlling features of the instrumentation.
13621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(isprint(marker_name[0]) && isprint(marker_name[1]));
1363578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1364578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
1365578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, (marker_name[1] << 8) | marker_name[0]);
1366578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1367578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
13681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
13691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlUseScratchRegisterScope::~UseScratchRegisterScope() {
13701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  available_->set_list(old_available_);
13711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  availablefp_->set_list(old_availablefp_);
13721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
13731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
13741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1375ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlbool UseScratchRegisterScope::IsAvailable(const CPURegister& reg) const {
1376ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  return available_->IncludesAliasOf(reg) || availablefp_->IncludesAliasOf(reg);
1377ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
1378ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1379ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
13801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlRegister UseScratchRegisterScope::AcquireSameSizeAs(const Register& reg) {
13811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  int code = AcquireNextAvailable(available_).code();
13821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  return Register(code, reg.SizeInBits());
13831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
13841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
13851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
13861123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlFPRegister UseScratchRegisterScope::AcquireSameSizeAs(const FPRegister& reg) {
13871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  int code = AcquireNextAvailable(availablefp_).code();
13881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  return FPRegister(code, reg.SizeInBits());
13891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
13901123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
13911123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
13921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::Release(const CPURegister& reg) {
13931123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (reg.IsRegister()) {
13941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    ReleaseByCode(available_, reg.code());
13951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else if (reg.IsFPRegister()) {
13961123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    ReleaseByCode(availablefp_, reg.code());
13971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
13981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(reg.IsNone());
13991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
14001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
14011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14021123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1403ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlvoid UseScratchRegisterScope::Include(const CPURegList& list) {
1404ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  if (list.type() == CPURegister::kRegister) {
1405ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Make sure that neither sp nor xzr are included the list.
1406ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    IncludeByRegList(available_, list.list() & ~(xzr.Bit() | sp.Bit()));
1407ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  } else {
1408ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_ASSERT(list.type() == CPURegister::kFPRegister);
1409ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    IncludeByRegList(availablefp_, list.list());
1410ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  }
1411ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
1412ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1413ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
14141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::Include(const Register& reg1,
14151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const Register& reg2,
14161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const Register& reg3,
14171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const Register& reg4) {
14181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  RegList include = reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit();
14191123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // Make sure that neither sp nor xzr are included the list.
14201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  include &= ~(xzr.Bit() | sp.Bit());
14211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  IncludeByRegList(available_, include);
14231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
14241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14251123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::Include(const FPRegister& reg1,
14271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const FPRegister& reg2,
14281123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const FPRegister& reg3,
14291123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const FPRegister& reg4) {
14301123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  RegList include = reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit();
14311123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  IncludeByRegList(availablefp_, include);
14321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
14331123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1435ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlvoid UseScratchRegisterScope::Exclude(const CPURegList& list) {
1436ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  if (list.type() == CPURegister::kRegister) {
1437ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    ExcludeByRegList(available_, list.list());
1438ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  } else {
1439ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_ASSERT(list.type() == CPURegister::kFPRegister);
1440ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    ExcludeByRegList(availablefp_, list.list());
1441ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  }
1442ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
1443ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1444ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
14451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::Exclude(const Register& reg1,
14461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const Register& reg2,
14471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const Register& reg3,
14481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const Register& reg4) {
14491123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  RegList exclude = reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit();
14501123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  ExcludeByRegList(available_, exclude);
14511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
14521123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14531123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::Exclude(const FPRegister& reg1,
14551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const FPRegister& reg2,
14561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const FPRegister& reg3,
14571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const FPRegister& reg4) {
14581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  RegList excludefp = reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit();
14591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  ExcludeByRegList(availablefp_, excludefp);
14601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
14611123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::Exclude(const CPURegister& reg1,
14641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const CPURegister& reg2,
14651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const CPURegister& reg3,
14661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                      const CPURegister& reg4) {
14671123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  RegList exclude = 0;
14681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  RegList excludefp = 0;
14691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  const CPURegister regs[] = {reg1, reg2, reg3, reg4};
14711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  for (unsigned i = 0; i < (sizeof(regs) / sizeof(regs[0])); i++) {
14731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    if (regs[i].IsRegister()) {
14741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      exclude |= regs[i].Bit();
14751123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    } else if (regs[i].IsFPRegister()) {
14761123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      excludefp |= regs[i].Bit();
14771123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    } else {
14781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT(regs[i].IsNone());
14791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
14801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
14811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  ExcludeByRegList(available_, exclude);
14831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  ExcludeByRegList(availablefp_, excludefp);
14841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
14851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14861123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::ExcludeAll() {
14881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  ExcludeByRegList(available_, available_->list());
14891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  ExcludeByRegList(availablefp_, availablefp_->list());
14901123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
14911123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
14931123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlCPURegister UseScratchRegisterScope::AcquireNextAvailable(
14941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    CPURegList* available) {
14951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_CHECK(!available->IsEmpty());
14961123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  CPURegister result = available->PopLowestIndex();
14971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(!AreAliased(result, xzr, sp));
14981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  return result;
14991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
15001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
15011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
15021123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::ReleaseByCode(CPURegList* available, int code) {
15031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  ReleaseByRegList(available, static_cast<RegList>(1) << code);
15041123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
15051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
15061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
15071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::ReleaseByRegList(CPURegList* available,
15081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                               RegList regs) {
15091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  available->set_list(available->list() | regs);
15101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
15111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
15121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
15131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::IncludeByRegList(CPURegList* available,
15141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                               RegList regs) {
15151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  available->set_list(available->list() | regs);
15161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
15171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
15181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
15191123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid UseScratchRegisterScope::ExcludeByRegList(CPURegList* available,
15201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                               RegList exclude) {
15211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  available->set_list(available->list() & ~exclude);
15221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
15231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1524ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
1525