Home | History | Annotate | Download | only in a64
      1 // Copyright 2013, ARM Limited
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are met:
      6 //
      7 //   * Redistributions of source code must retain the above copyright notice,
      8 //     this list of conditions and the following disclaimer.
      9 //   * Redistributions in binary form must reproduce the above copyright notice,
     10 //     this list of conditions and the following disclaimer in the documentation
     11 //     and/or other materials provided with the distribution.
     12 //   * Neither the name of ARM Limited nor the names of its contributors may be
     13 //     used to endorse or promote products derived from this software without
     14 //     specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 
     27 #include "a64/macro-assembler-a64.h"
     28 namespace vixl {
     29 
     30 void MacroAssembler::B(Label* label, BranchType type, Register reg, int bit) {
     31   VIXL_ASSERT((reg.Is(NoReg) || (type >= kBranchTypeFirstUsingReg)) &&
     32               ((bit == -1) || (type >= kBranchTypeFirstUsingBit)));
     33   if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
     34     B(static_cast<Condition>(type), label);
     35   } else {
     36     switch (type) {
     37       case always:        B(label);              break;
     38       case never:         break;
     39       case reg_zero:      Cbz(reg, label);       break;
     40       case reg_not_zero:  Cbnz(reg, label);      break;
     41       case reg_bit_clear: Tbz(reg, bit, label);  break;
     42       case reg_bit_set:   Tbnz(reg, bit, label); break;
     43       default:
     44         VIXL_UNREACHABLE();
     45     }
     46   }
     47 }
     48 
     49 void MacroAssembler::And(const Register& rd,
     50                          const Register& rn,
     51                          const Operand& operand) {
     52   VIXL_ASSERT(allow_macro_instructions_);
     53   LogicalMacro(rd, rn, operand, AND);
     54 }
     55 
     56 
     57 void MacroAssembler::Ands(const Register& rd,
     58                           const Register& rn,
     59                           const Operand& operand) {
     60   VIXL_ASSERT(allow_macro_instructions_);
     61   LogicalMacro(rd, rn, operand, ANDS);
     62 }
     63 
     64 
     65 void MacroAssembler::Tst(const Register& rn,
     66                          const Operand& operand) {
     67   VIXL_ASSERT(allow_macro_instructions_);
     68   Ands(AppropriateZeroRegFor(rn), rn, operand);
     69 }
     70 
     71 
     72 void MacroAssembler::Bic(const Register& rd,
     73                          const Register& rn,
     74                          const Operand& operand) {
     75   VIXL_ASSERT(allow_macro_instructions_);
     76   LogicalMacro(rd, rn, operand, BIC);
     77 }
     78 
     79 
     80 void MacroAssembler::Bics(const Register& rd,
     81                           const Register& rn,
     82                           const Operand& operand) {
     83   VIXL_ASSERT(allow_macro_instructions_);
     84   LogicalMacro(rd, rn, operand, BICS);
     85 }
     86 
     87 
     88 void MacroAssembler::Orr(const Register& rd,
     89                          const Register& rn,
     90                          const Operand& operand) {
     91   VIXL_ASSERT(allow_macro_instructions_);
     92   LogicalMacro(rd, rn, operand, ORR);
     93 }
     94 
     95 
     96 void MacroAssembler::Orn(const Register& rd,
     97                          const Register& rn,
     98                          const Operand& operand) {
     99   VIXL_ASSERT(allow_macro_instructions_);
    100   LogicalMacro(rd, rn, operand, ORN);
    101 }
    102 
    103 
    104 void MacroAssembler::Eor(const Register& rd,
    105                          const Register& rn,
    106                          const Operand& operand) {
    107   VIXL_ASSERT(allow_macro_instructions_);
    108   LogicalMacro(rd, rn, operand, EOR);
    109 }
    110 
    111 
    112 void MacroAssembler::Eon(const Register& rd,
    113                          const Register& rn,
    114                          const Operand& operand) {
    115   VIXL_ASSERT(allow_macro_instructions_);
    116   LogicalMacro(rd, rn, operand, EON);
    117 }
    118 
    119 
    120 void MacroAssembler::LogicalMacro(const Register& rd,
    121                                   const Register& rn,
    122                                   const Operand& operand,
    123                                   LogicalOp op) {
    124   UseScratchRegisterScope temps(this);
    125 
    126   if (operand.IsImmediate()) {
    127     int64_t immediate = operand.immediate();
    128     unsigned reg_size = rd.size();
    129     VIXL_ASSERT(rd.Is64Bits() || is_uint32(immediate));
    130 
    131     // If the operation is NOT, invert the operation and immediate.
    132     if ((op & NOT) == NOT) {
    133       op = static_cast<LogicalOp>(op & ~NOT);
    134       immediate = ~immediate;
    135       if (rd.Is32Bits()) {
    136         immediate &= kWRegMask;
    137       }
    138     }
    139 
    140     // Special cases for all set or all clear immediates.
    141     if (immediate == 0) {
    142       switch (op) {
    143         case AND:
    144           Mov(rd, 0);
    145           return;
    146         case ORR:  // Fall through.
    147         case EOR:
    148           Mov(rd, rn);
    149           return;
    150         case ANDS:  // Fall through.
    151         case BICS:
    152           break;
    153         default:
    154           VIXL_UNREACHABLE();
    155       }
    156     } else if ((rd.Is64Bits() && (immediate == -1)) ||
    157                (rd.Is32Bits() && (immediate == 0xffffffff))) {
    158       switch (op) {
    159         case AND:
    160           Mov(rd, rn);
    161           return;
    162         case ORR:
    163           Mov(rd, immediate);
    164           return;
    165         case EOR:
    166           Mvn(rd, rn);
    167           return;
    168         case ANDS:  // Fall through.
    169         case BICS:
    170           break;
    171         default:
    172           VIXL_UNREACHABLE();
    173       }
    174     }
    175 
    176     unsigned n, imm_s, imm_r;
    177     if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
    178       // Immediate can be encoded in the instruction.
    179       LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
    180     } else {
    181       // Immediate can't be encoded: synthesize using move immediate.
    182       Register temp = temps.AcquireSameSizeAs(rn);
    183       Mov(temp, immediate);
    184       if (rd.Is(sp)) {
    185         // If rd is the stack pointer we cannot use it as the destination
    186         // register so we use the temp register as an intermediate again.
    187         Logical(temp, rn, Operand(temp), op);
    188         Mov(sp, temp);
    189       } else {
    190         Logical(rd, rn, Operand(temp), op);
    191       }
    192     }
    193   } else if (operand.IsExtendedRegister()) {
    194     VIXL_ASSERT(operand.reg().size() <= rd.size());
    195     // Add/sub extended supports shift <= 4. We want to support exactly the
    196     // same modes here.
    197     VIXL_ASSERT(operand.shift_amount() <= 4);
    198     VIXL_ASSERT(operand.reg().Is64Bits() ||
    199            ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
    200 
    201     temps.Exclude(operand.reg());
    202     Register temp = temps.AcquireSameSizeAs(rn);
    203     EmitExtendShift(temp, operand.reg(), operand.extend(),
    204                     operand.shift_amount());
    205     Logical(rd, rn, Operand(temp), op);
    206   } else {
    207     // The operand can be encoded in the instruction.
    208     VIXL_ASSERT(operand.IsShiftedRegister());
    209     Logical(rd, rn, operand, op);
    210   }
    211 }
    212 
    213 
    214 void MacroAssembler::Mov(const Register& rd,
    215                          const Operand& operand,
    216                          DiscardMoveMode discard_mode) {
    217   VIXL_ASSERT(allow_macro_instructions_);
    218   if (operand.IsImmediate()) {
    219     // Call the macro assembler for generic immediates.
    220     Mov(rd, operand.immediate());
    221   } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
    222     // Emit a shift instruction if moving a shifted register. This operation
    223     // could also be achieved using an orr instruction (like orn used by Mvn),
    224     // but using a shift instruction makes the disassembly clearer.
    225     EmitShift(rd, operand.reg(), operand.shift(), operand.shift_amount());
    226   } else if (operand.IsExtendedRegister()) {
    227     // Emit an extend instruction if moving an extended register. This handles
    228     // extend with post-shift operations, too.
    229     EmitExtendShift(rd, operand.reg(), operand.extend(),
    230                     operand.shift_amount());
    231   } else {
    232     // Otherwise, emit a register move only if the registers are distinct, or
    233     // if they are not X registers.
    234     //
    235     // Note that mov(w0, w0) is not a no-op because it clears the top word of
    236     // x0. A flag is provided (kDiscardForSameWReg) if a move between the same W
    237     // registers is not required to clear the top word of the X register. In
    238     // this case, the instruction is discarded.
    239     //
    240     // If the sp is an operand, add #0 is emitted, otherwise, orr #0.
    241     if (!rd.Is(operand.reg()) || (rd.Is32Bits() &&
    242                                   (discard_mode == kDontDiscardForSameWReg))) {
    243       mov(rd, operand.reg());
    244     }
    245   }
    246 }
    247 
    248 
    249 void MacroAssembler::Mvn(const Register& rd, const Operand& operand) {
    250   VIXL_ASSERT(allow_macro_instructions_);
    251   if (operand.IsImmediate()) {
    252     // Call the macro assembler for generic immediates.
    253     Mvn(rd, operand.immediate());
    254   } else if (operand.IsExtendedRegister()) {
    255     UseScratchRegisterScope temps(this);
    256     temps.Exclude(operand.reg());
    257 
    258     // Emit two instructions for the extend case. This differs from Mov, as
    259     // the extend and invert can't be achieved in one instruction.
    260     Register temp = temps.AcquireSameSizeAs(rd);
    261     EmitExtendShift(temp, operand.reg(), operand.extend(),
    262                     operand.shift_amount());
    263     mvn(rd, Operand(temp));
    264   } else {
    265     // Otherwise, register and shifted register cases can be handled by the
    266     // assembler directly, using orn.
    267     mvn(rd, operand);
    268   }
    269 }
    270 
    271 
    272 void MacroAssembler::Mov(const Register& rd, uint64_t imm) {
    273   VIXL_ASSERT(allow_macro_instructions_);
    274   VIXL_ASSERT(is_uint32(imm) || is_int32(imm) || rd.Is64Bits());
    275 
    276   // Immediates on Aarch64 can be produced using an initial value, and zero to
    277   // three move keep operations.
    278   //
    279   // Initial values can be generated with:
    280   //  1. 64-bit move zero (movz).
    281   //  2. 32-bit move inverted (movn).
    282   //  3. 64-bit move inverted.
    283   //  4. 32-bit orr immediate.
    284   //  5. 64-bit orr immediate.
    285   // Move-keep may then be used to modify each of the 16-bit half words.
    286   //
    287   // The code below supports all five initial value generators, and
    288   // applying move-keep operations to move-zero and move-inverted initial
    289   // values.
    290 
    291   unsigned reg_size = rd.size();
    292   unsigned n, imm_s, imm_r;
    293   if (IsImmMovz(imm, reg_size) && !rd.IsSP()) {
    294     // Immediate can be represented in a move zero instruction. Movz can't
    295     // write to the stack pointer.
    296     movz(rd, imm);
    297   } else if (IsImmMovn(imm, reg_size) && !rd.IsSP()) {
    298     // Immediate can be represented in a move negative instruction. Movn can't
    299     // write to the stack pointer.
    300     movn(rd, rd.Is64Bits() ? ~imm : (~imm & kWRegMask));
    301   } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) {
    302     // Immediate can be represented in a logical orr instruction.
    303     VIXL_ASSERT(!rd.IsZero());
    304     LogicalImmediate(rd, AppropriateZeroRegFor(rd), n, imm_s, imm_r, ORR);
    305   } else {
    306     // Generic immediate case. Imm will be represented by
    307     //   [imm3, imm2, imm1, imm0], where each imm is 16 bits.
    308     // A move-zero or move-inverted is generated for the first non-zero or
    309     // non-0xffff immX, and a move-keep for subsequent non-zero immX.
    310 
    311     uint64_t ignored_halfword = 0;
    312     bool invert_move = false;
    313     // If the number of 0xffff halfwords is greater than the number of 0x0000
    314     // halfwords, it's more efficient to use move-inverted.
    315     if (CountClearHalfWords(~imm, reg_size) >
    316         CountClearHalfWords(imm, reg_size)) {
    317       ignored_halfword = 0xffff;
    318       invert_move = true;
    319     }
    320 
    321     // Mov instructions can't move values into the stack pointer, so set up a
    322     // temporary register, if needed.
    323     UseScratchRegisterScope temps(this);
    324     Register temp = rd.IsSP() ? temps.AcquireSameSizeAs(rd) : rd;
    325 
    326     // Iterate through the halfwords. Use movn/movz for the first non-ignored
    327     // halfword, and movk for subsequent halfwords.
    328     VIXL_ASSERT((reg_size % 16) == 0);
    329     bool first_mov_done = false;
    330     for (unsigned i = 0; i < (temp.size() / 16); i++) {
    331       uint64_t imm16 = (imm >> (16 * i)) & 0xffff;
    332       if (imm16 != ignored_halfword) {
    333         if (!first_mov_done) {
    334           if (invert_move) {
    335             movn(temp, ~imm16 & 0xffff, 16 * i);
    336           } else {
    337             movz(temp, imm16, 16 * i);
    338           }
    339           first_mov_done = true;
    340         } else {
    341           // Construct a wider constant.
    342           movk(temp, imm16, 16 * i);
    343         }
    344       }
    345     }
    346 
    347     VIXL_ASSERT(first_mov_done);
    348 
    349     // Move the temporary if the original destination register was the stack
    350     // pointer.
    351     if (rd.IsSP()) {
    352       mov(rd, temp);
    353     }
    354   }
    355 }
    356 
    357 
    358 unsigned MacroAssembler::CountClearHalfWords(uint64_t imm, unsigned reg_size) {
    359   VIXL_ASSERT((reg_size % 8) == 0);
    360   int count = 0;
    361   for (unsigned i = 0; i < (reg_size / 16); i++) {
    362     if ((imm & 0xffff) == 0) {
    363       count++;
    364     }
    365     imm >>= 16;
    366   }
    367   return count;
    368 }
    369 
    370 
    371 // The movn instruction can generate immediates containing an arbitrary 16-bit
    372 // value, with remaining bits set, eg. 0x00001234, 0x0000123400000000.
    373 bool MacroAssembler::IsImmMovz(uint64_t imm, unsigned reg_size) {
    374   VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
    375   return CountClearHalfWords(imm, reg_size) >= ((reg_size / 16) - 1);
    376 }
    377 
    378 
    379 // The movn instruction can generate immediates containing an arbitrary 16-bit
    380 // value, with remaining bits set, eg. 0xffff1234, 0xffff1234ffffffff.
    381 bool MacroAssembler::IsImmMovn(uint64_t imm, unsigned reg_size) {
    382   return IsImmMovz(~imm, reg_size);
    383 }
    384 
    385 
    386 void MacroAssembler::Ccmp(const Register& rn,
    387                           const Operand& operand,
    388                           StatusFlags nzcv,
    389                           Condition cond) {
    390   VIXL_ASSERT(allow_macro_instructions_);
    391   if (operand.IsImmediate() && (operand.immediate() < 0)) {
    392     ConditionalCompareMacro(rn, -operand.immediate(), nzcv, cond, CCMN);
    393   } else {
    394     ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
    395   }
    396 }
    397 
    398 
    399 void MacroAssembler::Ccmn(const Register& rn,
    400                           const Operand& operand,
    401                           StatusFlags nzcv,
    402                           Condition cond) {
    403   VIXL_ASSERT(allow_macro_instructions_);
    404   if (operand.IsImmediate() && (operand.immediate() < 0)) {
    405     ConditionalCompareMacro(rn, -operand.immediate(), nzcv, cond, CCMP);
    406   } else {
    407     ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
    408   }
    409 }
    410 
    411 
    412 void MacroAssembler::ConditionalCompareMacro(const Register& rn,
    413                                              const Operand& operand,
    414                                              StatusFlags nzcv,
    415                                              Condition cond,
    416                                              ConditionalCompareOp op) {
    417   VIXL_ASSERT((cond != al) && (cond != nv));
    418   if ((operand.IsShiftedRegister() && (operand.shift_amount() == 0)) ||
    419       (operand.IsImmediate() && IsImmConditionalCompare(operand.immediate()))) {
    420     // The immediate can be encoded in the instruction, or the operand is an
    421     // unshifted register: call the assembler.
    422     ConditionalCompare(rn, operand, nzcv, cond, op);
    423   } else {
    424     UseScratchRegisterScope temps(this);
    425     // The operand isn't directly supported by the instruction: perform the
    426     // operation on a temporary register.
    427     Register temp = temps.AcquireSameSizeAs(rn);
    428     Mov(temp, operand);
    429     ConditionalCompare(rn, temp, nzcv, cond, op);
    430   }
    431 }
    432 
    433 
    434 void MacroAssembler::Csel(const Register& rd,
    435                           const Register& rn,
    436                           const Operand& operand,
    437                           Condition cond) {
    438   VIXL_ASSERT(allow_macro_instructions_);
    439   VIXL_ASSERT(!rd.IsZero());
    440   VIXL_ASSERT(!rn.IsZero());
    441   VIXL_ASSERT((cond != al) && (cond != nv));
    442   if (operand.IsImmediate()) {
    443     // Immediate argument. Handle special cases of 0, 1 and -1 using zero
    444     // register.
    445     int64_t imm = operand.immediate();
    446     Register zr = AppropriateZeroRegFor(rn);
    447     if (imm == 0) {
    448       csel(rd, rn, zr, cond);
    449     } else if (imm == 1) {
    450       csinc(rd, rn, zr, cond);
    451     } else if (imm == -1) {
    452       csinv(rd, rn, zr, cond);
    453     } else {
    454       UseScratchRegisterScope temps(this);
    455       Register temp = temps.AcquireSameSizeAs(rn);
    456       Mov(temp, operand.immediate());
    457       csel(rd, rn, temp, cond);
    458     }
    459   } else if (operand.IsShiftedRegister() && (operand.shift_amount() == 0)) {
    460     // Unshifted register argument.
    461     csel(rd, rn, operand.reg(), cond);
    462   } else {
    463     // All other arguments.
    464     UseScratchRegisterScope temps(this);
    465     Register temp = temps.AcquireSameSizeAs(rn);
    466     Mov(temp, operand);
    467     csel(rd, rn, temp, cond);
    468   }
    469 }
    470 
    471 
    472 void MacroAssembler::Add(const Register& rd,
    473                          const Register& rn,
    474                          const Operand& operand) {
    475   VIXL_ASSERT(allow_macro_instructions_);
    476   if (operand.IsImmediate() && (operand.immediate() < 0)) {
    477     AddSubMacro(rd, rn, -operand.immediate(), LeaveFlags, SUB);
    478   } else {
    479     AddSubMacro(rd, rn, operand, LeaveFlags, ADD);
    480   }
    481 }
    482 
    483 
    484 void MacroAssembler::Adds(const Register& rd,
    485                           const Register& rn,
    486                           const Operand& operand) {
    487   VIXL_ASSERT(allow_macro_instructions_);
    488   if (operand.IsImmediate() && (operand.immediate() < 0)) {
    489     AddSubMacro(rd, rn, -operand.immediate(), SetFlags, SUB);
    490   } else {
    491     AddSubMacro(rd, rn, operand, SetFlags, ADD);
    492   }
    493 }
    494 
    495 
    496 void MacroAssembler::Sub(const Register& rd,
    497                          const Register& rn,
    498                          const Operand& operand) {
    499   VIXL_ASSERT(allow_macro_instructions_);
    500   if (operand.IsImmediate() && (operand.immediate() < 0)) {
    501     AddSubMacro(rd, rn, -operand.immediate(), LeaveFlags, ADD);
    502   } else {
    503     AddSubMacro(rd, rn, operand, LeaveFlags, SUB);
    504   }
    505 }
    506 
    507 
    508 void MacroAssembler::Subs(const Register& rd,
    509                           const Register& rn,
    510                           const Operand& operand) {
    511   VIXL_ASSERT(allow_macro_instructions_);
    512   if (operand.IsImmediate() && (operand.immediate() < 0)) {
    513     AddSubMacro(rd, rn, -operand.immediate(), SetFlags, ADD);
    514   } else {
    515     AddSubMacro(rd, rn, operand, SetFlags, SUB);
    516   }
    517 }
    518 
    519 
    520 void MacroAssembler::Cmn(const Register& rn, const Operand& operand) {
    521   VIXL_ASSERT(allow_macro_instructions_);
    522   Adds(AppropriateZeroRegFor(rn), rn, operand);
    523 }
    524 
    525 
    526 void MacroAssembler::Cmp(const Register& rn, const Operand& operand) {
    527   VIXL_ASSERT(allow_macro_instructions_);
    528   Subs(AppropriateZeroRegFor(rn), rn, operand);
    529 }
    530 
    531 
    532 void MacroAssembler::Fcmp(const FPRegister& fn, double value) {
    533   VIXL_ASSERT(allow_macro_instructions_);
    534   if (value != 0.0) {
    535     UseScratchRegisterScope temps(this);
    536     FPRegister tmp = temps.AcquireSameSizeAs(fn);
    537     Fmov(tmp, value);
    538     fcmp(fn, tmp);
    539   } else {
    540     fcmp(fn, value);
    541   }
    542 }
    543 
    544 
    545 void MacroAssembler::Fmov(FPRegister fd, double imm) {
    546   VIXL_ASSERT(allow_macro_instructions_);
    547   if (fd.Is32Bits()) {
    548     Fmov(fd, static_cast<float>(imm));
    549     return;
    550   }
    551 
    552   VIXL_ASSERT(fd.Is64Bits());
    553   if (IsImmFP64(imm)) {
    554     fmov(fd, imm);
    555   } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
    556     fmov(fd, xzr);
    557   } else {
    558     ldr(fd, imm);
    559   }
    560 }
    561 
    562 
    563 void MacroAssembler::Fmov(FPRegister fd, float imm) {
    564   VIXL_ASSERT(allow_macro_instructions_);
    565   if (fd.Is64Bits()) {
    566     Fmov(fd, static_cast<double>(imm));
    567     return;
    568   }
    569 
    570   VIXL_ASSERT(fd.Is32Bits());
    571   if (IsImmFP32(imm)) {
    572     fmov(fd, imm);
    573   } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
    574     fmov(fd, wzr);
    575   } else {
    576     ldr(fd, imm);
    577   }
    578 }
    579 
    580 
    581 
    582 void MacroAssembler::Neg(const Register& rd,
    583                          const Operand& operand) {
    584   VIXL_ASSERT(allow_macro_instructions_);
    585   if (operand.IsImmediate()) {
    586     Mov(rd, -operand.immediate());
    587   } else {
    588     Sub(rd, AppropriateZeroRegFor(rd), operand);
    589   }
    590 }
    591 
    592 
    593 void MacroAssembler::Negs(const Register& rd,
    594                           const Operand& operand) {
    595   VIXL_ASSERT(allow_macro_instructions_);
    596   Subs(rd, AppropriateZeroRegFor(rd), operand);
    597 }
    598 
    599 
    600 void MacroAssembler::AddSubMacro(const Register& rd,
    601                                  const Register& rn,
    602                                  const Operand& operand,
    603                                  FlagsUpdate S,
    604                                  AddSubOp op) {
    605   if (operand.IsZero() && rd.Is(rn) && rd.Is64Bits() && rn.Is64Bits() &&
    606       (S == LeaveFlags)) {
    607     // The instruction would be a nop. Avoid generating useless code.
    608     return;
    609   }
    610 
    611   if ((operand.IsImmediate() && !IsImmAddSub(operand.immediate())) ||
    612       (rn.IsZero() && !operand.IsShiftedRegister())                ||
    613       (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
    614     UseScratchRegisterScope temps(this);
    615     Register temp = temps.AcquireSameSizeAs(rn);
    616     Mov(temp, operand);
    617     AddSub(rd, rn, temp, S, op);
    618   } else {
    619     AddSub(rd, rn, operand, S, op);
    620   }
    621 }
    622 
    623 
    624 void MacroAssembler::Adc(const Register& rd,
    625                          const Register& rn,
    626                          const Operand& operand) {
    627   VIXL_ASSERT(allow_macro_instructions_);
    628   AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, ADC);
    629 }
    630 
    631 
    632 void MacroAssembler::Adcs(const Register& rd,
    633                           const Register& rn,
    634                           const Operand& operand) {
    635   VIXL_ASSERT(allow_macro_instructions_);
    636   AddSubWithCarryMacro(rd, rn, operand, SetFlags, ADC);
    637 }
    638 
    639 
    640 void MacroAssembler::Sbc(const Register& rd,
    641                          const Register& rn,
    642                          const Operand& operand) {
    643   VIXL_ASSERT(allow_macro_instructions_);
    644   AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, SBC);
    645 }
    646 
    647 
    648 void MacroAssembler::Sbcs(const Register& rd,
    649                           const Register& rn,
    650                           const Operand& operand) {
    651   VIXL_ASSERT(allow_macro_instructions_);
    652   AddSubWithCarryMacro(rd, rn, operand, SetFlags, SBC);
    653 }
    654 
    655 
    656 void MacroAssembler::Ngc(const Register& rd,
    657                          const Operand& operand) {
    658   VIXL_ASSERT(allow_macro_instructions_);
    659   Register zr = AppropriateZeroRegFor(rd);
    660   Sbc(rd, zr, operand);
    661 }
    662 
    663 
    664 void MacroAssembler::Ngcs(const Register& rd,
    665                          const Operand& operand) {
    666   VIXL_ASSERT(allow_macro_instructions_);
    667   Register zr = AppropriateZeroRegFor(rd);
    668   Sbcs(rd, zr, operand);
    669 }
    670 
    671 
    672 void MacroAssembler::AddSubWithCarryMacro(const Register& rd,
    673                                           const Register& rn,
    674                                           const Operand& operand,
    675                                           FlagsUpdate S,
    676                                           AddSubWithCarryOp op) {
    677   VIXL_ASSERT(rd.size() == rn.size());
    678   UseScratchRegisterScope temps(this);
    679 
    680   if (operand.IsImmediate() ||
    681       (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
    682     // Add/sub with carry (immediate or ROR shifted register.)
    683     Register temp = temps.AcquireSameSizeAs(rn);
    684     Mov(temp, operand);
    685     AddSubWithCarry(rd, rn, Operand(temp), S, op);
    686   } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
    687     // Add/sub with carry (shifted register).
    688     VIXL_ASSERT(operand.reg().size() == rd.size());
    689     VIXL_ASSERT(operand.shift() != ROR);
    690     VIXL_ASSERT(is_uintn(rd.size() == kXRegSize ? kXRegSizeLog2 : kWRegSizeLog2,
    691                     operand.shift_amount()));
    692     temps.Exclude(operand.reg());
    693     Register temp = temps.AcquireSameSizeAs(rn);
    694     EmitShift(temp, operand.reg(), operand.shift(), operand.shift_amount());
    695     AddSubWithCarry(rd, rn, Operand(temp), S, op);
    696   } else if (operand.IsExtendedRegister()) {
    697     // Add/sub with carry (extended register).
    698     VIXL_ASSERT(operand.reg().size() <= rd.size());
    699     // Add/sub extended supports a shift <= 4. We want to support exactly the
    700     // same modes.
    701     VIXL_ASSERT(operand.shift_amount() <= 4);
    702     VIXL_ASSERT(operand.reg().Is64Bits() ||
    703            ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
    704     temps.Exclude(operand.reg());
    705     Register temp = temps.AcquireSameSizeAs(rn);
    706     EmitExtendShift(temp, operand.reg(), operand.extend(),
    707                     operand.shift_amount());
    708     AddSubWithCarry(rd, rn, Operand(temp), S, op);
    709   } else {
    710     // The addressing mode is directly supported by the instruction.
    711     AddSubWithCarry(rd, rn, operand, S, op);
    712   }
    713 }
    714 
    715 
    716 #define DEFINE_FUNCTION(FN, REGTYPE, REG, OP)                         \
    717 void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) {  \
    718   LoadStoreMacro(REG, addr, OP);                                      \
    719 }
    720 LS_MACRO_LIST(DEFINE_FUNCTION)
    721 #undef DEFINE_FUNCTION
    722 
    723 void MacroAssembler::LoadStoreMacro(const CPURegister& rt,
    724                                     const MemOperand& addr,
    725                                     LoadStoreOp op) {
    726   int64_t offset = addr.offset();
    727   LSDataSize size = CalcLSDataSize(op);
    728 
    729   // Check if an immediate offset fits in the immediate field of the
    730   // appropriate instruction. If not, emit two instructions to perform
    731   // the operation.
    732   if (addr.IsImmediateOffset() && !IsImmLSScaled(offset, size) &&
    733       !IsImmLSUnscaled(offset)) {
    734     // Immediate offset that can't be encoded using unsigned or unscaled
    735     // addressing modes.
    736     UseScratchRegisterScope temps(this);
    737     Register temp = temps.AcquireSameSizeAs(addr.base());
    738     Mov(temp, addr.offset());
    739     LoadStore(rt, MemOperand(addr.base(), temp), op);
    740   } else if (addr.IsPostIndex() && !IsImmLSUnscaled(offset)) {
    741     // Post-index beyond unscaled addressing range.
    742     LoadStore(rt, MemOperand(addr.base()), op);
    743     Add(addr.base(), addr.base(), Operand(offset));
    744   } else if (addr.IsPreIndex() && !IsImmLSUnscaled(offset)) {
    745     // Pre-index beyond unscaled addressing range.
    746     Add(addr.base(), addr.base(), Operand(offset));
    747     LoadStore(rt, MemOperand(addr.base()), op);
    748   } else {
    749     // Encodable in one load/store instruction.
    750     LoadStore(rt, addr, op);
    751   }
    752 }
    753 
    754 
    755 void MacroAssembler::Push(const CPURegister& src0, const CPURegister& src1,
    756                           const CPURegister& src2, const CPURegister& src3) {
    757   VIXL_ASSERT(allow_macro_instructions_);
    758   VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
    759   VIXL_ASSERT(src0.IsValid());
    760 
    761   int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid();
    762   int size = src0.SizeInBytes();
    763 
    764   PrepareForPush(count, size);
    765   PushHelper(count, size, src0, src1, src2, src3);
    766 }
    767 
    768 
    769 void MacroAssembler::Pop(const CPURegister& dst0, const CPURegister& dst1,
    770                          const CPURegister& dst2, const CPURegister& dst3) {
    771   // It is not valid to pop into the same register more than once in one
    772   // instruction, not even into the zero register.
    773   VIXL_ASSERT(allow_macro_instructions_);
    774   VIXL_ASSERT(!AreAliased(dst0, dst1, dst2, dst3));
    775   VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
    776   VIXL_ASSERT(dst0.IsValid());
    777 
    778   int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid();
    779   int size = dst0.SizeInBytes();
    780 
    781   PrepareForPop(count, size);
    782   PopHelper(count, size, dst0, dst1, dst2, dst3);
    783 }
    784 
    785 
    786 void MacroAssembler::PushCPURegList(CPURegList registers) {
    787   int size = registers.RegisterSizeInBytes();
    788 
    789   PrepareForPush(registers.Count(), size);
    790   // Push up to four registers at a time because if the current stack pointer is
    791   // sp and reg_size is 32, registers must be pushed in blocks of four in order
    792   // to maintain the 16-byte alignment for sp.
    793   VIXL_ASSERT(allow_macro_instructions_);
    794   while (!registers.IsEmpty()) {
    795     int count_before = registers.Count();
    796     const CPURegister& src0 = registers.PopHighestIndex();
    797     const CPURegister& src1 = registers.PopHighestIndex();
    798     const CPURegister& src2 = registers.PopHighestIndex();
    799     const CPURegister& src3 = registers.PopHighestIndex();
    800     int count = count_before - registers.Count();
    801     PushHelper(count, size, src0, src1, src2, src3);
    802   }
    803 }
    804 
    805 
    806 void MacroAssembler::PopCPURegList(CPURegList registers) {
    807   int size = registers.RegisterSizeInBytes();
    808 
    809   PrepareForPop(registers.Count(), size);
    810   // Pop up to four registers at a time because if the current stack pointer is
    811   // sp and reg_size is 32, registers must be pushed in blocks of four in order
    812   // to maintain the 16-byte alignment for sp.
    813   VIXL_ASSERT(allow_macro_instructions_);
    814   while (!registers.IsEmpty()) {
    815     int count_before = registers.Count();
    816     const CPURegister& dst0 = registers.PopLowestIndex();
    817     const CPURegister& dst1 = registers.PopLowestIndex();
    818     const CPURegister& dst2 = registers.PopLowestIndex();
    819     const CPURegister& dst3 = registers.PopLowestIndex();
    820     int count = count_before - registers.Count();
    821     PopHelper(count, size, dst0, dst1, dst2, dst3);
    822   }
    823 }
    824 
    825 
    826 void MacroAssembler::PushMultipleTimes(int count, Register src) {
    827   VIXL_ASSERT(allow_macro_instructions_);
    828   int size = src.SizeInBytes();
    829 
    830   PrepareForPush(count, size);
    831   // Push up to four registers at a time if possible because if the current
    832   // stack pointer is sp and the register size is 32, registers must be pushed
    833   // in blocks of four in order to maintain the 16-byte alignment for sp.
    834   while (count >= 4) {
    835     PushHelper(4, size, src, src, src, src);
    836     count -= 4;
    837   }
    838   if (count >= 2) {
    839     PushHelper(2, size, src, src, NoReg, NoReg);
    840     count -= 2;
    841   }
    842   if (count == 1) {
    843     PushHelper(1, size, src, NoReg, NoReg, NoReg);
    844     count -= 1;
    845   }
    846   VIXL_ASSERT(count == 0);
    847 }
    848 
    849 
    850 void MacroAssembler::PushHelper(int count, int size,
    851                                 const CPURegister& src0,
    852                                 const CPURegister& src1,
    853                                 const CPURegister& src2,
    854                                 const CPURegister& src3) {
    855   // Ensure that we don't unintentionally modify scratch or debug registers.
    856   InstructionAccurateScope scope(this);
    857 
    858   VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
    859   VIXL_ASSERT(size == src0.SizeInBytes());
    860 
    861   // When pushing multiple registers, the store order is chosen such that
    862   // Push(a, b) is equivalent to Push(a) followed by Push(b).
    863   switch (count) {
    864     case 1:
    865       VIXL_ASSERT(src1.IsNone() && src2.IsNone() && src3.IsNone());
    866       str(src0, MemOperand(StackPointer(), -1 * size, PreIndex));
    867       break;
    868     case 2:
    869       VIXL_ASSERT(src2.IsNone() && src3.IsNone());
    870       stp(src1, src0, MemOperand(StackPointer(), -2 * size, PreIndex));
    871       break;
    872     case 3:
    873       VIXL_ASSERT(src3.IsNone());
    874       stp(src2, src1, MemOperand(StackPointer(), -3 * size, PreIndex));
    875       str(src0, MemOperand(StackPointer(), 2 * size));
    876       break;
    877     case 4:
    878       // Skip over 4 * size, then fill in the gap. This allows four W registers
    879       // to be pushed using sp, whilst maintaining 16-byte alignment for sp at
    880       // all times.
    881       stp(src3, src2, MemOperand(StackPointer(), -4 * size, PreIndex));
    882       stp(src1, src0, MemOperand(StackPointer(), 2 * size));
    883       break;
    884     default:
    885       VIXL_UNREACHABLE();
    886   }
    887 }
    888 
    889 
    890 void MacroAssembler::PopHelper(int count, int size,
    891                                const CPURegister& dst0,
    892                                const CPURegister& dst1,
    893                                const CPURegister& dst2,
    894                                const CPURegister& dst3) {
    895   // Ensure that we don't unintentionally modify scratch or debug registers.
    896   InstructionAccurateScope scope(this);
    897 
    898   VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
    899   VIXL_ASSERT(size == dst0.SizeInBytes());
    900 
    901   // When popping multiple registers, the load order is chosen such that
    902   // Pop(a, b) is equivalent to Pop(a) followed by Pop(b).
    903   switch (count) {
    904     case 1:
    905       VIXL_ASSERT(dst1.IsNone() && dst2.IsNone() && dst3.IsNone());
    906       ldr(dst0, MemOperand(StackPointer(), 1 * size, PostIndex));
    907       break;
    908     case 2:
    909       VIXL_ASSERT(dst2.IsNone() && dst3.IsNone());
    910       ldp(dst0, dst1, MemOperand(StackPointer(), 2 * size, PostIndex));
    911       break;
    912     case 3:
    913       VIXL_ASSERT(dst3.IsNone());
    914       ldr(dst2, MemOperand(StackPointer(), 2 * size));
    915       ldp(dst0, dst1, MemOperand(StackPointer(), 3 * size, PostIndex));
    916       break;
    917     case 4:
    918       // Load the higher addresses first, then load the lower addresses and skip
    919       // the whole block in the second instruction. This allows four W registers
    920       // to be popped using sp, whilst maintaining 16-byte alignment for sp at
    921       // all times.
    922       ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size));
    923       ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex));
    924       break;
    925     default:
    926       VIXL_UNREACHABLE();
    927   }
    928 }
    929 
    930 
    931 void MacroAssembler::PrepareForPush(int count, int size) {
    932   if (sp.Is(StackPointer())) {
    933     // If the current stack pointer is sp, then it must be aligned to 16 bytes
    934     // on entry and the total size of the specified registers must also be a
    935     // multiple of 16 bytes.
    936     VIXL_ASSERT((count * size) % 16 == 0);
    937   } else {
    938     // Even if the current stack pointer is not the system stack pointer (sp),
    939     // the system stack pointer will still be modified in order to comply with
    940     // ABI rules about accessing memory below the system stack pointer.
    941     BumpSystemStackPointer(count * size);
    942   }
    943 }
    944 
    945 
    946 void MacroAssembler::PrepareForPop(int count, int size) {
    947   USE(count);
    948   USE(size);
    949   if (sp.Is(StackPointer())) {
    950     // If the current stack pointer is sp, then it must be aligned to 16 bytes
    951     // on entry and the total size of the specified registers must also be a
    952     // multiple of 16 bytes.
    953     VIXL_ASSERT((count * size) % 16 == 0);
    954   }
    955 }
    956 
    957 void MacroAssembler::Poke(const Register& src, const Operand& offset) {
    958   VIXL_ASSERT(allow_macro_instructions_);
    959   if (offset.IsImmediate()) {
    960     VIXL_ASSERT(offset.immediate() >= 0);
    961   }
    962 
    963   Str(src, MemOperand(StackPointer(), offset));
    964 }
    965 
    966 
    967 void MacroAssembler::Peek(const Register& dst, const Operand& offset) {
    968   VIXL_ASSERT(allow_macro_instructions_);
    969   if (offset.IsImmediate()) {
    970     VIXL_ASSERT(offset.immediate() >= 0);
    971   }
    972 
    973   Ldr(dst, MemOperand(StackPointer(), offset));
    974 }
    975 
    976 
    977 void MacroAssembler::Claim(const Operand& size) {
    978   VIXL_ASSERT(allow_macro_instructions_);
    979 
    980   if (size.IsZero()) {
    981     return;
    982   }
    983 
    984   if (size.IsImmediate()) {
    985     VIXL_ASSERT(size.immediate() > 0);
    986     if (sp.Is(StackPointer())) {
    987       VIXL_ASSERT((size.immediate() % 16) == 0);
    988     }
    989   }
    990 
    991   if (!sp.Is(StackPointer())) {
    992     BumpSystemStackPointer(size);
    993   }
    994 
    995   Sub(StackPointer(), StackPointer(), size);
    996 }
    997 
    998 
    999 void MacroAssembler::Drop(const Operand& size) {
   1000   VIXL_ASSERT(allow_macro_instructions_);
   1001 
   1002   if (size.IsZero()) {
   1003     return;
   1004   }
   1005 
   1006   if (size.IsImmediate()) {
   1007     VIXL_ASSERT(size.immediate() > 0);
   1008     if (sp.Is(StackPointer())) {
   1009       VIXL_ASSERT((size.immediate() % 16) == 0);
   1010     }
   1011   }
   1012 
   1013   Add(StackPointer(), StackPointer(), size);
   1014 }
   1015 
   1016 
   1017 void MacroAssembler::PushCalleeSavedRegisters() {
   1018   // Ensure that the macro-assembler doesn't use any scratch registers.
   1019   InstructionAccurateScope scope(this);
   1020 
   1021   // This method must not be called unless the current stack pointer is sp.
   1022   VIXL_ASSERT(sp.Is(StackPointer()));
   1023 
   1024   MemOperand tos(sp, -2 * kXRegSizeInBytes, PreIndex);
   1025 
   1026   stp(x29, x30, tos);
   1027   stp(x27, x28, tos);
   1028   stp(x25, x26, tos);
   1029   stp(x23, x24, tos);
   1030   stp(x21, x22, tos);
   1031   stp(x19, x20, tos);
   1032 
   1033   stp(d14, d15, tos);
   1034   stp(d12, d13, tos);
   1035   stp(d10, d11, tos);
   1036   stp(d8, d9, tos);
   1037 }
   1038 
   1039 
   1040 void MacroAssembler::PopCalleeSavedRegisters() {
   1041   // Ensure that the macro-assembler doesn't use any scratch registers.
   1042   InstructionAccurateScope scope(this);
   1043 
   1044   // This method must not be called unless the current stack pointer is sp.
   1045   VIXL_ASSERT(sp.Is(StackPointer()));
   1046 
   1047   MemOperand tos(sp, 2 * kXRegSizeInBytes, PostIndex);
   1048 
   1049   ldp(d8, d9, tos);
   1050   ldp(d10, d11, tos);
   1051   ldp(d12, d13, tos);
   1052   ldp(d14, d15, tos);
   1053 
   1054   ldp(x19, x20, tos);
   1055   ldp(x21, x22, tos);
   1056   ldp(x23, x24, tos);
   1057   ldp(x25, x26, tos);
   1058   ldp(x27, x28, tos);
   1059   ldp(x29, x30, tos);
   1060 }
   1061 
   1062 void MacroAssembler::BumpSystemStackPointer(const Operand& space) {
   1063   VIXL_ASSERT(!sp.Is(StackPointer()));
   1064   // TODO: Several callers rely on this not using scratch registers, so we use
   1065   // the assembler directly here. However, this means that large immediate
   1066   // values of 'space' cannot be handled.
   1067   InstructionAccurateScope scope(this);
   1068   sub(sp, StackPointer(), space);
   1069 }
   1070 
   1071 
   1072 // This is the main Printf implementation. All callee-saved registers are
   1073 // preserved, but NZCV and the caller-saved registers may be clobbered.
   1074 void MacroAssembler::PrintfNoPreserve(const char * format,
   1075                                       const CPURegister& arg0,
   1076                                       const CPURegister& arg1,
   1077                                       const CPURegister& arg2,
   1078                                       const CPURegister& arg3) {
   1079   // We cannot handle a caller-saved stack pointer. It doesn't make much sense
   1080   // in most cases anyway, so this restriction shouldn't be too serious.
   1081   VIXL_ASSERT(!kCallerSaved.IncludesAliasOf(StackPointer()));
   1082 
   1083   // The provided arguments, and their proper PCS registers.
   1084   CPURegister args[kPrintfMaxArgCount] = {arg0, arg1, arg2, arg3};
   1085   CPURegister pcs[kPrintfMaxArgCount];
   1086 
   1087   int arg_count = kPrintfMaxArgCount;
   1088 
   1089   // The PCS varargs registers for printf. Note that x0 is used for the printf
   1090   // format string.
   1091   static const CPURegList kPCSVarargs =
   1092       CPURegList(CPURegister::kRegister, kXRegSize, 1, arg_count);
   1093   static const CPURegList kPCSVarargsFP =
   1094       CPURegList(CPURegister::kFPRegister, kDRegSize, 0, arg_count - 1);
   1095 
   1096   // We can use caller-saved registers as scratch values, except for the
   1097   // arguments and the PCS registers where they might need to go.
   1098   UseScratchRegisterScope temps(this);
   1099   temps.Include(kCallerSaved);
   1100   temps.Include(kCallerSavedFP);
   1101   temps.Exclude(kPCSVarargs);
   1102   temps.Exclude(kPCSVarargsFP);
   1103   temps.Exclude(arg0, arg1, arg2, arg3);
   1104 
   1105   // Copies of the arg lists that we can iterate through.
   1106   CPURegList pcs_varargs = kPCSVarargs;
   1107   CPURegList pcs_varargs_fp = kPCSVarargsFP;
   1108 
   1109   // Place the arguments. There are lots of clever tricks and optimizations we
   1110   // could use here, but Printf is a debug tool so instead we just try to keep
   1111   // it simple: Move each input that isn't already in the right place to a
   1112   // scratch register, then move everything back.
   1113   for (unsigned i = 0; i < kPrintfMaxArgCount; i++) {
   1114     // Work out the proper PCS register for this argument.
   1115     if (args[i].IsRegister()) {
   1116       pcs[i] = pcs_varargs.PopLowestIndex().X();
   1117       // We might only need a W register here. We need to know the size of the
   1118       // argument so we can properly encode it for the simulator call.
   1119       if (args[i].Is32Bits()) pcs[i] = pcs[i].W();
   1120     } else if (args[i].IsFPRegister()) {
   1121       // In C, floats are always cast to doubles for varargs calls.
   1122       pcs[i] = pcs_varargs_fp.PopLowestIndex().D();
   1123     } else {
   1124       VIXL_ASSERT(args[i].IsNone());
   1125       arg_count = i;
   1126       break;
   1127     }
   1128 
   1129     // If the argument is already in the right place, leave it where it is.
   1130     if (args[i].Aliases(pcs[i])) continue;
   1131 
   1132     // Otherwise, if the argument is in a PCS argument register, allocate an
   1133     // appropriate scratch register and then move it out of the way.
   1134     if (kPCSVarargs.IncludesAliasOf(args[i]) ||
   1135         kPCSVarargsFP.IncludesAliasOf(args[i])) {
   1136       if (args[i].IsRegister()) {
   1137         Register old_arg = Register(args[i]);
   1138         Register new_arg = temps.AcquireSameSizeAs(old_arg);
   1139         Mov(new_arg, old_arg);
   1140         args[i] = new_arg;
   1141       } else {
   1142         FPRegister old_arg = FPRegister(args[i]);
   1143         FPRegister new_arg = temps.AcquireSameSizeAs(old_arg);
   1144         Fmov(new_arg, old_arg);
   1145         args[i] = new_arg;
   1146       }
   1147     }
   1148   }
   1149 
   1150   // Do a second pass to move values into their final positions and perform any
   1151   // conversions that may be required.
   1152   for (int i = 0; i < arg_count; i++) {
   1153     VIXL_ASSERT(pcs[i].type() == args[i].type());
   1154     if (pcs[i].IsRegister()) {
   1155       Mov(Register(pcs[i]), Register(args[i]), kDiscardForSameWReg);
   1156     } else {
   1157       VIXL_ASSERT(pcs[i].IsFPRegister());
   1158       if (pcs[i].size() == args[i].size()) {
   1159         Fmov(FPRegister(pcs[i]), FPRegister(args[i]));
   1160       } else {
   1161         Fcvt(FPRegister(pcs[i]), FPRegister(args[i]));
   1162       }
   1163     }
   1164   }
   1165 
   1166   // Load the format string into x0, as per the procedure-call standard.
   1167   //
   1168   // To make the code as portable as possible, the format string is encoded
   1169   // directly in the instruction stream. It might be cleaner to encode it in a
   1170   // literal pool, but since Printf is usually used for debugging, it is
   1171   // beneficial for it to be minimally dependent on other features.
   1172   temps.Exclude(x0);
   1173   Label format_address;
   1174   Adr(x0, &format_address);
   1175 
   1176   // Emit the format string directly in the instruction stream.
   1177   { BlockLiteralPoolScope scope(this);
   1178     Label after_data;
   1179     B(&after_data);
   1180     Bind(&format_address);
   1181     EmitStringData(format);
   1182     Unreachable();
   1183     Bind(&after_data);
   1184   }
   1185 
   1186   // We don't pass any arguments on the stack, but we still need to align the C
   1187   // stack pointer to a 16-byte boundary for PCS compliance.
   1188   if (!sp.Is(StackPointer())) {
   1189     Bic(sp, StackPointer(), 0xf);
   1190   }
   1191 
   1192   // Actually call printf. This part needs special handling for the simulator,
   1193   // since the system printf function will use a different instruction set and
   1194   // the procedure-call standard will not be compatible.
   1195 #ifdef USE_SIMULATOR
   1196   { InstructionAccurateScope scope(this, kPrintfLength / kInstructionSize);
   1197     hlt(kPrintfOpcode);
   1198     dc32(arg_count);          // kPrintfArgCountOffset
   1199 
   1200     // Determine the argument pattern.
   1201     uint32_t arg_pattern_list = 0;
   1202     for (int i = 0; i < arg_count; i++) {
   1203       uint32_t arg_pattern;
   1204       if (pcs[i].IsRegister()) {
   1205         arg_pattern = pcs[i].Is32Bits() ? kPrintfArgW : kPrintfArgX;
   1206       } else {
   1207         VIXL_ASSERT(pcs[i].Is64Bits());
   1208         arg_pattern = kPrintfArgD;
   1209       }
   1210       VIXL_ASSERT(arg_pattern < (1 << kPrintfArgPatternBits));
   1211       arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i));
   1212     }
   1213     dc32(arg_pattern_list);   // kPrintfArgPatternListOffset
   1214   }
   1215 #else
   1216   Register tmp = temps.AcquireX();
   1217   Mov(tmp, reinterpret_cast<uintptr_t>(printf));
   1218   Blr(tmp);
   1219 #endif
   1220 }
   1221 
   1222 
   1223 void MacroAssembler::Printf(const char * format,
   1224                             CPURegister arg0,
   1225                             CPURegister arg1,
   1226                             CPURegister arg2,
   1227                             CPURegister arg3) {
   1228   // We can only print sp if it is the current stack pointer.
   1229   if (!sp.Is(StackPointer())) {
   1230     VIXL_ASSERT(!sp.Aliases(arg0));
   1231     VIXL_ASSERT(!sp.Aliases(arg1));
   1232     VIXL_ASSERT(!sp.Aliases(arg2));
   1233     VIXL_ASSERT(!sp.Aliases(arg3));
   1234   }
   1235 
   1236   // Make sure that the macro assembler doesn't try to use any of our arguments
   1237   // as scratch registers.
   1238   UseScratchRegisterScope exclude_all(this);
   1239   exclude_all.ExcludeAll();
   1240 
   1241   // Preserve all caller-saved registers as well as NZCV.
   1242   // If sp is the stack pointer, PushCPURegList asserts that the size of each
   1243   // list is a multiple of 16 bytes.
   1244   PushCPURegList(kCallerSaved);
   1245   PushCPURegList(kCallerSavedFP);
   1246 
   1247   { UseScratchRegisterScope temps(this);
   1248     // We can use caller-saved registers as scratch values (except for argN).
   1249     temps.Include(kCallerSaved);
   1250     temps.Include(kCallerSavedFP);
   1251     temps.Exclude(arg0, arg1, arg2, arg3);
   1252 
   1253     // If any of the arguments are the current stack pointer, allocate a new
   1254     // register for them, and adjust the value to compensate for pushing the
   1255     // caller-saved registers.
   1256     bool arg0_sp = StackPointer().Aliases(arg0);
   1257     bool arg1_sp = StackPointer().Aliases(arg1);
   1258     bool arg2_sp = StackPointer().Aliases(arg2);
   1259     bool arg3_sp = StackPointer().Aliases(arg3);
   1260     if (arg0_sp || arg1_sp || arg2_sp || arg3_sp) {
   1261       // Allocate a register to hold the original stack pointer value, to pass
   1262       // to PrintfNoPreserve as an argument.
   1263       Register arg_sp = temps.AcquireX();
   1264       Add(arg_sp, StackPointer(),
   1265           kCallerSaved.TotalSizeInBytes() + kCallerSavedFP.TotalSizeInBytes());
   1266       if (arg0_sp) arg0 = Register(arg_sp.code(), arg0.size());
   1267       if (arg1_sp) arg1 = Register(arg_sp.code(), arg1.size());
   1268       if (arg2_sp) arg2 = Register(arg_sp.code(), arg2.size());
   1269       if (arg3_sp) arg3 = Register(arg_sp.code(), arg3.size());
   1270     }
   1271 
   1272     // Preserve NZCV.
   1273     Register tmp = temps.AcquireX();
   1274     Mrs(tmp, NZCV);
   1275     Push(tmp, xzr);
   1276     temps.Release(tmp);
   1277 
   1278     PrintfNoPreserve(format, arg0, arg1, arg2, arg3);
   1279 
   1280     // Restore NZCV.
   1281     tmp = temps.AcquireX();
   1282     Pop(xzr, tmp);
   1283     Msr(NZCV, tmp);
   1284     temps.Release(tmp);
   1285   }
   1286 
   1287   PopCPURegList(kCallerSavedFP);
   1288   PopCPURegList(kCallerSaved);
   1289 }
   1290 
   1291 void MacroAssembler::Trace(TraceParameters parameters, TraceCommand command) {
   1292   VIXL_ASSERT(allow_macro_instructions_);
   1293 
   1294 #ifdef USE_SIMULATOR
   1295   // The arguments to the trace pseudo instruction need to be contiguous in
   1296   // memory, so make sure we don't try to emit a literal pool.
   1297   InstructionAccurateScope scope(this, kTraceLength / kInstructionSize);
   1298 
   1299   Label start;
   1300   bind(&start);
   1301 
   1302   // Refer to instructions-a64.h for a description of the marker and its
   1303   // arguments.
   1304   hlt(kTraceOpcode);
   1305 
   1306   VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceParamsOffset);
   1307   dc32(parameters);
   1308 
   1309   VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceCommandOffset);
   1310   dc32(command);
   1311 #else
   1312   // Emit nothing on real hardware.
   1313   USE(parameters);
   1314   USE(command);
   1315 #endif
   1316 }
   1317 
   1318 
   1319 void MacroAssembler::Log(TraceParameters parameters) {
   1320   VIXL_ASSERT(allow_macro_instructions_);
   1321 
   1322 #ifdef USE_SIMULATOR
   1323   // The arguments to the log pseudo instruction need to be contiguous in
   1324   // memory, so make sure we don't try to emit a literal pool.
   1325   InstructionAccurateScope scope(this, kLogLength / kInstructionSize);
   1326 
   1327   Label start;
   1328   bind(&start);
   1329 
   1330   // Refer to instructions-a64.h for a description of the marker and its
   1331   // arguments.
   1332   hlt(kLogOpcode);
   1333 
   1334   VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kLogParamsOffset);
   1335   dc32(parameters);
   1336 #else
   1337   // Emit nothing on real hardware.
   1338   USE(parameters);
   1339 #endif
   1340 }
   1341 
   1342 
   1343 void MacroAssembler::EnableInstrumentation() {
   1344   VIXL_ASSERT(!isprint(InstrumentStateEnable));
   1345   InstructionAccurateScope scope(this, 1);
   1346   movn(xzr, InstrumentStateEnable);
   1347 }
   1348 
   1349 
   1350 void MacroAssembler::DisableInstrumentation() {
   1351   VIXL_ASSERT(!isprint(InstrumentStateDisable));
   1352   InstructionAccurateScope scope(this, 1);
   1353   movn(xzr, InstrumentStateDisable);
   1354 }
   1355 
   1356 
   1357 void MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
   1358   VIXL_ASSERT(strlen(marker_name) == 2);
   1359 
   1360   // We allow only printable characters in the marker names. Unprintable
   1361   // characters are reserved for controlling features of the instrumentation.
   1362   VIXL_ASSERT(isprint(marker_name[0]) && isprint(marker_name[1]));
   1363 
   1364   InstructionAccurateScope scope(this, 1);
   1365   movn(xzr, (marker_name[1] << 8) | marker_name[0]);
   1366 }
   1367 
   1368 
   1369 UseScratchRegisterScope::~UseScratchRegisterScope() {
   1370   available_->set_list(old_available_);
   1371   availablefp_->set_list(old_availablefp_);
   1372 }
   1373 
   1374 
   1375 bool UseScratchRegisterScope::IsAvailable(const CPURegister& reg) const {
   1376   return available_->IncludesAliasOf(reg) || availablefp_->IncludesAliasOf(reg);
   1377 }
   1378 
   1379 
   1380 Register UseScratchRegisterScope::AcquireSameSizeAs(const Register& reg) {
   1381   int code = AcquireNextAvailable(available_).code();
   1382   return Register(code, reg.SizeInBits());
   1383 }
   1384 
   1385 
   1386 FPRegister UseScratchRegisterScope::AcquireSameSizeAs(const FPRegister& reg) {
   1387   int code = AcquireNextAvailable(availablefp_).code();
   1388   return FPRegister(code, reg.SizeInBits());
   1389 }
   1390 
   1391 
   1392 void UseScratchRegisterScope::Release(const CPURegister& reg) {
   1393   if (reg.IsRegister()) {
   1394     ReleaseByCode(available_, reg.code());
   1395   } else if (reg.IsFPRegister()) {
   1396     ReleaseByCode(availablefp_, reg.code());
   1397   } else {
   1398     VIXL_ASSERT(reg.IsNone());
   1399   }
   1400 }
   1401 
   1402 
   1403 void UseScratchRegisterScope::Include(const CPURegList& list) {
   1404   if (list.type() == CPURegister::kRegister) {
   1405     // Make sure that neither sp nor xzr are included the list.
   1406     IncludeByRegList(available_, list.list() & ~(xzr.Bit() | sp.Bit()));
   1407   } else {
   1408     VIXL_ASSERT(list.type() == CPURegister::kFPRegister);
   1409     IncludeByRegList(availablefp_, list.list());
   1410   }
   1411 }
   1412 
   1413 
   1414 void UseScratchRegisterScope::Include(const Register& reg1,
   1415                                       const Register& reg2,
   1416                                       const Register& reg3,
   1417                                       const Register& reg4) {
   1418   RegList include = reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit();
   1419   // Make sure that neither sp nor xzr are included the list.
   1420   include &= ~(xzr.Bit() | sp.Bit());
   1421 
   1422   IncludeByRegList(available_, include);
   1423 }
   1424 
   1425 
   1426 void UseScratchRegisterScope::Include(const FPRegister& reg1,
   1427                                       const FPRegister& reg2,
   1428                                       const FPRegister& reg3,
   1429                                       const FPRegister& reg4) {
   1430   RegList include = reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit();
   1431   IncludeByRegList(availablefp_, include);
   1432 }
   1433 
   1434 
   1435 void UseScratchRegisterScope::Exclude(const CPURegList& list) {
   1436   if (list.type() == CPURegister::kRegister) {
   1437     ExcludeByRegList(available_, list.list());
   1438   } else {
   1439     VIXL_ASSERT(list.type() == CPURegister::kFPRegister);
   1440     ExcludeByRegList(availablefp_, list.list());
   1441   }
   1442 }
   1443 
   1444 
   1445 void UseScratchRegisterScope::Exclude(const Register& reg1,
   1446                                       const Register& reg2,
   1447                                       const Register& reg3,
   1448                                       const Register& reg4) {
   1449   RegList exclude = reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit();
   1450   ExcludeByRegList(available_, exclude);
   1451 }
   1452 
   1453 
   1454 void UseScratchRegisterScope::Exclude(const FPRegister& reg1,
   1455                                       const FPRegister& reg2,
   1456                                       const FPRegister& reg3,
   1457                                       const FPRegister& reg4) {
   1458   RegList excludefp = reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit();
   1459   ExcludeByRegList(availablefp_, excludefp);
   1460 }
   1461 
   1462 
   1463 void UseScratchRegisterScope::Exclude(const CPURegister& reg1,
   1464                                       const CPURegister& reg2,
   1465                                       const CPURegister& reg3,
   1466                                       const CPURegister& reg4) {
   1467   RegList exclude = 0;
   1468   RegList excludefp = 0;
   1469 
   1470   const CPURegister regs[] = {reg1, reg2, reg3, reg4};
   1471 
   1472   for (unsigned i = 0; i < (sizeof(regs) / sizeof(regs[0])); i++) {
   1473     if (regs[i].IsRegister()) {
   1474       exclude |= regs[i].Bit();
   1475     } else if (regs[i].IsFPRegister()) {
   1476       excludefp |= regs[i].Bit();
   1477     } else {
   1478       VIXL_ASSERT(regs[i].IsNone());
   1479     }
   1480   }
   1481 
   1482   ExcludeByRegList(available_, exclude);
   1483   ExcludeByRegList(availablefp_, excludefp);
   1484 }
   1485 
   1486 
   1487 void UseScratchRegisterScope::ExcludeAll() {
   1488   ExcludeByRegList(available_, available_->list());
   1489   ExcludeByRegList(availablefp_, availablefp_->list());
   1490 }
   1491 
   1492 
   1493 CPURegister UseScratchRegisterScope::AcquireNextAvailable(
   1494     CPURegList* available) {
   1495   VIXL_CHECK(!available->IsEmpty());
   1496   CPURegister result = available->PopLowestIndex();
   1497   VIXL_ASSERT(!AreAliased(result, xzr, sp));
   1498   return result;
   1499 }
   1500 
   1501 
   1502 void UseScratchRegisterScope::ReleaseByCode(CPURegList* available, int code) {
   1503   ReleaseByRegList(available, static_cast<RegList>(1) << code);
   1504 }
   1505 
   1506 
   1507 void UseScratchRegisterScope::ReleaseByRegList(CPURegList* available,
   1508                                                RegList regs) {
   1509   available->set_list(available->list() | regs);
   1510 }
   1511 
   1512 
   1513 void UseScratchRegisterScope::IncludeByRegList(CPURegList* available,
   1514                                                RegList regs) {
   1515   available->set_list(available->list() | regs);
   1516 }
   1517 
   1518 
   1519 void UseScratchRegisterScope::ExcludeByRegList(CPURegList* available,
   1520                                                RegList exclude) {
   1521   available->set_list(available->list() & ~exclude);
   1522 }
   1523 
   1524 }  // namespace vixl
   1525