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