1 // Copyright 2015, 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 #ifndef VIXL_A64_MACRO_ASSEMBLER_A64_H_ 28 #define VIXL_A64_MACRO_ASSEMBLER_A64_H_ 29 30 #include <algorithm> 31 #include <limits> 32 33 #include "jit/arm64/Assembler-arm64.h" 34 #include "jit/arm64/vixl/Debugger-vixl.h" 35 #include "jit/arm64/vixl/Globals-vixl.h" 36 #include "jit/arm64/vixl/Instrument-vixl.h" 37 #include "jit/arm64/vixl/Simulator-Constants-vixl.h" 38 39 #define LS_MACRO_LIST(V) \ 40 V(Ldrb, Register&, rt, LDRB_w) \ 41 V(Strb, Register&, rt, STRB_w) \ 42 V(Ldrsb, Register&, rt, rt.Is64Bits() ? LDRSB_x : LDRSB_w) \ 43 V(Ldrh, Register&, rt, LDRH_w) \ 44 V(Strh, Register&, rt, STRH_w) \ 45 V(Ldrsh, Register&, rt, rt.Is64Bits() ? LDRSH_x : LDRSH_w) \ 46 V(Ldr, CPURegister&, rt, LoadOpFor(rt)) \ 47 V(Str, CPURegister&, rt, StoreOpFor(rt)) \ 48 V(Ldrsw, Register&, rt, LDRSW_x) 49 50 51 #define LSPAIR_MACRO_LIST(V) \ 52 V(Ldp, CPURegister&, rt, rt2, LoadPairOpFor(rt, rt2)) \ 53 V(Stp, CPURegister&, rt, rt2, StorePairOpFor(rt, rt2)) \ 54 V(Ldpsw, CPURegister&, rt, rt2, LDPSW_x) 55 56 namespace vixl { 57 58 // Forward declaration 59 class MacroAssembler; 60 class UseScratchRegisterScope; 61 62 // This scope has the following purposes: 63 // * Acquire/Release the underlying assembler's code buffer. 64 // * This is mandatory before emitting. 65 // * Emit the literal or veneer pools if necessary before emitting the 66 // macro-instruction. 67 // * Ensure there is enough space to emit the macro-instruction. 68 class EmissionCheckScope { 69 public: EmissionCheckScope(MacroAssembler * masm,size_t size)70 EmissionCheckScope(MacroAssembler* masm, size_t size) 71 : masm_(masm) 72 { } 73 74 protected: 75 MacroAssembler* masm_; 76 #ifdef DEBUG 77 Label start_; 78 size_t size_; 79 #endif 80 }; 81 82 83 // Helper for common Emission checks. 84 // The macro-instruction maps to a single instruction. 85 class SingleEmissionCheckScope : public EmissionCheckScope { 86 public: SingleEmissionCheckScope(MacroAssembler * masm)87 explicit SingleEmissionCheckScope(MacroAssembler* masm) 88 : EmissionCheckScope(masm, kInstructionSize) {} 89 }; 90 91 92 // The macro instruction is a "typical" macro-instruction. Typical macro- 93 // instruction only emit a few instructions, a few being defined as 8 here. 94 class MacroEmissionCheckScope : public EmissionCheckScope { 95 public: MacroEmissionCheckScope(MacroAssembler * masm)96 explicit MacroEmissionCheckScope(MacroAssembler* masm) 97 : EmissionCheckScope(masm, kTypicalMacroInstructionMaxSize) {} 98 99 private: 100 static const size_t kTypicalMacroInstructionMaxSize = 8 * kInstructionSize; 101 }; 102 103 104 enum BranchType { 105 // Copies of architectural conditions. 106 // The associated conditions can be used in place of those, the code will 107 // take care of reinterpreting them with the correct type. 108 integer_eq = eq, 109 integer_ne = ne, 110 integer_hs = hs, 111 integer_lo = lo, 112 integer_mi = mi, 113 integer_pl = pl, 114 integer_vs = vs, 115 integer_vc = vc, 116 integer_hi = hi, 117 integer_ls = ls, 118 integer_ge = ge, 119 integer_lt = lt, 120 integer_gt = gt, 121 integer_le = le, 122 integer_al = al, 123 integer_nv = nv, 124 125 // These two are *different* from the architectural codes al and nv. 126 // 'always' is used to generate unconditional branches. 127 // 'never' is used to not generate a branch (generally as the inverse 128 // branch type of 'always). 129 always, never, 130 // cbz and cbnz 131 reg_zero, reg_not_zero, 132 // tbz and tbnz 133 reg_bit_clear, reg_bit_set, 134 135 // Aliases. 136 kBranchTypeFirstCondition = eq, 137 kBranchTypeLastCondition = nv, 138 kBranchTypeFirstUsingReg = reg_zero, 139 kBranchTypeFirstUsingBit = reg_bit_clear 140 }; 141 142 143 enum DiscardMoveMode { kDontDiscardForSameWReg, kDiscardForSameWReg }; 144 145 // The macro assembler supports moving automatically pre-shifted immediates for 146 // arithmetic and logical instructions, and then applying a post shift in the 147 // instruction to undo the modification, in order to reduce the code emitted for 148 // an operation. For example: 149 // 150 // Add(x0, x0, 0x1f7de) => movz x16, 0xfbef; add x0, x0, x16, lsl #1. 151 // 152 // This optimisation can be only partially applied when the stack pointer is an 153 // operand or destination, so this enumeration is used to control the shift. 154 enum PreShiftImmMode { 155 kNoShift, // Don't pre-shift. 156 kLimitShiftForSP, // Limit pre-shift for add/sub extend use. 157 kAnyShift // Allow any pre-shift. 158 }; 159 160 161 class MacroAssembler : public js::jit::Assembler { 162 public: 163 MacroAssembler(); 164 165 // Finalize a code buffer of generated instructions. This function must be 166 // called before executing or copying code from the buffer. 167 void FinalizeCode(); 168 169 170 // Constant generation helpers. 171 // These functions return the number of instructions required to move the 172 // immediate into the destination register. Also, if the masm pointer is 173 // non-null, it generates the code to do so. 174 // The two features are implemented using one function to avoid duplication of 175 // the logic. 176 // The function can be used to evaluate the cost of synthesizing an 177 // instruction using 'mov immediate' instructions. A user might prefer loading 178 // a constant using the literal pool instead of using multiple 'mov immediate' 179 // instructions. 180 static int MoveImmediateHelper(MacroAssembler* masm, 181 const Register &rd, 182 uint64_t imm); 183 static bool OneInstrMoveImmediateHelper(MacroAssembler* masm, 184 const Register& dst, 185 int64_t imm); 186 187 188 // Logical macros. 189 void And(const Register& rd, 190 const Register& rn, 191 const Operand& operand); 192 void Ands(const Register& rd, 193 const Register& rn, 194 const Operand& operand); 195 void Bic(const Register& rd, 196 const Register& rn, 197 const Operand& operand); 198 void Bics(const Register& rd, 199 const Register& rn, 200 const Operand& operand); 201 void Orr(const Register& rd, 202 const Register& rn, 203 const Operand& operand); 204 void Orn(const Register& rd, 205 const Register& rn, 206 const Operand& operand); 207 void Eor(const Register& rd, 208 const Register& rn, 209 const Operand& operand); 210 void Eon(const Register& rd, 211 const Register& rn, 212 const Operand& operand); 213 void Tst(const Register& rn, const Operand& operand); 214 void LogicalMacro(const Register& rd, 215 const Register& rn, 216 const Operand& operand, 217 LogicalOp op); 218 219 // Add and sub macros. 220 void Add(const Register& rd, 221 const Register& rn, 222 const Operand& operand, 223 FlagsUpdate S = LeaveFlags); 224 void Adds(const Register& rd, 225 const Register& rn, 226 const Operand& operand); 227 void Sub(const Register& rd, 228 const Register& rn, 229 const Operand& operand, 230 FlagsUpdate S = LeaveFlags); 231 void Subs(const Register& rd, 232 const Register& rn, 233 const Operand& operand); 234 void Cmn(const Register& rn, const Operand& operand); 235 void Cmp(const Register& rn, const Operand& operand); 236 void Neg(const Register& rd, 237 const Operand& operand); 238 void Negs(const Register& rd, 239 const Operand& operand); 240 241 void AddSubMacro(const Register& rd, 242 const Register& rn, 243 const Operand& operand, 244 FlagsUpdate S, 245 AddSubOp op); 246 247 // Add/sub with carry macros. 248 void Adc(const Register& rd, 249 const Register& rn, 250 const Operand& operand); 251 void Adcs(const Register& rd, 252 const Register& rn, 253 const Operand& operand); 254 void Sbc(const Register& rd, 255 const Register& rn, 256 const Operand& operand); 257 void Sbcs(const Register& rd, 258 const Register& rn, 259 const Operand& operand); 260 void Ngc(const Register& rd, 261 const Operand& operand); 262 void Ngcs(const Register& rd, 263 const Operand& operand); 264 void AddSubWithCarryMacro(const Register& rd, 265 const Register& rn, 266 const Operand& operand, 267 FlagsUpdate S, 268 AddSubWithCarryOp op); 269 270 // Move macros. 271 void Mov(const Register& rd, uint64_t imm); 272 void Mov(const Register& rd, 273 const Operand& operand, 274 DiscardMoveMode discard_mode = kDontDiscardForSameWReg); Mvn(const Register & rd,uint64_t imm)275 void Mvn(const Register& rd, uint64_t imm) { 276 Mov(rd, (rd.size() == kXRegSize) ? ~imm : (~imm & kWRegMask)); 277 } 278 void Mvn(const Register& rd, const Operand& operand); 279 280 // Try to move an immediate into the destination register in a single 281 // instruction. Returns true for success, and updates the contents of dst. 282 // Returns false, otherwise. 283 bool TryOneInstrMoveImmediate(const Register& dst, int64_t imm); 284 285 // Move an immediate into register dst, and return an Operand object for 286 // use with a subsequent instruction that accepts a shift. The value moved 287 // into dst is not necessarily equal to imm; it may have had a shifting 288 // operation applied to it that will be subsequently undone by the shift 289 // applied in the Operand. 290 Operand MoveImmediateForShiftedOp(const Register& dst, 291 int64_t imm, 292 PreShiftImmMode mode); 293 294 // Synthesises the address represented by a MemOperand into a register. 295 void ComputeAddress(const Register& dst, const MemOperand& mem_op); 296 297 // Conditional macros. 298 void Ccmp(const Register& rn, 299 const Operand& operand, 300 StatusFlags nzcv, 301 Condition cond); 302 void Ccmn(const Register& rn, 303 const Operand& operand, 304 StatusFlags nzcv, 305 Condition cond); 306 void ConditionalCompareMacro(const Register& rn, 307 const Operand& operand, 308 StatusFlags nzcv, 309 Condition cond, 310 ConditionalCompareOp op); 311 void Csel(const Register& rd, 312 const Register& rn, 313 const Operand& operand, 314 Condition cond); 315 316 // Load/store macros. 317 #define DECLARE_FUNCTION(FN, REGTYPE, REG, OP) \ 318 void FN(const REGTYPE REG, const MemOperand& addr); 319 LS_MACRO_LIST(DECLARE_FUNCTION) 320 #undef DECLARE_FUNCTION 321 322 void LoadStoreMacro(const CPURegister& rt, 323 const MemOperand& addr, 324 LoadStoreOp op); 325 326 #define DECLARE_FUNCTION(FN, REGTYPE, REG, REG2, OP) \ 327 void FN(const REGTYPE REG, const REGTYPE REG2, const MemOperand& addr); 328 LSPAIR_MACRO_LIST(DECLARE_FUNCTION) 329 #undef DECLARE_FUNCTION 330 331 void LoadStorePairMacro(const CPURegister& rt, 332 const CPURegister& rt2, 333 const MemOperand& addr, 334 LoadStorePairOp op); 335 336 void Prfm(PrefetchOperation op, const MemOperand& addr); 337 338 // Push or pop up to 4 registers of the same width to or from the stack, 339 // using the current stack pointer as set by SetStackPointer. 340 // 341 // If an argument register is 'NoReg', all further arguments are also assumed 342 // to be 'NoReg', and are thus not pushed or popped. 343 // 344 // Arguments are ordered such that "Push(a, b);" is functionally equivalent 345 // to "Push(a); Push(b);". 346 // 347 // It is valid to push the same register more than once, and there is no 348 // restriction on the order in which registers are specified. 349 // 350 // It is not valid to pop into the same register more than once in one 351 // operation, not even into the zero register. 352 // 353 // If the current stack pointer (as set by SetStackPointer) is sp, then it 354 // must be aligned to 16 bytes on entry and the total size of the specified 355 // registers must also be a multiple of 16 bytes. 356 // 357 // Even if the current stack pointer is not the system stack pointer (sp), 358 // Push (and derived methods) will still modify the system stack pointer in 359 // order to comply with ABI rules about accessing memory below the system 360 // stack pointer. 361 // 362 // Other than the registers passed into Pop, the stack pointer and (possibly) 363 // the system stack pointer, these methods do not modify any other registers. 364 void Push(const CPURegister& src0, const CPURegister& src1 = NoReg, 365 const CPURegister& src2 = NoReg, const CPURegister& src3 = NoReg); 366 void Pop(const CPURegister& dst0, const CPURegister& dst1 = NoReg, 367 const CPURegister& dst2 = NoReg, const CPURegister& dst3 = NoReg); 368 void PushStackPointer(); 369 370 // Alternative forms of Push and Pop, taking a RegList or CPURegList that 371 // specifies the registers that are to be pushed or popped. Higher-numbered 372 // registers are associated with higher memory addresses (as in the A32 push 373 // and pop instructions). 374 // 375 // (Push|Pop)SizeRegList allow you to specify the register size as a 376 // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are 377 // supported. 378 // 379 // Otherwise, (Push|Pop)(CPU|X|W|D|S)RegList is preferred. 380 void PushCPURegList(CPURegList registers); 381 void PopCPURegList(CPURegList registers); 382 383 void PushSizeRegList(RegList registers, unsigned reg_size, 384 CPURegister::RegisterType type = CPURegister::kRegister) { 385 PushCPURegList(CPURegList(type, reg_size, registers)); 386 } 387 void PopSizeRegList(RegList registers, unsigned reg_size, 388 CPURegister::RegisterType type = CPURegister::kRegister) { 389 PopCPURegList(CPURegList(type, reg_size, registers)); 390 } PushXRegList(RegList regs)391 void PushXRegList(RegList regs) { 392 PushSizeRegList(regs, kXRegSize); 393 } PopXRegList(RegList regs)394 void PopXRegList(RegList regs) { 395 PopSizeRegList(regs, kXRegSize); 396 } PushWRegList(RegList regs)397 void PushWRegList(RegList regs) { 398 PushSizeRegList(regs, kWRegSize); 399 } PopWRegList(RegList regs)400 void PopWRegList(RegList regs) { 401 PopSizeRegList(regs, kWRegSize); 402 } PushDRegList(RegList regs)403 void PushDRegList(RegList regs) { 404 PushSizeRegList(regs, kDRegSize, CPURegister::kVRegister); 405 } PopDRegList(RegList regs)406 void PopDRegList(RegList regs) { 407 PopSizeRegList(regs, kDRegSize, CPURegister::kVRegister); 408 } PushSRegList(RegList regs)409 void PushSRegList(RegList regs) { 410 PushSizeRegList(regs, kSRegSize, CPURegister::kVRegister); 411 } PopSRegList(RegList regs)412 void PopSRegList(RegList regs) { 413 PopSizeRegList(regs, kSRegSize, CPURegister::kVRegister); 414 } 415 416 // Push the specified register 'count' times. 417 void PushMultipleTimes(int count, Register src); 418 419 // Poke 'src' onto the stack. The offset is in bytes. 420 // 421 // If the current stack pointer (as set by SetStackPointer) is sp, then sp 422 // must be aligned to 16 bytes. 423 void Poke(const Register& src, const Operand& offset); 424 425 // Peek at a value on the stack, and put it in 'dst'. The offset is in bytes. 426 // 427 // If the current stack pointer (as set by SetStackPointer) is sp, then sp 428 // must be aligned to 16 bytes. 429 void Peek(const Register& dst, const Operand& offset); 430 431 // Alternative forms of Peek and Poke, taking a RegList or CPURegList that 432 // specifies the registers that are to be pushed or popped. Higher-numbered 433 // registers are associated with higher memory addresses. 434 // 435 // (Peek|Poke)SizeRegList allow you to specify the register size as a 436 // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are 437 // supported. 438 // 439 // Otherwise, (Peek|Poke)(CPU|X|W|D|S)RegList is preferred. PeekCPURegList(CPURegList registers,int64_t offset)440 void PeekCPURegList(CPURegList registers, int64_t offset) { 441 LoadCPURegList(registers, MemOperand(StackPointer(), offset)); 442 } PokeCPURegList(CPURegList registers,int64_t offset)443 void PokeCPURegList(CPURegList registers, int64_t offset) { 444 StoreCPURegList(registers, MemOperand(StackPointer(), offset)); 445 } 446 447 void PeekSizeRegList(RegList registers, int64_t offset, unsigned reg_size, 448 CPURegister::RegisterType type = CPURegister::kRegister) { 449 PeekCPURegList(CPURegList(type, reg_size, registers), offset); 450 } 451 void PokeSizeRegList(RegList registers, int64_t offset, unsigned reg_size, 452 CPURegister::RegisterType type = CPURegister::kRegister) { 453 PokeCPURegList(CPURegList(type, reg_size, registers), offset); 454 } PeekXRegList(RegList regs,int64_t offset)455 void PeekXRegList(RegList regs, int64_t offset) { 456 PeekSizeRegList(regs, offset, kXRegSize); 457 } PokeXRegList(RegList regs,int64_t offset)458 void PokeXRegList(RegList regs, int64_t offset) { 459 PokeSizeRegList(regs, offset, kXRegSize); 460 } PeekWRegList(RegList regs,int64_t offset)461 void PeekWRegList(RegList regs, int64_t offset) { 462 PeekSizeRegList(regs, offset, kWRegSize); 463 } PokeWRegList(RegList regs,int64_t offset)464 void PokeWRegList(RegList regs, int64_t offset) { 465 PokeSizeRegList(regs, offset, kWRegSize); 466 } PeekDRegList(RegList regs,int64_t offset)467 void PeekDRegList(RegList regs, int64_t offset) { 468 PeekSizeRegList(regs, offset, kDRegSize, CPURegister::kVRegister); 469 } PokeDRegList(RegList regs,int64_t offset)470 void PokeDRegList(RegList regs, int64_t offset) { 471 PokeSizeRegList(regs, offset, kDRegSize, CPURegister::kVRegister); 472 } PeekSRegList(RegList regs,int64_t offset)473 void PeekSRegList(RegList regs, int64_t offset) { 474 PeekSizeRegList(regs, offset, kSRegSize, CPURegister::kVRegister); 475 } PokeSRegList(RegList regs,int64_t offset)476 void PokeSRegList(RegList regs, int64_t offset) { 477 PokeSizeRegList(regs, offset, kSRegSize, CPURegister::kVRegister); 478 } 479 480 481 // Claim or drop stack space without actually accessing memory. 482 // 483 // If the current stack pointer (as set by SetStackPointer) is sp, then it 484 // must be aligned to 16 bytes and the size claimed or dropped must be a 485 // multiple of 16 bytes. 486 void Claim(const Operand& size); 487 void Drop(const Operand& size); 488 489 // Preserve the callee-saved registers (as defined by AAPCS64). 490 // 491 // Higher-numbered registers are pushed before lower-numbered registers, and 492 // thus get higher addresses. 493 // Floating-point registers are pushed before general-purpose registers, and 494 // thus get higher addresses. 495 // 496 // This method must not be called unless StackPointer() is sp, and it is 497 // aligned to 16 bytes. 498 void PushCalleeSavedRegisters(); 499 500 // Restore the callee-saved registers (as defined by AAPCS64). 501 // 502 // Higher-numbered registers are popped after lower-numbered registers, and 503 // thus come from higher addresses. 504 // Floating-point registers are popped after general-purpose registers, and 505 // thus come from higher addresses. 506 // 507 // This method must not be called unless StackPointer() is sp, and it is 508 // aligned to 16 bytes. 509 void PopCalleeSavedRegisters(); 510 511 void LoadCPURegList(CPURegList registers, const MemOperand& src); 512 void StoreCPURegList(CPURegList registers, const MemOperand& dst); 513 514 // Remaining instructions are simple pass-through calls to the assembler. Adr(const Register & rd,Label * label)515 void Adr(const Register& rd, Label* label) { 516 VIXL_ASSERT(!rd.IsZero()); 517 SingleEmissionCheckScope guard(this); 518 adr(rd, label); 519 } Adrp(const Register & rd,Label * label)520 void Adrp(const Register& rd, Label* label) { 521 VIXL_ASSERT(!rd.IsZero()); 522 SingleEmissionCheckScope guard(this); 523 adrp(rd, label); 524 } Asr(const Register & rd,const Register & rn,unsigned shift)525 void Asr(const Register& rd, const Register& rn, unsigned shift) { 526 VIXL_ASSERT(!rd.IsZero()); 527 VIXL_ASSERT(!rn.IsZero()); 528 SingleEmissionCheckScope guard(this); 529 asr(rd, rn, shift); 530 } Asr(const Register & rd,const Register & rn,const Register & rm)531 void Asr(const Register& rd, const Register& rn, const Register& rm) { 532 VIXL_ASSERT(!rd.IsZero()); 533 VIXL_ASSERT(!rn.IsZero()); 534 VIXL_ASSERT(!rm.IsZero()); 535 SingleEmissionCheckScope guard(this); 536 asrv(rd, rn, rm); 537 } 538 539 // Branch type inversion relies on these relations. 540 VIXL_STATIC_ASSERT((reg_zero == (reg_not_zero ^ 1)) && 541 (reg_bit_clear == (reg_bit_set ^ 1)) && 542 (always == (never ^ 1))); 543 InvertBranchType(BranchType type)544 BranchType InvertBranchType(BranchType type) { 545 if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) { 546 return static_cast<BranchType>( 547 InvertCondition(static_cast<Condition>(type))); 548 } else { 549 return static_cast<BranchType>(type ^ 1); 550 } 551 } 552 553 void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1); 554 555 void B(Label* label); 556 void B(Label* label, Condition cond); B(Condition cond,Label * label)557 void B(Condition cond, Label* label) { 558 B(label, cond); 559 } Bfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)560 void Bfm(const Register& rd, 561 const Register& rn, 562 unsigned immr, 563 unsigned imms) { 564 VIXL_ASSERT(!rd.IsZero()); 565 VIXL_ASSERT(!rn.IsZero()); 566 SingleEmissionCheckScope guard(this); 567 bfm(rd, rn, immr, imms); 568 } Bfi(const Register & rd,const Register & rn,unsigned lsb,unsigned width)569 void Bfi(const Register& rd, 570 const Register& rn, 571 unsigned lsb, 572 unsigned width) { 573 VIXL_ASSERT(!rd.IsZero()); 574 VIXL_ASSERT(!rn.IsZero()); 575 SingleEmissionCheckScope guard(this); 576 bfi(rd, rn, lsb, width); 577 } Bfxil(const Register & rd,const Register & rn,unsigned lsb,unsigned width)578 void Bfxil(const Register& rd, 579 const Register& rn, 580 unsigned lsb, 581 unsigned width) { 582 VIXL_ASSERT(!rd.IsZero()); 583 VIXL_ASSERT(!rn.IsZero()); 584 SingleEmissionCheckScope guard(this); 585 bfxil(rd, rn, lsb, width); 586 } 587 void Bind(Label* label); 588 // Bind a label to a specified offset from the start of the buffer. 589 void BindToOffset(Label* label, ptrdiff_t offset); Bl(Label * label)590 void Bl(Label* label) { 591 SingleEmissionCheckScope guard(this); 592 bl(label); 593 } Blr(const Register & xn)594 void Blr(const Register& xn) { 595 VIXL_ASSERT(!xn.IsZero()); 596 SingleEmissionCheckScope guard(this); 597 blr(xn); 598 } Br(const Register & xn)599 void Br(const Register& xn) { 600 VIXL_ASSERT(!xn.IsZero()); 601 SingleEmissionCheckScope guard(this); 602 br(xn); 603 } 604 void Brk(int code = 0) { 605 SingleEmissionCheckScope guard(this); 606 brk(code); 607 } 608 void Cbnz(const Register& rt, Label* label); 609 void Cbz(const Register& rt, Label* label); Cinc(const Register & rd,const Register & rn,Condition cond)610 void Cinc(const Register& rd, const Register& rn, Condition cond) { 611 VIXL_ASSERT(!rd.IsZero()); 612 VIXL_ASSERT(!rn.IsZero()); 613 SingleEmissionCheckScope guard(this); 614 cinc(rd, rn, cond); 615 } Cinv(const Register & rd,const Register & rn,Condition cond)616 void Cinv(const Register& rd, const Register& rn, Condition cond) { 617 VIXL_ASSERT(!rd.IsZero()); 618 VIXL_ASSERT(!rn.IsZero()); 619 SingleEmissionCheckScope guard(this); 620 cinv(rd, rn, cond); 621 } Clrex()622 void Clrex() { 623 SingleEmissionCheckScope guard(this); 624 clrex(); 625 } Cls(const Register & rd,const Register & rn)626 void Cls(const Register& rd, const Register& rn) { 627 VIXL_ASSERT(!rd.IsZero()); 628 VIXL_ASSERT(!rn.IsZero()); 629 SingleEmissionCheckScope guard(this); 630 cls(rd, rn); 631 } Clz(const Register & rd,const Register & rn)632 void Clz(const Register& rd, const Register& rn) { 633 VIXL_ASSERT(!rd.IsZero()); 634 VIXL_ASSERT(!rn.IsZero()); 635 SingleEmissionCheckScope guard(this); 636 clz(rd, rn); 637 } Cneg(const Register & rd,const Register & rn,Condition cond)638 void Cneg(const Register& rd, const Register& rn, Condition cond) { 639 VIXL_ASSERT(!rd.IsZero()); 640 VIXL_ASSERT(!rn.IsZero()); 641 SingleEmissionCheckScope guard(this); 642 cneg(rd, rn, cond); 643 } Cset(const Register & rd,Condition cond)644 void Cset(const Register& rd, Condition cond) { 645 VIXL_ASSERT(!rd.IsZero()); 646 SingleEmissionCheckScope guard(this); 647 cset(rd, cond); 648 } Csetm(const Register & rd,Condition cond)649 void Csetm(const Register& rd, Condition cond) { 650 VIXL_ASSERT(!rd.IsZero()); 651 SingleEmissionCheckScope guard(this); 652 csetm(rd, cond); 653 } Csinc(const Register & rd,const Register & rn,const Register & rm,Condition cond)654 void Csinc(const Register& rd, 655 const Register& rn, 656 const Register& rm, 657 Condition cond) { 658 VIXL_ASSERT(!rd.IsZero()); 659 // The VIXL source code contains these assertions, but the AArch64 ISR 660 // explicitly permits the use of zero registers. CSET itself is defined 661 // in terms of CSINC with WZR/XZR. 662 // 663 // VIXL_ASSERT(!rn.IsZero()); 664 // VIXL_ASSERT(!rm.IsZero()); 665 VIXL_ASSERT((cond != al) && (cond != nv)); 666 SingleEmissionCheckScope guard(this); 667 csinc(rd, rn, rm, cond); 668 } Csinv(const Register & rd,const Register & rn,const Register & rm,Condition cond)669 void Csinv(const Register& rd, 670 const Register& rn, 671 const Register& rm, 672 Condition cond) { 673 VIXL_ASSERT(!rd.IsZero()); 674 VIXL_ASSERT(!rn.IsZero()); 675 VIXL_ASSERT(!rm.IsZero()); 676 VIXL_ASSERT((cond != al) && (cond != nv)); 677 SingleEmissionCheckScope guard(this); 678 csinv(rd, rn, rm, cond); 679 } Csneg(const Register & rd,const Register & rn,const Register & rm,Condition cond)680 void Csneg(const Register& rd, 681 const Register& rn, 682 const Register& rm, 683 Condition cond) { 684 VIXL_ASSERT(!rd.IsZero()); 685 VIXL_ASSERT(!rn.IsZero()); 686 VIXL_ASSERT(!rm.IsZero()); 687 VIXL_ASSERT((cond != al) && (cond != nv)); 688 SingleEmissionCheckScope guard(this); 689 csneg(rd, rn, rm, cond); 690 } Dmb(BarrierDomain domain,BarrierType type)691 void Dmb(BarrierDomain domain, BarrierType type) { 692 SingleEmissionCheckScope guard(this); 693 dmb(domain, type); 694 } Dsb(BarrierDomain domain,BarrierType type)695 void Dsb(BarrierDomain domain, BarrierType type) { 696 SingleEmissionCheckScope guard(this); 697 dsb(domain, type); 698 } Extr(const Register & rd,const Register & rn,const Register & rm,unsigned lsb)699 void Extr(const Register& rd, 700 const Register& rn, 701 const Register& rm, 702 unsigned lsb) { 703 VIXL_ASSERT(!rd.IsZero()); 704 VIXL_ASSERT(!rn.IsZero()); 705 VIXL_ASSERT(!rm.IsZero()); 706 SingleEmissionCheckScope guard(this); 707 extr(rd, rn, rm, lsb); 708 } Fadd(const VRegister & vd,const VRegister & vn,const VRegister & vm)709 void Fadd(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 710 SingleEmissionCheckScope guard(this); 711 fadd(vd, vn, vm); 712 } 713 void Fccmp(const VRegister& vn, 714 const VRegister& vm, 715 StatusFlags nzcv, 716 Condition cond, 717 FPTrapFlags trap = DisableTrap) { 718 VIXL_ASSERT((cond != al) && (cond != nv)); 719 SingleEmissionCheckScope guard(this); 720 FPCCompareMacro(vn, vm, nzcv, cond, trap); 721 } Fccmpe(const VRegister & vn,const VRegister & vm,StatusFlags nzcv,Condition cond)722 void Fccmpe(const VRegister& vn, 723 const VRegister& vm, 724 StatusFlags nzcv, 725 Condition cond) { 726 Fccmp(vn, vm, nzcv, cond, EnableTrap); 727 } 728 void Fcmp(const VRegister& vn, const VRegister& vm, 729 FPTrapFlags trap = DisableTrap) { 730 SingleEmissionCheckScope guard(this); 731 FPCompareMacro(vn, vm, trap); 732 } 733 void Fcmp(const VRegister& vn, double value, 734 FPTrapFlags trap = DisableTrap); 735 void Fcmpe(const VRegister& vn, double value); Fcmpe(const VRegister & vn,const VRegister & vm)736 void Fcmpe(const VRegister& vn, const VRegister& vm) { 737 Fcmp(vn, vm, EnableTrap); 738 } Fcsel(const VRegister & vd,const VRegister & vn,const VRegister & vm,Condition cond)739 void Fcsel(const VRegister& vd, 740 const VRegister& vn, 741 const VRegister& vm, 742 Condition cond) { 743 VIXL_ASSERT((cond != al) && (cond != nv)); 744 SingleEmissionCheckScope guard(this); 745 fcsel(vd, vn, vm, cond); 746 } Fcvt(const VRegister & vd,const VRegister & vn)747 void Fcvt(const VRegister& vd, const VRegister& vn) { 748 SingleEmissionCheckScope guard(this); 749 fcvt(vd, vn); 750 } Fcvtl(const VRegister & vd,const VRegister & vn)751 void Fcvtl(const VRegister& vd, const VRegister& vn) { 752 SingleEmissionCheckScope guard(this); 753 fcvtl(vd, vn); 754 } Fcvtl2(const VRegister & vd,const VRegister & vn)755 void Fcvtl2(const VRegister& vd, const VRegister& vn) { 756 SingleEmissionCheckScope guard(this); 757 fcvtl2(vd, vn); 758 } Fcvtn(const VRegister & vd,const VRegister & vn)759 void Fcvtn(const VRegister& vd, const VRegister& vn) { 760 SingleEmissionCheckScope guard(this); 761 fcvtn(vd, vn); 762 } Fcvtn2(const VRegister & vd,const VRegister & vn)763 void Fcvtn2(const VRegister& vd, const VRegister& vn) { 764 SingleEmissionCheckScope guard(this); 765 fcvtn2(vd, vn); 766 } Fcvtxn(const VRegister & vd,const VRegister & vn)767 void Fcvtxn(const VRegister& vd, const VRegister& vn) { 768 SingleEmissionCheckScope guard(this); 769 fcvtxn(vd, vn); 770 } Fcvtxn2(const VRegister & vd,const VRegister & vn)771 void Fcvtxn2(const VRegister& vd, const VRegister& vn) { 772 SingleEmissionCheckScope guard(this); 773 fcvtxn2(vd, vn); 774 } Fcvtas(const Register & rd,const VRegister & vn)775 void Fcvtas(const Register& rd, const VRegister& vn) { 776 VIXL_ASSERT(!rd.IsZero()); 777 SingleEmissionCheckScope guard(this); 778 fcvtas(rd, vn); 779 } Fcvtau(const Register & rd,const VRegister & vn)780 void Fcvtau(const Register& rd, const VRegister& vn) { 781 VIXL_ASSERT(!rd.IsZero()); 782 SingleEmissionCheckScope guard(this); 783 fcvtau(rd, vn); 784 } Fcvtms(const Register & rd,const VRegister & vn)785 void Fcvtms(const Register& rd, const VRegister& vn) { 786 VIXL_ASSERT(!rd.IsZero()); 787 SingleEmissionCheckScope guard(this); 788 fcvtms(rd, vn); 789 } Fcvtmu(const Register & rd,const VRegister & vn)790 void Fcvtmu(const Register& rd, const VRegister& vn) { 791 VIXL_ASSERT(!rd.IsZero()); 792 SingleEmissionCheckScope guard(this); 793 fcvtmu(rd, vn); 794 } Fcvtns(const Register & rd,const VRegister & vn)795 void Fcvtns(const Register& rd, const VRegister& vn) { 796 VIXL_ASSERT(!rd.IsZero()); 797 SingleEmissionCheckScope guard(this); 798 fcvtns(rd, vn); 799 } Fcvtnu(const Register & rd,const VRegister & vn)800 void Fcvtnu(const Register& rd, const VRegister& vn) { 801 VIXL_ASSERT(!rd.IsZero()); 802 SingleEmissionCheckScope guard(this); 803 fcvtnu(rd, vn); 804 } Fcvtps(const Register & rd,const VRegister & vn)805 void Fcvtps(const Register& rd, const VRegister& vn) { 806 VIXL_ASSERT(!rd.IsZero()); 807 SingleEmissionCheckScope guard(this); 808 fcvtps(rd, vn); 809 } Fcvtpu(const Register & rd,const VRegister & vn)810 void Fcvtpu(const Register& rd, const VRegister& vn) { 811 VIXL_ASSERT(!rd.IsZero()); 812 SingleEmissionCheckScope guard(this); 813 fcvtpu(rd, vn); 814 } 815 void Fcvtzs(const Register& rd, const VRegister& vn, int fbits = 0) { 816 VIXL_ASSERT(!rd.IsZero()); 817 SingleEmissionCheckScope guard(this); 818 fcvtzs(rd, vn, fbits); 819 } Fjcvtzs(const Register & rd,const VRegister & vn)820 void Fjcvtzs(const Register& rd, const VRegister& vn) { 821 VIXL_ASSERT(!rd.IsZero()); 822 SingleEmissionCheckScope guard(this); 823 fjcvtzs(rd, vn); 824 } 825 void Fcvtzu(const Register& rd, const VRegister& vn, int fbits = 0) { 826 VIXL_ASSERT(!rd.IsZero()); 827 SingleEmissionCheckScope guard(this); 828 fcvtzu(rd, vn, fbits); 829 } Fdiv(const VRegister & vd,const VRegister & vn,const VRegister & vm)830 void Fdiv(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 831 SingleEmissionCheckScope guard(this); 832 fdiv(vd, vn, vm); 833 } Fmax(const VRegister & vd,const VRegister & vn,const VRegister & vm)834 void Fmax(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 835 SingleEmissionCheckScope guard(this); 836 fmax(vd, vn, vm); 837 } Fmaxnm(const VRegister & vd,const VRegister & vn,const VRegister & vm)838 void Fmaxnm(const VRegister& vd, 839 const VRegister& vn, 840 const VRegister& vm) { 841 SingleEmissionCheckScope guard(this); 842 fmaxnm(vd, vn, vm); 843 } Fmin(const VRegister & vd,const VRegister & vn,const VRegister & vm)844 void Fmin(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 845 SingleEmissionCheckScope guard(this); 846 fmin(vd, vn, vm); 847 } Fminnm(const VRegister & vd,const VRegister & vn,const VRegister & vm)848 void Fminnm(const VRegister& vd, 849 const VRegister& vn, 850 const VRegister& vm) { 851 SingleEmissionCheckScope guard(this); 852 fminnm(vd, vn, vm); 853 } Fmov(VRegister vd,VRegister vn)854 void Fmov(VRegister vd, VRegister vn) { 855 SingleEmissionCheckScope guard(this); 856 // Only emit an instruction if vd and vn are different, and they are both D 857 // registers. fmov(s0, s0) is not a no-op because it clears the top word of 858 // d0. Technically, fmov(d0, d0) is not a no-op either because it clears 859 // the top of q0, but VRegister does not currently support Q registers. 860 if (!vd.Is(vn) || !vd.Is64Bits()) { 861 fmov(vd, vn); 862 } 863 } Fmov(VRegister vd,Register rn)864 void Fmov(VRegister vd, Register rn) { 865 SingleEmissionCheckScope guard(this); 866 fmov(vd, rn); 867 } Fmov(const VRegister & vd,int index,const Register & rn)868 void Fmov(const VRegister& vd, int index, const Register& rn) { 869 SingleEmissionCheckScope guard(this); 870 fmov(vd, index, rn); 871 } Fmov(const Register & rd,const VRegister & vn,int index)872 void Fmov(const Register& rd, const VRegister& vn, int index) { 873 SingleEmissionCheckScope guard(this); 874 fmov(rd, vn, index); 875 } 876 877 // Provide explicit double and float interfaces for FP immediate moves, rather 878 // than relying on implicit C++ casts. This allows signalling NaNs to be 879 // preserved when the immediate matches the format of vd. Most systems convert 880 // signalling NaNs to quiet NaNs when converting between float and double. 881 void Fmov(VRegister vd, double imm); 882 void Fmov(VRegister vd, float imm); 883 // Provide a template to allow other types to be converted automatically. 884 template<typename T> Fmov(VRegister vd,T imm)885 void Fmov(VRegister vd, T imm) { 886 Fmov(vd, static_cast<double>(imm)); 887 } Fmov(Register rd,VRegister vn)888 void Fmov(Register rd, VRegister vn) { 889 VIXL_ASSERT(!rd.IsZero()); 890 SingleEmissionCheckScope guard(this); 891 fmov(rd, vn); 892 } Fmul(const VRegister & vd,const VRegister & vn,const VRegister & vm)893 void Fmul(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 894 SingleEmissionCheckScope guard(this); 895 fmul(vd, vn, vm); 896 } Fnmul(const VRegister & vd,const VRegister & vn,const VRegister & vm)897 void Fnmul(const VRegister& vd, const VRegister& vn, 898 const VRegister& vm) { 899 SingleEmissionCheckScope guard(this); 900 fnmul(vd, vn, vm); 901 } Fmadd(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)902 void Fmadd(const VRegister& vd, 903 const VRegister& vn, 904 const VRegister& vm, 905 const VRegister& va) { 906 SingleEmissionCheckScope guard(this); 907 fmadd(vd, vn, vm, va); 908 } Fmsub(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)909 void Fmsub(const VRegister& vd, 910 const VRegister& vn, 911 const VRegister& vm, 912 const VRegister& va) { 913 SingleEmissionCheckScope guard(this); 914 fmsub(vd, vn, vm, va); 915 } Fnmadd(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)916 void Fnmadd(const VRegister& vd, 917 const VRegister& vn, 918 const VRegister& vm, 919 const VRegister& va) { 920 SingleEmissionCheckScope guard(this); 921 fnmadd(vd, vn, vm, va); 922 } Fnmsub(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)923 void Fnmsub(const VRegister& vd, 924 const VRegister& vn, 925 const VRegister& vm, 926 const VRegister& va) { 927 SingleEmissionCheckScope guard(this); 928 fnmsub(vd, vn, vm, va); 929 } Fsub(const VRegister & vd,const VRegister & vn,const VRegister & vm)930 void Fsub(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 931 SingleEmissionCheckScope guard(this); 932 fsub(vd, vn, vm); 933 } Hint(SystemHint code)934 void Hint(SystemHint code) { 935 SingleEmissionCheckScope guard(this); 936 hint(code); 937 } Hlt(int code)938 void Hlt(int code) { 939 SingleEmissionCheckScope guard(this); 940 hlt(code); 941 } Isb()942 void Isb() { 943 SingleEmissionCheckScope guard(this); 944 isb(); 945 } Ldar(const Register & rt,const MemOperand & src)946 void Ldar(const Register& rt, const MemOperand& src) { 947 SingleEmissionCheckScope guard(this); 948 ldar(rt, src); 949 } Ldarb(const Register & rt,const MemOperand & src)950 void Ldarb(const Register& rt, const MemOperand& src) { 951 SingleEmissionCheckScope guard(this); 952 ldarb(rt, src); 953 } Ldarh(const Register & rt,const MemOperand & src)954 void Ldarh(const Register& rt, const MemOperand& src) { 955 SingleEmissionCheckScope guard(this); 956 ldarh(rt, src); 957 } Ldaxp(const Register & rt,const Register & rt2,const MemOperand & src)958 void Ldaxp(const Register& rt, const Register& rt2, const MemOperand& src) { 959 VIXL_ASSERT(!rt.Aliases(rt2)); 960 SingleEmissionCheckScope guard(this); 961 ldaxp(rt, rt2, src); 962 } Ldaxr(const Register & rt,const MemOperand & src)963 void Ldaxr(const Register& rt, const MemOperand& src) { 964 SingleEmissionCheckScope guard(this); 965 ldaxr(rt, src); 966 } Ldaxrb(const Register & rt,const MemOperand & src)967 void Ldaxrb(const Register& rt, const MemOperand& src) { 968 SingleEmissionCheckScope guard(this); 969 ldaxrb(rt, src); 970 } Ldaxrh(const Register & rt,const MemOperand & src)971 void Ldaxrh(const Register& rt, const MemOperand& src) { 972 SingleEmissionCheckScope guard(this); 973 ldaxrh(rt, src); 974 } Ldnp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & src)975 void Ldnp(const CPURegister& rt, 976 const CPURegister& rt2, 977 const MemOperand& src) { 978 SingleEmissionCheckScope guard(this); 979 ldnp(rt, rt2, src); 980 } 981 // Provide both double and float interfaces for FP immediate loads, rather 982 // than relying on implicit C++ casts. This allows signalling NaNs to be 983 // preserved when the immediate matches the format of fd. Most systems convert 984 // signalling NaNs to quiet NaNs when converting between float and double. Ldr(const VRegister & vt,double imm)985 void Ldr(const VRegister& vt, double imm) { 986 SingleEmissionCheckScope guard(this); 987 if (vt.Is64Bits()) { 988 ldr(vt, imm); 989 } else { 990 ldr(vt, static_cast<float>(imm)); 991 } 992 } Ldr(const VRegister & vt,float imm)993 void Ldr(const VRegister& vt, float imm) { 994 SingleEmissionCheckScope guard(this); 995 if (vt.Is32Bits()) { 996 ldr(vt, imm); 997 } else { 998 ldr(vt, static_cast<double>(imm)); 999 } 1000 } 1001 /* 1002 void Ldr(const VRegister& vt, uint64_t high64, uint64_t low64) { 1003 VIXL_ASSERT(vt.IsQ()); 1004 SingleEmissionCheckScope guard(this); 1005 ldr(vt, new Literal<uint64_t>(high64, low64, 1006 &literal_pool_, 1007 RawLiteral::kDeletedOnPlacementByPool)); 1008 } 1009 */ Ldr(const Register & rt,uint64_t imm)1010 void Ldr(const Register& rt, uint64_t imm) { 1011 VIXL_ASSERT(!rt.IsZero()); 1012 SingleEmissionCheckScope guard(this); 1013 ldr(rt, imm); 1014 } Ldrsw(const Register & rt,uint32_t imm)1015 void Ldrsw(const Register& rt, uint32_t imm) { 1016 VIXL_ASSERT(!rt.IsZero()); 1017 SingleEmissionCheckScope guard(this); 1018 ldrsw(rt, imm); 1019 } Ldxp(const Register & rt,const Register & rt2,const MemOperand & src)1020 void Ldxp(const Register& rt, const Register& rt2, const MemOperand& src) { 1021 VIXL_ASSERT(!rt.Aliases(rt2)); 1022 SingleEmissionCheckScope guard(this); 1023 ldxp(rt, rt2, src); 1024 } Ldxr(const Register & rt,const MemOperand & src)1025 void Ldxr(const Register& rt, const MemOperand& src) { 1026 SingleEmissionCheckScope guard(this); 1027 ldxr(rt, src); 1028 } Ldxrb(const Register & rt,const MemOperand & src)1029 void Ldxrb(const Register& rt, const MemOperand& src) { 1030 SingleEmissionCheckScope guard(this); 1031 ldxrb(rt, src); 1032 } Ldxrh(const Register & rt,const MemOperand & src)1033 void Ldxrh(const Register& rt, const MemOperand& src) { 1034 SingleEmissionCheckScope guard(this); 1035 ldxrh(rt, src); 1036 } Lsl(const Register & rd,const Register & rn,unsigned shift)1037 void Lsl(const Register& rd, const Register& rn, unsigned shift) { 1038 VIXL_ASSERT(!rd.IsZero()); 1039 VIXL_ASSERT(!rn.IsZero()); 1040 SingleEmissionCheckScope guard(this); 1041 lsl(rd, rn, shift); 1042 } Lsl(const Register & rd,const Register & rn,const Register & rm)1043 void Lsl(const Register& rd, const Register& rn, const Register& rm) { 1044 VIXL_ASSERT(!rd.IsZero()); 1045 VIXL_ASSERT(!rn.IsZero()); 1046 VIXL_ASSERT(!rm.IsZero()); 1047 SingleEmissionCheckScope guard(this); 1048 lslv(rd, rn, rm); 1049 } Lsr(const Register & rd,const Register & rn,unsigned shift)1050 void Lsr(const Register& rd, const Register& rn, unsigned shift) { 1051 VIXL_ASSERT(!rd.IsZero()); 1052 VIXL_ASSERT(!rn.IsZero()); 1053 SingleEmissionCheckScope guard(this); 1054 lsr(rd, rn, shift); 1055 } Lsr(const Register & rd,const Register & rn,const Register & rm)1056 void Lsr(const Register& rd, const Register& rn, const Register& rm) { 1057 VIXL_ASSERT(!rd.IsZero()); 1058 VIXL_ASSERT(!rn.IsZero()); 1059 VIXL_ASSERT(!rm.IsZero()); 1060 SingleEmissionCheckScope guard(this); 1061 lsrv(rd, rn, rm); 1062 } Madd(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1063 void Madd(const Register& rd, 1064 const Register& rn, 1065 const Register& rm, 1066 const Register& ra) { 1067 VIXL_ASSERT(!rd.IsZero()); 1068 VIXL_ASSERT(!rn.IsZero()); 1069 VIXL_ASSERT(!rm.IsZero()); 1070 VIXL_ASSERT(!ra.IsZero()); 1071 SingleEmissionCheckScope guard(this); 1072 madd(rd, rn, rm, ra); 1073 } Mneg(const Register & rd,const Register & rn,const Register & rm)1074 void Mneg(const Register& rd, const Register& rn, const Register& rm) { 1075 VIXL_ASSERT(!rd.IsZero()); 1076 VIXL_ASSERT(!rn.IsZero()); 1077 VIXL_ASSERT(!rm.IsZero()); 1078 SingleEmissionCheckScope guard(this); 1079 mneg(rd, rn, rm); 1080 } Mov(const Register & rd,const Register & rn)1081 void Mov(const Register& rd, const Register& rn) { 1082 SingleEmissionCheckScope guard(this); 1083 mov(rd, rn); 1084 } 1085 void Movk(const Register& rd, uint64_t imm, int shift = -1) { 1086 VIXL_ASSERT(!rd.IsZero()); 1087 SingleEmissionCheckScope guard(this); 1088 movk(rd, imm, shift); 1089 } Mrs(const Register & rt,SystemRegister sysreg)1090 void Mrs(const Register& rt, SystemRegister sysreg) { 1091 VIXL_ASSERT(!rt.IsZero()); 1092 SingleEmissionCheckScope guard(this); 1093 mrs(rt, sysreg); 1094 } Msr(SystemRegister sysreg,const Register & rt)1095 void Msr(SystemRegister sysreg, const Register& rt) { 1096 VIXL_ASSERT(!rt.IsZero()); 1097 SingleEmissionCheckScope guard(this); 1098 msr(sysreg, rt); 1099 } 1100 void Sys(int op1, int crn, int crm, int op2, const Register& rt = xzr) { 1101 SingleEmissionCheckScope guard(this); 1102 sys(op1, crn, crm, op2, rt); 1103 } Dc(DataCacheOp op,const Register & rt)1104 void Dc(DataCacheOp op, const Register& rt) { 1105 SingleEmissionCheckScope guard(this); 1106 dc(op, rt); 1107 } Ic(InstructionCacheOp op,const Register & rt)1108 void Ic(InstructionCacheOp op, const Register& rt) { 1109 SingleEmissionCheckScope guard(this); 1110 ic(op, rt); 1111 } Msub(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1112 void Msub(const Register& rd, 1113 const Register& rn, 1114 const Register& rm, 1115 const Register& ra) { 1116 VIXL_ASSERT(!rd.IsZero()); 1117 VIXL_ASSERT(!rn.IsZero()); 1118 VIXL_ASSERT(!rm.IsZero()); 1119 VIXL_ASSERT(!ra.IsZero()); 1120 SingleEmissionCheckScope guard(this); 1121 msub(rd, rn, rm, ra); 1122 } Mul(const Register & rd,const Register & rn,const Register & rm)1123 void Mul(const Register& rd, const Register& rn, const Register& rm) { 1124 VIXL_ASSERT(!rd.IsZero()); 1125 VIXL_ASSERT(!rn.IsZero()); 1126 VIXL_ASSERT(!rm.IsZero()); 1127 SingleEmissionCheckScope guard(this); 1128 mul(rd, rn, rm); 1129 } Nop()1130 void Nop() { 1131 SingleEmissionCheckScope guard(this); 1132 nop(); 1133 } Csdb()1134 void Csdb() { 1135 SingleEmissionCheckScope guard(this); 1136 csdb(); 1137 } Rbit(const Register & rd,const Register & rn)1138 void Rbit(const Register& rd, const Register& rn) { 1139 VIXL_ASSERT(!rd.IsZero()); 1140 VIXL_ASSERT(!rn.IsZero()); 1141 SingleEmissionCheckScope guard(this); 1142 rbit(rd, rn); 1143 } 1144 void Ret(const Register& xn = lr) { 1145 VIXL_ASSERT(!xn.IsZero()); 1146 SingleEmissionCheckScope guard(this); 1147 ret(xn); 1148 } Rev(const Register & rd,const Register & rn)1149 void Rev(const Register& rd, const Register& rn) { 1150 VIXL_ASSERT(!rd.IsZero()); 1151 VIXL_ASSERT(!rn.IsZero()); 1152 SingleEmissionCheckScope guard(this); 1153 rev(rd, rn); 1154 } Rev16(const Register & rd,const Register & rn)1155 void Rev16(const Register& rd, const Register& rn) { 1156 VIXL_ASSERT(!rd.IsZero()); 1157 VIXL_ASSERT(!rn.IsZero()); 1158 SingleEmissionCheckScope guard(this); 1159 rev16(rd, rn); 1160 } Rev32(const Register & rd,const Register & rn)1161 void Rev32(const Register& rd, const Register& rn) { 1162 VIXL_ASSERT(!rd.IsZero()); 1163 VIXL_ASSERT(!rn.IsZero()); 1164 SingleEmissionCheckScope guard(this); 1165 rev32(rd, rn); 1166 } Ror(const Register & rd,const Register & rs,unsigned shift)1167 void Ror(const Register& rd, const Register& rs, unsigned shift) { 1168 VIXL_ASSERT(!rd.IsZero()); 1169 VIXL_ASSERT(!rs.IsZero()); 1170 SingleEmissionCheckScope guard(this); 1171 ror(rd, rs, shift); 1172 } Ror(const Register & rd,const Register & rn,const Register & rm)1173 void Ror(const Register& rd, const Register& rn, const Register& rm) { 1174 VIXL_ASSERT(!rd.IsZero()); 1175 VIXL_ASSERT(!rn.IsZero()); 1176 VIXL_ASSERT(!rm.IsZero()); 1177 SingleEmissionCheckScope guard(this); 1178 rorv(rd, rn, rm); 1179 } Sbfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1180 void Sbfiz(const Register& rd, 1181 const Register& rn, 1182 unsigned lsb, 1183 unsigned width) { 1184 VIXL_ASSERT(!rd.IsZero()); 1185 VIXL_ASSERT(!rn.IsZero()); 1186 SingleEmissionCheckScope guard(this); 1187 sbfiz(rd, rn, lsb, width); 1188 } Sbfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)1189 void Sbfm(const Register& rd, 1190 const Register& rn, 1191 unsigned immr, 1192 unsigned imms) { 1193 VIXL_ASSERT(!rd.IsZero()); 1194 VIXL_ASSERT(!rn.IsZero()); 1195 SingleEmissionCheckScope guard(this); 1196 sbfm(rd, rn, immr, imms); 1197 } Sbfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1198 void Sbfx(const Register& rd, 1199 const Register& rn, 1200 unsigned lsb, 1201 unsigned width) { 1202 VIXL_ASSERT(!rd.IsZero()); 1203 VIXL_ASSERT(!rn.IsZero()); 1204 SingleEmissionCheckScope guard(this); 1205 sbfx(rd, rn, lsb, width); 1206 } 1207 void Scvtf(const VRegister& vd, const Register& rn, int fbits = 0) { 1208 VIXL_ASSERT(!rn.IsZero()); 1209 SingleEmissionCheckScope guard(this); 1210 scvtf(vd, rn, fbits); 1211 } Sdiv(const Register & rd,const Register & rn,const Register & rm)1212 void Sdiv(const Register& rd, const Register& rn, const Register& rm) { 1213 VIXL_ASSERT(!rd.IsZero()); 1214 VIXL_ASSERT(!rn.IsZero()); 1215 VIXL_ASSERT(!rm.IsZero()); 1216 SingleEmissionCheckScope guard(this); 1217 sdiv(rd, rn, rm); 1218 } Smaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1219 void Smaddl(const Register& rd, 1220 const Register& rn, 1221 const Register& rm, 1222 const Register& ra) { 1223 VIXL_ASSERT(!rd.IsZero()); 1224 VIXL_ASSERT(!rn.IsZero()); 1225 VIXL_ASSERT(!rm.IsZero()); 1226 VIXL_ASSERT(!ra.IsZero()); 1227 SingleEmissionCheckScope guard(this); 1228 smaddl(rd, rn, rm, ra); 1229 } Smsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1230 void Smsubl(const Register& rd, 1231 const Register& rn, 1232 const Register& rm, 1233 const Register& ra) { 1234 VIXL_ASSERT(!rd.IsZero()); 1235 VIXL_ASSERT(!rn.IsZero()); 1236 VIXL_ASSERT(!rm.IsZero()); 1237 VIXL_ASSERT(!ra.IsZero()); 1238 SingleEmissionCheckScope guard(this); 1239 smsubl(rd, rn, rm, ra); 1240 } Smull(const Register & rd,const Register & rn,const Register & rm)1241 void Smull(const Register& rd, const Register& rn, const Register& rm) { 1242 VIXL_ASSERT(!rd.IsZero()); 1243 VIXL_ASSERT(!rn.IsZero()); 1244 VIXL_ASSERT(!rm.IsZero()); 1245 SingleEmissionCheckScope guard(this); 1246 smull(rd, rn, rm); 1247 } Smulh(const Register & xd,const Register & xn,const Register & xm)1248 void Smulh(const Register& xd, const Register& xn, const Register& xm) { 1249 VIXL_ASSERT(!xd.IsZero()); 1250 VIXL_ASSERT(!xn.IsZero()); 1251 VIXL_ASSERT(!xm.IsZero()); 1252 SingleEmissionCheckScope guard(this); 1253 smulh(xd, xn, xm); 1254 } Stlr(const Register & rt,const MemOperand & dst)1255 void Stlr(const Register& rt, const MemOperand& dst) { 1256 SingleEmissionCheckScope guard(this); 1257 stlr(rt, dst); 1258 } Stlrb(const Register & rt,const MemOperand & dst)1259 void Stlrb(const Register& rt, const MemOperand& dst) { 1260 SingleEmissionCheckScope guard(this); 1261 stlrb(rt, dst); 1262 } Stlrh(const Register & rt,const MemOperand & dst)1263 void Stlrh(const Register& rt, const MemOperand& dst) { 1264 SingleEmissionCheckScope guard(this); 1265 stlrh(rt, dst); 1266 } Stlxp(const Register & rs,const Register & rt,const Register & rt2,const MemOperand & dst)1267 void Stlxp(const Register& rs, 1268 const Register& rt, 1269 const Register& rt2, 1270 const MemOperand& dst) { 1271 VIXL_ASSERT(!rs.Aliases(dst.base())); 1272 VIXL_ASSERT(!rs.Aliases(rt)); 1273 VIXL_ASSERT(!rs.Aliases(rt2)); 1274 SingleEmissionCheckScope guard(this); 1275 stlxp(rs, rt, rt2, dst); 1276 } Stlxr(const Register & rs,const Register & rt,const MemOperand & dst)1277 void Stlxr(const Register& rs, const Register& rt, const MemOperand& dst) { 1278 VIXL_ASSERT(!rs.Aliases(dst.base())); 1279 VIXL_ASSERT(!rs.Aliases(rt)); 1280 SingleEmissionCheckScope guard(this); 1281 stlxr(rs, rt, dst); 1282 } Stlxrb(const Register & rs,const Register & rt,const MemOperand & dst)1283 void Stlxrb(const Register& rs, const Register& rt, const MemOperand& dst) { 1284 VIXL_ASSERT(!rs.Aliases(dst.base())); 1285 VIXL_ASSERT(!rs.Aliases(rt)); 1286 SingleEmissionCheckScope guard(this); 1287 stlxrb(rs, rt, dst); 1288 } Stlxrh(const Register & rs,const Register & rt,const MemOperand & dst)1289 void Stlxrh(const Register& rs, const Register& rt, const MemOperand& dst) { 1290 VIXL_ASSERT(!rs.Aliases(dst.base())); 1291 VIXL_ASSERT(!rs.Aliases(rt)); 1292 SingleEmissionCheckScope guard(this); 1293 stlxrh(rs, rt, dst); 1294 } Stnp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & dst)1295 void Stnp(const CPURegister& rt, 1296 const CPURegister& rt2, 1297 const MemOperand& dst) { 1298 SingleEmissionCheckScope guard(this); 1299 stnp(rt, rt2, dst); 1300 } Stxp(const Register & rs,const Register & rt,const Register & rt2,const MemOperand & dst)1301 void Stxp(const Register& rs, 1302 const Register& rt, 1303 const Register& rt2, 1304 const MemOperand& dst) { 1305 VIXL_ASSERT(!rs.Aliases(dst.base())); 1306 VIXL_ASSERT(!rs.Aliases(rt)); 1307 VIXL_ASSERT(!rs.Aliases(rt2)); 1308 SingleEmissionCheckScope guard(this); 1309 stxp(rs, rt, rt2, dst); 1310 } Stxr(const Register & rs,const Register & rt,const MemOperand & dst)1311 void Stxr(const Register& rs, const Register& rt, const MemOperand& dst) { 1312 VIXL_ASSERT(!rs.Aliases(dst.base())); 1313 VIXL_ASSERT(!rs.Aliases(rt)); 1314 SingleEmissionCheckScope guard(this); 1315 stxr(rs, rt, dst); 1316 } Stxrb(const Register & rs,const Register & rt,const MemOperand & dst)1317 void Stxrb(const Register& rs, const Register& rt, const MemOperand& dst) { 1318 VIXL_ASSERT(!rs.Aliases(dst.base())); 1319 VIXL_ASSERT(!rs.Aliases(rt)); 1320 SingleEmissionCheckScope guard(this); 1321 stxrb(rs, rt, dst); 1322 } Stxrh(const Register & rs,const Register & rt,const MemOperand & dst)1323 void Stxrh(const Register& rs, const Register& rt, const MemOperand& dst) { 1324 VIXL_ASSERT(!rs.Aliases(dst.base())); 1325 VIXL_ASSERT(!rs.Aliases(rt)); 1326 SingleEmissionCheckScope guard(this); 1327 stxrh(rs, rt, dst); 1328 } Svc(int code)1329 void Svc(int code) { 1330 SingleEmissionCheckScope guard(this); 1331 svc(code); 1332 } Sxtb(const Register & rd,const Register & rn)1333 void Sxtb(const Register& rd, const Register& rn) { 1334 VIXL_ASSERT(!rd.IsZero()); 1335 VIXL_ASSERT(!rn.IsZero()); 1336 SingleEmissionCheckScope guard(this); 1337 sxtb(rd, rn); 1338 } Sxth(const Register & rd,const Register & rn)1339 void Sxth(const Register& rd, const Register& rn) { 1340 VIXL_ASSERT(!rd.IsZero()); 1341 VIXL_ASSERT(!rn.IsZero()); 1342 SingleEmissionCheckScope guard(this); 1343 sxth(rd, rn); 1344 } Sxtw(const Register & rd,const Register & rn)1345 void Sxtw(const Register& rd, const Register& rn) { 1346 VIXL_ASSERT(!rd.IsZero()); 1347 VIXL_ASSERT(!rn.IsZero()); 1348 SingleEmissionCheckScope guard(this); 1349 sxtw(rd, rn); 1350 } Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vm)1351 void Tbl(const VRegister& vd, 1352 const VRegister& vn, 1353 const VRegister& vm) { 1354 SingleEmissionCheckScope guard(this); 1355 tbl(vd, vn, vm); 1356 } Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vm)1357 void Tbl(const VRegister& vd, 1358 const VRegister& vn, 1359 const VRegister& vn2, 1360 const VRegister& vm) { 1361 SingleEmissionCheckScope guard(this); 1362 tbl(vd, vn, vn2, vm); 1363 } Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vm)1364 void Tbl(const VRegister& vd, 1365 const VRegister& vn, 1366 const VRegister& vn2, 1367 const VRegister& vn3, 1368 const VRegister& vm) { 1369 SingleEmissionCheckScope guard(this); 1370 tbl(vd, vn, vn2, vn3, vm); 1371 } Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vn4,const VRegister & vm)1372 void Tbl(const VRegister& vd, 1373 const VRegister& vn, 1374 const VRegister& vn2, 1375 const VRegister& vn3, 1376 const VRegister& vn4, 1377 const VRegister& vm) { 1378 SingleEmissionCheckScope guard(this); 1379 tbl(vd, vn, vn2, vn3, vn4, vm); 1380 } Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vm)1381 void Tbx(const VRegister& vd, 1382 const VRegister& vn, 1383 const VRegister& vm) { 1384 SingleEmissionCheckScope guard(this); 1385 tbx(vd, vn, vm); 1386 } Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vm)1387 void Tbx(const VRegister& vd, 1388 const VRegister& vn, 1389 const VRegister& vn2, 1390 const VRegister& vm) { 1391 SingleEmissionCheckScope guard(this); 1392 tbx(vd, vn, vn2, vm); 1393 } Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vm)1394 void Tbx(const VRegister& vd, 1395 const VRegister& vn, 1396 const VRegister& vn2, 1397 const VRegister& vn3, 1398 const VRegister& vm) { 1399 SingleEmissionCheckScope guard(this); 1400 tbx(vd, vn, vn2, vn3, vm); 1401 } Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vn4,const VRegister & vm)1402 void Tbx(const VRegister& vd, 1403 const VRegister& vn, 1404 const VRegister& vn2, 1405 const VRegister& vn3, 1406 const VRegister& vn4, 1407 const VRegister& vm) { 1408 SingleEmissionCheckScope guard(this); 1409 tbx(vd, vn, vn2, vn3, vn4, vm); 1410 } 1411 void Tbnz(const Register& rt, unsigned bit_pos, Label* label); 1412 void Tbz(const Register& rt, unsigned bit_pos, Label* label); Ubfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1413 void Ubfiz(const Register& rd, 1414 const Register& rn, 1415 unsigned lsb, 1416 unsigned width) { 1417 VIXL_ASSERT(!rd.IsZero()); 1418 VIXL_ASSERT(!rn.IsZero()); 1419 SingleEmissionCheckScope guard(this); 1420 ubfiz(rd, rn, lsb, width); 1421 } Ubfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)1422 void Ubfm(const Register& rd, 1423 const Register& rn, 1424 unsigned immr, 1425 unsigned imms) { 1426 VIXL_ASSERT(!rd.IsZero()); 1427 VIXL_ASSERT(!rn.IsZero()); 1428 SingleEmissionCheckScope guard(this); 1429 ubfm(rd, rn, immr, imms); 1430 } Ubfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1431 void Ubfx(const Register& rd, 1432 const Register& rn, 1433 unsigned lsb, 1434 unsigned width) { 1435 VIXL_ASSERT(!rd.IsZero()); 1436 VIXL_ASSERT(!rn.IsZero()); 1437 SingleEmissionCheckScope guard(this); 1438 ubfx(rd, rn, lsb, width); 1439 } 1440 void Ucvtf(const VRegister& vd, const Register& rn, int fbits = 0) { 1441 VIXL_ASSERT(!rn.IsZero()); 1442 SingleEmissionCheckScope guard(this); 1443 ucvtf(vd, rn, fbits); 1444 } Udiv(const Register & rd,const Register & rn,const Register & rm)1445 void Udiv(const Register& rd, const Register& rn, const Register& rm) { 1446 VIXL_ASSERT(!rd.IsZero()); 1447 VIXL_ASSERT(!rn.IsZero()); 1448 VIXL_ASSERT(!rm.IsZero()); 1449 SingleEmissionCheckScope guard(this); 1450 udiv(rd, rn, rm); 1451 } Umaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1452 void Umaddl(const Register& rd, 1453 const Register& rn, 1454 const Register& rm, 1455 const Register& ra) { 1456 VIXL_ASSERT(!rd.IsZero()); 1457 VIXL_ASSERT(!rn.IsZero()); 1458 VIXL_ASSERT(!rm.IsZero()); 1459 VIXL_ASSERT(!ra.IsZero()); 1460 SingleEmissionCheckScope guard(this); 1461 umaddl(rd, rn, rm, ra); 1462 } Umull(const Register & rd,const Register & rn,const Register & rm)1463 void Umull(const Register& rd, 1464 const Register& rn, 1465 const Register& rm) { 1466 VIXL_ASSERT(!rd.IsZero()); 1467 VIXL_ASSERT(!rn.IsZero()); 1468 VIXL_ASSERT(!rm.IsZero()); 1469 SingleEmissionCheckScope guard(this); 1470 umull(rd, rn, rm); 1471 } Umulh(const Register & xd,const Register & xn,const Register & xm)1472 void Umulh(const Register& xd, const Register& xn, const Register& xm) { 1473 VIXL_ASSERT(!xd.IsZero()); 1474 VIXL_ASSERT(!xn.IsZero()); 1475 VIXL_ASSERT(!xm.IsZero()); 1476 SingleEmissionCheckScope guard(this); 1477 umulh(xd, xn, xm); 1478 } Umsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1479 void Umsubl(const Register& rd, 1480 const Register& rn, 1481 const Register& rm, 1482 const Register& ra) { 1483 VIXL_ASSERT(!rd.IsZero()); 1484 VIXL_ASSERT(!rn.IsZero()); 1485 VIXL_ASSERT(!rm.IsZero()); 1486 VIXL_ASSERT(!ra.IsZero()); 1487 SingleEmissionCheckScope guard(this); 1488 umsubl(rd, rn, rm, ra); 1489 } 1490 Unreachable()1491 void Unreachable() { 1492 SingleEmissionCheckScope guard(this); 1493 Emit(UNDEFINED_INST_PATTERN); 1494 } 1495 Uxtb(const Register & rd,const Register & rn)1496 void Uxtb(const Register& rd, const Register& rn) { 1497 VIXL_ASSERT(!rd.IsZero()); 1498 VIXL_ASSERT(!rn.IsZero()); 1499 SingleEmissionCheckScope guard(this); 1500 uxtb(rd, rn); 1501 } Uxth(const Register & rd,const Register & rn)1502 void Uxth(const Register& rd, const Register& rn) { 1503 VIXL_ASSERT(!rd.IsZero()); 1504 VIXL_ASSERT(!rn.IsZero()); 1505 SingleEmissionCheckScope guard(this); 1506 uxth(rd, rn); 1507 } Uxtw(const Register & rd,const Register & rn)1508 void Uxtw(const Register& rd, const Register& rn) { 1509 VIXL_ASSERT(!rd.IsZero()); 1510 VIXL_ASSERT(!rn.IsZero()); 1511 SingleEmissionCheckScope guard(this); 1512 uxtw(rd, rn); 1513 } 1514 1515 // NEON 3 vector register instructions. 1516 #define NEON_3VREG_MACRO_LIST(V) \ 1517 V(add, Add) \ 1518 V(addhn, Addhn) \ 1519 V(addhn2, Addhn2) \ 1520 V(addp, Addp) \ 1521 V(and_, And) \ 1522 V(bic, Bic) \ 1523 V(bif, Bif) \ 1524 V(bit, Bit) \ 1525 V(bsl, Bsl) \ 1526 V(cmeq, Cmeq) \ 1527 V(cmge, Cmge) \ 1528 V(cmgt, Cmgt) \ 1529 V(cmhi, Cmhi) \ 1530 V(cmhs, Cmhs) \ 1531 V(cmtst, Cmtst) \ 1532 V(eor, Eor) \ 1533 V(fabd, Fabd) \ 1534 V(facge, Facge) \ 1535 V(facgt, Facgt) \ 1536 V(faddp, Faddp) \ 1537 V(fcmeq, Fcmeq) \ 1538 V(fcmge, Fcmge) \ 1539 V(fcmgt, Fcmgt) \ 1540 V(fmaxnmp, Fmaxnmp) \ 1541 V(fmaxp, Fmaxp) \ 1542 V(fminnmp, Fminnmp) \ 1543 V(fminp, Fminp) \ 1544 V(fmla, Fmla) \ 1545 V(fmls, Fmls) \ 1546 V(fmulx, Fmulx) \ 1547 V(frecps, Frecps) \ 1548 V(frsqrts, Frsqrts) \ 1549 V(mla, Mla) \ 1550 V(mls, Mls) \ 1551 V(mul, Mul) \ 1552 V(orn, Orn) \ 1553 V(orr, Orr) \ 1554 V(pmul, Pmul) \ 1555 V(pmull, Pmull) \ 1556 V(pmull2, Pmull2) \ 1557 V(raddhn, Raddhn) \ 1558 V(raddhn2, Raddhn2) \ 1559 V(rsubhn, Rsubhn) \ 1560 V(rsubhn2, Rsubhn2) \ 1561 V(saba, Saba) \ 1562 V(sabal, Sabal) \ 1563 V(sabal2, Sabal2) \ 1564 V(sabd, Sabd) \ 1565 V(sabdl, Sabdl) \ 1566 V(sabdl2, Sabdl2) \ 1567 V(saddl, Saddl) \ 1568 V(saddl2, Saddl2) \ 1569 V(saddw, Saddw) \ 1570 V(saddw2, Saddw2) \ 1571 V(shadd, Shadd) \ 1572 V(shsub, Shsub) \ 1573 V(smax, Smax) \ 1574 V(smaxp, Smaxp) \ 1575 V(smin, Smin) \ 1576 V(sminp, Sminp) \ 1577 V(smlal, Smlal) \ 1578 V(smlal2, Smlal2) \ 1579 V(smlsl, Smlsl) \ 1580 V(smlsl2, Smlsl2) \ 1581 V(smull, Smull) \ 1582 V(smull2, Smull2) \ 1583 V(sqadd, Sqadd) \ 1584 V(sqdmlal, Sqdmlal) \ 1585 V(sqdmlal2, Sqdmlal2) \ 1586 V(sqdmlsl, Sqdmlsl) \ 1587 V(sqdmlsl2, Sqdmlsl2) \ 1588 V(sqdmulh, Sqdmulh) \ 1589 V(sqdmull, Sqdmull) \ 1590 V(sqdmull2, Sqdmull2) \ 1591 V(sqrdmulh, Sqrdmulh) \ 1592 V(sqrshl, Sqrshl) \ 1593 V(sqshl, Sqshl) \ 1594 V(sqsub, Sqsub) \ 1595 V(srhadd, Srhadd) \ 1596 V(srshl, Srshl) \ 1597 V(sshl, Sshl) \ 1598 V(ssubl, Ssubl) \ 1599 V(ssubl2, Ssubl2) \ 1600 V(ssubw, Ssubw) \ 1601 V(ssubw2, Ssubw2) \ 1602 V(sub, Sub) \ 1603 V(subhn, Subhn) \ 1604 V(subhn2, Subhn2) \ 1605 V(trn1, Trn1) \ 1606 V(trn2, Trn2) \ 1607 V(uaba, Uaba) \ 1608 V(uabal, Uabal) \ 1609 V(uabal2, Uabal2) \ 1610 V(uabd, Uabd) \ 1611 V(uabdl, Uabdl) \ 1612 V(uabdl2, Uabdl2) \ 1613 V(uaddl, Uaddl) \ 1614 V(uaddl2, Uaddl2) \ 1615 V(uaddw, Uaddw) \ 1616 V(uaddw2, Uaddw2) \ 1617 V(uhadd, Uhadd) \ 1618 V(uhsub, Uhsub) \ 1619 V(umax, Umax) \ 1620 V(umaxp, Umaxp) \ 1621 V(umin, Umin) \ 1622 V(uminp, Uminp) \ 1623 V(umlal, Umlal) \ 1624 V(umlal2, Umlal2) \ 1625 V(umlsl, Umlsl) \ 1626 V(umlsl2, Umlsl2) \ 1627 V(umull, Umull) \ 1628 V(umull2, Umull2) \ 1629 V(uqadd, Uqadd) \ 1630 V(uqrshl, Uqrshl) \ 1631 V(uqshl, Uqshl) \ 1632 V(uqsub, Uqsub) \ 1633 V(urhadd, Urhadd) \ 1634 V(urshl, Urshl) \ 1635 V(ushl, Ushl) \ 1636 V(usubl, Usubl) \ 1637 V(usubl2, Usubl2) \ 1638 V(usubw, Usubw) \ 1639 V(usubw2, Usubw2) \ 1640 V(uzp1, Uzp1) \ 1641 V(uzp2, Uzp2) \ 1642 V(zip1, Zip1) \ 1643 V(zip2, Zip2) 1644 1645 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 1646 void MASM(const VRegister& vd, \ 1647 const VRegister& vn, \ 1648 const VRegister& vm) { \ 1649 SingleEmissionCheckScope guard(this); \ 1650 ASM(vd, vn, vm); \ 1651 } 1652 NEON_3VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 1653 #undef DEFINE_MACRO_ASM_FUNC 1654 1655 // NEON 2 vector register instructions. 1656 #define NEON_2VREG_MACRO_LIST(V) \ 1657 V(abs, Abs) \ 1658 V(addp, Addp) \ 1659 V(addv, Addv) \ 1660 V(cls, Cls) \ 1661 V(clz, Clz) \ 1662 V(cnt, Cnt) \ 1663 V(fabs, Fabs) \ 1664 V(faddp, Faddp) \ 1665 V(fcvtas, Fcvtas) \ 1666 V(fcvtau, Fcvtau) \ 1667 V(fcvtms, Fcvtms) \ 1668 V(fcvtmu, Fcvtmu) \ 1669 V(fcvtns, Fcvtns) \ 1670 V(fcvtnu, Fcvtnu) \ 1671 V(fcvtps, Fcvtps) \ 1672 V(fcvtpu, Fcvtpu) \ 1673 V(fmaxnmp, Fmaxnmp) \ 1674 V(fmaxnmv, Fmaxnmv) \ 1675 V(fmaxp, Fmaxp) \ 1676 V(fmaxv, Fmaxv) \ 1677 V(fminnmp, Fminnmp) \ 1678 V(fminnmv, Fminnmv) \ 1679 V(fminp, Fminp) \ 1680 V(fminv, Fminv) \ 1681 V(fneg, Fneg) \ 1682 V(frecpe, Frecpe) \ 1683 V(frecpx, Frecpx) \ 1684 V(frinta, Frinta) \ 1685 V(frinti, Frinti) \ 1686 V(frintm, Frintm) \ 1687 V(frintn, Frintn) \ 1688 V(frintp, Frintp) \ 1689 V(frintx, Frintx) \ 1690 V(frintz, Frintz) \ 1691 V(frsqrte, Frsqrte) \ 1692 V(fsqrt, Fsqrt) \ 1693 V(mov, Mov) \ 1694 V(mvn, Mvn) \ 1695 V(neg, Neg) \ 1696 V(not_, Not) \ 1697 V(rbit, Rbit) \ 1698 V(rev16, Rev16) \ 1699 V(rev32, Rev32) \ 1700 V(rev64, Rev64) \ 1701 V(sadalp, Sadalp) \ 1702 V(saddlp, Saddlp) \ 1703 V(saddlv, Saddlv) \ 1704 V(smaxv, Smaxv) \ 1705 V(sminv, Sminv) \ 1706 V(sqabs, Sqabs) \ 1707 V(sqneg, Sqneg) \ 1708 V(sqxtn, Sqxtn) \ 1709 V(sqxtn2, Sqxtn2) \ 1710 V(sqxtun, Sqxtun) \ 1711 V(sqxtun2, Sqxtun2) \ 1712 V(suqadd, Suqadd) \ 1713 V(sxtl, Sxtl) \ 1714 V(sxtl2, Sxtl2) \ 1715 V(uadalp, Uadalp) \ 1716 V(uaddlp, Uaddlp) \ 1717 V(uaddlv, Uaddlv) \ 1718 V(umaxv, Umaxv) \ 1719 V(uminv, Uminv) \ 1720 V(uqxtn, Uqxtn) \ 1721 V(uqxtn2, Uqxtn2) \ 1722 V(urecpe, Urecpe) \ 1723 V(ursqrte, Ursqrte) \ 1724 V(usqadd, Usqadd) \ 1725 V(uxtl, Uxtl) \ 1726 V(uxtl2, Uxtl2) \ 1727 V(xtn, Xtn) \ 1728 V(xtn2, Xtn2) 1729 1730 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 1731 void MASM(const VRegister& vd, \ 1732 const VRegister& vn) { \ 1733 SingleEmissionCheckScope guard(this); \ 1734 ASM(vd, vn); \ 1735 } NEON_2VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)1736 NEON_2VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 1737 #undef DEFINE_MACRO_ASM_FUNC 1738 1739 // NEON 2 vector register with immediate instructions. 1740 #define NEON_2VREG_FPIMM_MACRO_LIST(V) \ 1741 V(fcmeq, Fcmeq) \ 1742 V(fcmge, Fcmge) \ 1743 V(fcmgt, Fcmgt) \ 1744 V(fcmle, Fcmle) \ 1745 V(fcmlt, Fcmlt) 1746 1747 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 1748 void MASM(const VRegister& vd, \ 1749 const VRegister& vn, \ 1750 double imm) { \ 1751 SingleEmissionCheckScope guard(this); \ 1752 ASM(vd, vn, imm); \ 1753 } 1754 NEON_2VREG_FPIMM_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 1755 #undef DEFINE_MACRO_ASM_FUNC 1756 1757 // NEON by element instructions. 1758 #define NEON_BYELEMENT_MACRO_LIST(V) \ 1759 V(fmul, Fmul) \ 1760 V(fmla, Fmla) \ 1761 V(fmls, Fmls) \ 1762 V(fmulx, Fmulx) \ 1763 V(mul, Mul) \ 1764 V(mla, Mla) \ 1765 V(mls, Mls) \ 1766 V(sqdmulh, Sqdmulh) \ 1767 V(sqrdmulh, Sqrdmulh) \ 1768 V(sqdmull, Sqdmull) \ 1769 V(sqdmull2, Sqdmull2) \ 1770 V(sqdmlal, Sqdmlal) \ 1771 V(sqdmlal2, Sqdmlal2) \ 1772 V(sqdmlsl, Sqdmlsl) \ 1773 V(sqdmlsl2, Sqdmlsl2) \ 1774 V(smull, Smull) \ 1775 V(smull2, Smull2) \ 1776 V(smlal, Smlal) \ 1777 V(smlal2, Smlal2) \ 1778 V(smlsl, Smlsl) \ 1779 V(smlsl2, Smlsl2) \ 1780 V(umull, Umull) \ 1781 V(umull2, Umull2) \ 1782 V(umlal, Umlal) \ 1783 V(umlal2, Umlal2) \ 1784 V(umlsl, Umlsl) \ 1785 V(umlsl2, Umlsl2) 1786 1787 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 1788 void MASM(const VRegister& vd, \ 1789 const VRegister& vn, \ 1790 const VRegister& vm, \ 1791 int vm_index \ 1792 ) { \ 1793 SingleEmissionCheckScope guard(this); \ 1794 ASM(vd, vn, vm, vm_index); \ 1795 } 1796 NEON_BYELEMENT_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 1797 #undef DEFINE_MACRO_ASM_FUNC 1798 1799 #define NEON_2VREG_SHIFT_MACRO_LIST(V) \ 1800 V(rshrn, Rshrn) \ 1801 V(rshrn2, Rshrn2) \ 1802 V(shl, Shl) \ 1803 V(shll, Shll) \ 1804 V(shll2, Shll2) \ 1805 V(shrn, Shrn) \ 1806 V(shrn2, Shrn2) \ 1807 V(sli, Sli) \ 1808 V(sqrshrn, Sqrshrn) \ 1809 V(sqrshrn2, Sqrshrn2) \ 1810 V(sqrshrun, Sqrshrun) \ 1811 V(sqrshrun2, Sqrshrun2) \ 1812 V(sqshl, Sqshl) \ 1813 V(sqshlu, Sqshlu) \ 1814 V(sqshrn, Sqshrn) \ 1815 V(sqshrn2, Sqshrn2) \ 1816 V(sqshrun, Sqshrun) \ 1817 V(sqshrun2, Sqshrun2) \ 1818 V(sri, Sri) \ 1819 V(srshr, Srshr) \ 1820 V(srsra, Srsra) \ 1821 V(sshll, Sshll) \ 1822 V(sshll2, Sshll2) \ 1823 V(sshr, Sshr) \ 1824 V(ssra, Ssra) \ 1825 V(uqrshrn, Uqrshrn) \ 1826 V(uqrshrn2, Uqrshrn2) \ 1827 V(uqshl, Uqshl) \ 1828 V(uqshrn, Uqshrn) \ 1829 V(uqshrn2, Uqshrn2) \ 1830 V(urshr, Urshr) \ 1831 V(ursra, Ursra) \ 1832 V(ushll, Ushll) \ 1833 V(ushll2, Ushll2) \ 1834 V(ushr, Ushr) \ 1835 V(usra, Usra) \ 1836 1837 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 1838 void MASM(const VRegister& vd, \ 1839 const VRegister& vn, \ 1840 int shift) { \ 1841 SingleEmissionCheckScope guard(this); \ 1842 ASM(vd, vn, shift); \ 1843 } 1844 NEON_2VREG_SHIFT_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 1845 #undef DEFINE_MACRO_ASM_FUNC 1846 1847 void Bic(const VRegister& vd, 1848 const int imm8, 1849 const int left_shift = 0) { 1850 SingleEmissionCheckScope guard(this); 1851 bic(vd, imm8, left_shift); 1852 } Cmeq(const VRegister & vd,const VRegister & vn,int imm)1853 void Cmeq(const VRegister& vd, 1854 const VRegister& vn, 1855 int imm) { 1856 SingleEmissionCheckScope guard(this); 1857 cmeq(vd, vn, imm); 1858 } Cmge(const VRegister & vd,const VRegister & vn,int imm)1859 void Cmge(const VRegister& vd, 1860 const VRegister& vn, 1861 int imm) { 1862 SingleEmissionCheckScope guard(this); 1863 cmge(vd, vn, imm); 1864 } Cmgt(const VRegister & vd,const VRegister & vn,int imm)1865 void Cmgt(const VRegister& vd, 1866 const VRegister& vn, 1867 int imm) { 1868 SingleEmissionCheckScope guard(this); 1869 cmgt(vd, vn, imm); 1870 } Cmle(const VRegister & vd,const VRegister & vn,int imm)1871 void Cmle(const VRegister& vd, 1872 const VRegister& vn, 1873 int imm) { 1874 SingleEmissionCheckScope guard(this); 1875 cmle(vd, vn, imm); 1876 } Cmlt(const VRegister & vd,const VRegister & vn,int imm)1877 void Cmlt(const VRegister& vd, 1878 const VRegister& vn, 1879 int imm) { 1880 SingleEmissionCheckScope guard(this); 1881 cmlt(vd, vn, imm); 1882 } Dup(const VRegister & vd,const VRegister & vn,int index)1883 void Dup(const VRegister& vd, 1884 const VRegister& vn, 1885 int index) { 1886 SingleEmissionCheckScope guard(this); 1887 dup(vd, vn, index); 1888 } Dup(const VRegister & vd,const Register & rn)1889 void Dup(const VRegister& vd, 1890 const Register& rn) { 1891 SingleEmissionCheckScope guard(this); 1892 dup(vd, rn); 1893 } Ext(const VRegister & vd,const VRegister & vn,const VRegister & vm,int index)1894 void Ext(const VRegister& vd, 1895 const VRegister& vn, 1896 const VRegister& vm, 1897 int index) { 1898 SingleEmissionCheckScope guard(this); 1899 ext(vd, vn, vm, index); 1900 } Ins(const VRegister & vd,int vd_index,const VRegister & vn,int vn_index)1901 void Ins(const VRegister& vd, 1902 int vd_index, 1903 const VRegister& vn, 1904 int vn_index) { 1905 SingleEmissionCheckScope guard(this); 1906 ins(vd, vd_index, vn, vn_index); 1907 } Ins(const VRegister & vd,int vd_index,const Register & rn)1908 void Ins(const VRegister& vd, 1909 int vd_index, 1910 const Register& rn) { 1911 SingleEmissionCheckScope guard(this); 1912 ins(vd, vd_index, rn); 1913 } Ld1(const VRegister & vt,const MemOperand & src)1914 void Ld1(const VRegister& vt, 1915 const MemOperand& src) { 1916 SingleEmissionCheckScope guard(this); 1917 ld1(vt, src); 1918 } Ld1(const VRegister & vt,const VRegister & vt2,const MemOperand & src)1919 void Ld1(const VRegister& vt, 1920 const VRegister& vt2, 1921 const MemOperand& src) { 1922 SingleEmissionCheckScope guard(this); 1923 ld1(vt, vt2, src); 1924 } Ld1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)1925 void Ld1(const VRegister& vt, 1926 const VRegister& vt2, 1927 const VRegister& vt3, 1928 const MemOperand& src) { 1929 SingleEmissionCheckScope guard(this); 1930 ld1(vt, vt2, vt3, src); 1931 } Ld1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)1932 void Ld1(const VRegister& vt, 1933 const VRegister& vt2, 1934 const VRegister& vt3, 1935 const VRegister& vt4, 1936 const MemOperand& src) { 1937 SingleEmissionCheckScope guard(this); 1938 ld1(vt, vt2, vt3, vt4, src); 1939 } Ld1(const VRegister & vt,int lane,const MemOperand & src)1940 void Ld1(const VRegister& vt, 1941 int lane, 1942 const MemOperand& src) { 1943 SingleEmissionCheckScope guard(this); 1944 ld1(vt, lane, src); 1945 } Ld1r(const VRegister & vt,const MemOperand & src)1946 void Ld1r(const VRegister& vt, 1947 const MemOperand& src) { 1948 SingleEmissionCheckScope guard(this); 1949 ld1r(vt, src); 1950 } Ld2(const VRegister & vt,const VRegister & vt2,const MemOperand & src)1951 void Ld2(const VRegister& vt, 1952 const VRegister& vt2, 1953 const MemOperand& src) { 1954 SingleEmissionCheckScope guard(this); 1955 ld2(vt, vt2, src); 1956 } Ld2(const VRegister & vt,const VRegister & vt2,int lane,const MemOperand & src)1957 void Ld2(const VRegister& vt, 1958 const VRegister& vt2, 1959 int lane, 1960 const MemOperand& src) { 1961 SingleEmissionCheckScope guard(this); 1962 ld2(vt, vt2, lane, src); 1963 } Ld2r(const VRegister & vt,const VRegister & vt2,const MemOperand & src)1964 void Ld2r(const VRegister& vt, 1965 const VRegister& vt2, 1966 const MemOperand& src) { 1967 SingleEmissionCheckScope guard(this); 1968 ld2r(vt, vt2, src); 1969 } Ld3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)1970 void Ld3(const VRegister& vt, 1971 const VRegister& vt2, 1972 const VRegister& vt3, 1973 const MemOperand& src) { 1974 SingleEmissionCheckScope guard(this); 1975 ld3(vt, vt2, vt3, src); 1976 } Ld3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,int lane,const MemOperand & src)1977 void Ld3(const VRegister& vt, 1978 const VRegister& vt2, 1979 const VRegister& vt3, 1980 int lane, 1981 const MemOperand& src) { 1982 SingleEmissionCheckScope guard(this); 1983 ld3(vt, vt2, vt3, lane, src); 1984 } Ld3r(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)1985 void Ld3r(const VRegister& vt, 1986 const VRegister& vt2, 1987 const VRegister& vt3, 1988 const MemOperand& src) { 1989 SingleEmissionCheckScope guard(this); 1990 ld3r(vt, vt2, vt3, src); 1991 } Ld4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)1992 void Ld4(const VRegister& vt, 1993 const VRegister& vt2, 1994 const VRegister& vt3, 1995 const VRegister& vt4, 1996 const MemOperand& src) { 1997 SingleEmissionCheckScope guard(this); 1998 ld4(vt, vt2, vt3, vt4, src); 1999 } Ld4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,int lane,const MemOperand & src)2000 void Ld4(const VRegister& vt, 2001 const VRegister& vt2, 2002 const VRegister& vt3, 2003 const VRegister& vt4, 2004 int lane, 2005 const MemOperand& src) { 2006 SingleEmissionCheckScope guard(this); 2007 ld4(vt, vt2, vt3, vt4, lane, src); 2008 } Ld4r(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)2009 void Ld4r(const VRegister& vt, 2010 const VRegister& vt2, 2011 const VRegister& vt3, 2012 const VRegister& vt4, 2013 const MemOperand& src) { 2014 SingleEmissionCheckScope guard(this); 2015 ld4r(vt, vt2, vt3, vt4, src); 2016 } Mov(const VRegister & vd,int vd_index,const VRegister & vn,int vn_index)2017 void Mov(const VRegister& vd, 2018 int vd_index, 2019 const VRegister& vn, 2020 int vn_index) { 2021 SingleEmissionCheckScope guard(this); 2022 mov(vd, vd_index, vn, vn_index); 2023 } Mov(const VRegister & vd,const VRegister & vn,int index)2024 void Mov(const VRegister& vd, 2025 const VRegister& vn, 2026 int index) { 2027 SingleEmissionCheckScope guard(this); 2028 mov(vd, vn, index); 2029 } Mov(const VRegister & vd,int vd_index,const Register & rn)2030 void Mov(const VRegister& vd, 2031 int vd_index, 2032 const Register& rn) { 2033 SingleEmissionCheckScope guard(this); 2034 mov(vd, vd_index, rn); 2035 } Mov(const Register & rd,const VRegister & vn,int vn_index)2036 void Mov(const Register& rd, 2037 const VRegister& vn, 2038 int vn_index) { 2039 SingleEmissionCheckScope guard(this); 2040 mov(rd, vn, vn_index); 2041 } 2042 void Movi(const VRegister& vd, 2043 uint64_t imm, 2044 Shift shift = LSL, 2045 int shift_amount = 0); 2046 void Movi(const VRegister& vd, uint64_t hi, uint64_t lo); 2047 void Mvni(const VRegister& vd, 2048 const int imm8, 2049 Shift shift = LSL, 2050 const int shift_amount = 0) { 2051 SingleEmissionCheckScope guard(this); 2052 mvni(vd, imm8, shift, shift_amount); 2053 } 2054 void Orr(const VRegister& vd, 2055 const int imm8, 2056 const int left_shift = 0) { 2057 SingleEmissionCheckScope guard(this); 2058 orr(vd, imm8, left_shift); 2059 } 2060 void Scvtf(const VRegister& vd, 2061 const VRegister& vn, 2062 int fbits = 0) { 2063 SingleEmissionCheckScope guard(this); 2064 scvtf(vd, vn, fbits); 2065 } 2066 void Ucvtf(const VRegister& vd, 2067 const VRegister& vn, 2068 int fbits = 0) { 2069 SingleEmissionCheckScope guard(this); 2070 ucvtf(vd, vn, fbits); 2071 } 2072 void Fcvtzs(const VRegister& vd, 2073 const VRegister& vn, 2074 int fbits = 0) { 2075 SingleEmissionCheckScope guard(this); 2076 fcvtzs(vd, vn, fbits); 2077 } 2078 void Fcvtzu(const VRegister& vd, 2079 const VRegister& vn, 2080 int fbits = 0) { 2081 SingleEmissionCheckScope guard(this); 2082 fcvtzu(vd, vn, fbits); 2083 } St1(const VRegister & vt,const MemOperand & dst)2084 void St1(const VRegister& vt, 2085 const MemOperand& dst) { 2086 SingleEmissionCheckScope guard(this); 2087 st1(vt, dst); 2088 } St1(const VRegister & vt,const VRegister & vt2,const MemOperand & dst)2089 void St1(const VRegister& vt, 2090 const VRegister& vt2, 2091 const MemOperand& dst) { 2092 SingleEmissionCheckScope guard(this); 2093 st1(vt, vt2, dst); 2094 } St1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & dst)2095 void St1(const VRegister& vt, 2096 const VRegister& vt2, 2097 const VRegister& vt3, 2098 const MemOperand& dst) { 2099 SingleEmissionCheckScope guard(this); 2100 st1(vt, vt2, vt3, dst); 2101 } St1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & dst)2102 void St1(const VRegister& vt, 2103 const VRegister& vt2, 2104 const VRegister& vt3, 2105 const VRegister& vt4, 2106 const MemOperand& dst) { 2107 SingleEmissionCheckScope guard(this); 2108 st1(vt, vt2, vt3, vt4, dst); 2109 } St1(const VRegister & vt,int lane,const MemOperand & dst)2110 void St1(const VRegister& vt, 2111 int lane, 2112 const MemOperand& dst) { 2113 SingleEmissionCheckScope guard(this); 2114 st1(vt, lane, dst); 2115 } St2(const VRegister & vt,const VRegister & vt2,const MemOperand & dst)2116 void St2(const VRegister& vt, 2117 const VRegister& vt2, 2118 const MemOperand& dst) { 2119 SingleEmissionCheckScope guard(this); 2120 st2(vt, vt2, dst); 2121 } St3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & dst)2122 void St3(const VRegister& vt, 2123 const VRegister& vt2, 2124 const VRegister& vt3, 2125 const MemOperand& dst) { 2126 SingleEmissionCheckScope guard(this); 2127 st3(vt, vt2, vt3, dst); 2128 } St4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & dst)2129 void St4(const VRegister& vt, 2130 const VRegister& vt2, 2131 const VRegister& vt3, 2132 const VRegister& vt4, 2133 const MemOperand& dst) { 2134 SingleEmissionCheckScope guard(this); 2135 st4(vt, vt2, vt3, vt4, dst); 2136 } St2(const VRegister & vt,const VRegister & vt2,int lane,const MemOperand & dst)2137 void St2(const VRegister& vt, 2138 const VRegister& vt2, 2139 int lane, 2140 const MemOperand& dst) { 2141 SingleEmissionCheckScope guard(this); 2142 st2(vt, vt2, lane, dst); 2143 } St3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,int lane,const MemOperand & dst)2144 void St3(const VRegister& vt, 2145 const VRegister& vt2, 2146 const VRegister& vt3, 2147 int lane, 2148 const MemOperand& dst) { 2149 SingleEmissionCheckScope guard(this); 2150 st3(vt, vt2, vt3, lane, dst); 2151 } St4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,int lane,const MemOperand & dst)2152 void St4(const VRegister& vt, 2153 const VRegister& vt2, 2154 const VRegister& vt3, 2155 const VRegister& vt4, 2156 int lane, 2157 const MemOperand& dst) { 2158 SingleEmissionCheckScope guard(this); 2159 st4(vt, vt2, vt3, vt4, lane, dst); 2160 } Smov(const Register & rd,const VRegister & vn,int vn_index)2161 void Smov(const Register& rd, 2162 const VRegister& vn, 2163 int vn_index) { 2164 SingleEmissionCheckScope guard(this); 2165 smov(rd, vn, vn_index); 2166 } Umov(const Register & rd,const VRegister & vn,int vn_index)2167 void Umov(const Register& rd, 2168 const VRegister& vn, 2169 int vn_index) { 2170 SingleEmissionCheckScope guard(this); 2171 umov(rd, vn, vn_index); 2172 } Crc32b(const Register & rd,const Register & rn,const Register & rm)2173 void Crc32b(const Register& rd, 2174 const Register& rn, 2175 const Register& rm) { 2176 SingleEmissionCheckScope guard(this); 2177 crc32b(rd, rn, rm); 2178 } Crc32h(const Register & rd,const Register & rn,const Register & rm)2179 void Crc32h(const Register& rd, 2180 const Register& rn, 2181 const Register& rm) { 2182 SingleEmissionCheckScope guard(this); 2183 crc32h(rd, rn, rm); 2184 } Crc32w(const Register & rd,const Register & rn,const Register & rm)2185 void Crc32w(const Register& rd, 2186 const Register& rn, 2187 const Register& rm) { 2188 SingleEmissionCheckScope guard(this); 2189 crc32w(rd, rn, rm); 2190 } Crc32x(const Register & rd,const Register & rn,const Register & rm)2191 void Crc32x(const Register& rd, 2192 const Register& rn, 2193 const Register& rm) { 2194 SingleEmissionCheckScope guard(this); 2195 crc32x(rd, rn, rm); 2196 } Crc32cb(const Register & rd,const Register & rn,const Register & rm)2197 void Crc32cb(const Register& rd, 2198 const Register& rn, 2199 const Register& rm) { 2200 SingleEmissionCheckScope guard(this); 2201 crc32cb(rd, rn, rm); 2202 } Crc32ch(const Register & rd,const Register & rn,const Register & rm)2203 void Crc32ch(const Register& rd, 2204 const Register& rn, 2205 const Register& rm) { 2206 SingleEmissionCheckScope guard(this); 2207 crc32ch(rd, rn, rm); 2208 } Crc32cw(const Register & rd,const Register & rn,const Register & rm)2209 void Crc32cw(const Register& rd, 2210 const Register& rn, 2211 const Register& rm) { 2212 SingleEmissionCheckScope guard(this); 2213 crc32cw(rd, rn, rm); 2214 } Crc32cx(const Register & rd,const Register & rn,const Register & rm)2215 void Crc32cx(const Register& rd, 2216 const Register& rn, 2217 const Register& rm) { 2218 SingleEmissionCheckScope guard(this); 2219 crc32cx(rd, rn, rm); 2220 } 2221 2222 // Push the system stack pointer (sp) down to allow the same to be done to 2223 // the current stack pointer (according to StackPointer()). This must be 2224 // called _before_ accessing the memory. 2225 // 2226 // This is necessary when pushing or otherwise adding things to the stack, to 2227 // satisfy the AAPCS64 constraint that the memory below the system stack 2228 // pointer is not accessed. 2229 // 2230 // This method asserts that StackPointer() is not sp, since the call does 2231 // not make sense in that context. 2232 // 2233 // TODO: This method can only accept values of 'space' that can be encoded in 2234 // one instruction. Refer to the implementation for details. 2235 void BumpSystemStackPointer(const Operand& space); 2236 2237 // Set the current stack pointer, but don't generate any code. SetStackPointer64(const Register & stack_pointer)2238 void SetStackPointer64(const Register& stack_pointer) { 2239 VIXL_ASSERT(!TmpList()->IncludesAliasOf(stack_pointer)); 2240 sp_ = stack_pointer; 2241 } 2242 2243 // Return the current stack pointer, as set by SetStackPointer. StackPointer()2244 const Register& StackPointer() const { 2245 return sp_; 2246 } 2247 GetStackPointer64()2248 const Register& GetStackPointer64() const { 2249 return sp_; 2250 } 2251 getStackPointer()2252 js::jit::RegisterOrSP getStackPointer() const { 2253 return js::jit::RegisterOrSP(sp_.code()); 2254 } 2255 TmpList()2256 CPURegList* TmpList() { return &tmp_list_; } FPTmpList()2257 CPURegList* FPTmpList() { return &fptmp_list_; } 2258 2259 // Trace control when running the debug simulator. 2260 // 2261 // For example: 2262 // 2263 // __ Trace(LOG_REGS, TRACE_ENABLE); 2264 // Will add registers to the trace if it wasn't already the case. 2265 // 2266 // __ Trace(LOG_DISASM, TRACE_DISABLE); 2267 // Will stop logging disassembly. It has no effect if the disassembly wasn't 2268 // already being logged. 2269 void Trace(TraceParameters parameters, TraceCommand command); 2270 2271 // Log the requested data independently of what is being traced. 2272 // 2273 // For example: 2274 // 2275 // __ Log(LOG_FLAGS) 2276 // Will output the flags. 2277 void Log(TraceParameters parameters); 2278 2279 // Enable or disable instrumentation when an Instrument visitor is attached to 2280 // the simulator. 2281 void EnableInstrumentation(); 2282 void DisableInstrumentation(); 2283 2284 // Add a marker to the instrumentation data produced by an Instrument visitor. 2285 // The name is a two character string that will be attached to the marker in 2286 // the output data. 2287 void AnnotateInstrumentation(const char* marker_name); 2288 2289 private: 2290 // The actual Push and Pop implementations. These don't generate any code 2291 // other than that required for the push or pop. This allows 2292 // (Push|Pop)CPURegList to bundle together setup code for a large block of 2293 // registers. 2294 // 2295 // Note that size is per register, and is specified in bytes. 2296 void PushHelper(int count, int size, 2297 const CPURegister& src0, const CPURegister& src1, 2298 const CPURegister& src2, const CPURegister& src3); 2299 void PopHelper(int count, int size, 2300 const CPURegister& dst0, const CPURegister& dst1, 2301 const CPURegister& dst2, const CPURegister& dst3); 2302 2303 void Movi16bitHelper(const VRegister& vd, uint64_t imm); 2304 void Movi32bitHelper(const VRegister& vd, uint64_t imm); 2305 void Movi64bitHelper(const VRegister& vd, uint64_t imm); 2306 2307 // Perform necessary maintenance operations before a push or pop. 2308 // 2309 // Note that size is per register, and is specified in bytes. 2310 void PrepareForPush(int count, int size); 2311 void PrepareForPop(int count, int size); 2312 2313 // The actual implementation of load and store operations for CPURegList. 2314 enum LoadStoreCPURegListAction { 2315 kLoad, 2316 kStore 2317 }; 2318 void LoadStoreCPURegListHelper(LoadStoreCPURegListAction operation, 2319 CPURegList registers, 2320 const MemOperand& mem); 2321 // Returns a MemOperand suitable for loading or storing a CPURegList at `dst`. 2322 // This helper may allocate registers from `scratch_scope` and generate code 2323 // to compute an intermediate address. The resulting MemOperand is only valid 2324 // as long as `scratch_scope` remains valid. 2325 MemOperand BaseMemOperandForLoadStoreCPURegList( 2326 const CPURegList& registers, 2327 const MemOperand& mem, 2328 UseScratchRegisterScope* scratch_scope); 2329 LabelIsOutOfRange(Label * label,ImmBranchType branch_type)2330 bool LabelIsOutOfRange(Label* label, ImmBranchType branch_type) { 2331 return !Instruction::IsValidImmPCOffset(branch_type, nextOffset().getOffset() - label->offset()); 2332 } 2333 2334 // The register to use as a stack pointer for stack operations. 2335 Register sp_; 2336 2337 // Scratch registers available for use by the MacroAssembler. 2338 CPURegList tmp_list_; 2339 CPURegList fptmp_list_; 2340 2341 ptrdiff_t checkpoint_; 2342 ptrdiff_t recommended_checkpoint_; 2343 }; 2344 2345 2346 // All Assembler emits MUST acquire/release the underlying code buffer. The 2347 // helper scope below will do so and optionally ensure the buffer is big enough 2348 // to receive the emit. It is possible to request the scope not to perform any 2349 // checks (kNoCheck) if for example it is known in advance the buffer size is 2350 // adequate or there is some other size checking mechanism in place. 2351 class CodeBufferCheckScope { 2352 public: 2353 // Tell whether or not the scope needs to ensure the associated CodeBuffer 2354 // has enough space for the requested size. 2355 enum CheckPolicy { 2356 kNoCheck, 2357 kCheck 2358 }; 2359 2360 // Tell whether or not the scope should assert the amount of code emitted 2361 // within the scope is consistent with the requested amount. 2362 enum AssertPolicy { 2363 kNoAssert, // No assert required. 2364 kExactSize, // The code emitted must be exactly size bytes. 2365 kMaximumSize // The code emitted must be at most size bytes. 2366 }; 2367 2368 CodeBufferCheckScope(Assembler* assm, 2369 size_t size, 2370 CheckPolicy check_policy = kCheck, 2371 AssertPolicy assert_policy = kMaximumSize) 2372 { } 2373 2374 // This is a shortcut for CodeBufferCheckScope(assm, 0, kNoCheck, kNoAssert). CodeBufferCheckScope(Assembler * assm)2375 explicit CodeBufferCheckScope(Assembler* assm) {} 2376 }; 2377 2378 2379 // Use this scope when you need a one-to-one mapping between methods and 2380 // instructions. This scope prevents the MacroAssembler from being called and 2381 // literal pools from being emitted. It also asserts the number of instructions 2382 // emitted is what you specified when creating the scope. 2383 // FIXME: Because of the disabled calls below, this class asserts nothing. 2384 class InstructionAccurateScope : public CodeBufferCheckScope { 2385 public: 2386 InstructionAccurateScope(MacroAssembler* masm, 2387 int64_t count, 2388 AssertPolicy policy = kExactSize) 2389 : CodeBufferCheckScope(masm, 2390 (count * kInstructionSize), 2391 kCheck, 2392 policy) { 2393 } 2394 }; 2395 2396 2397 // This scope utility allows scratch registers to be managed safely. The 2398 // MacroAssembler's TmpList() (and FPTmpList()) is used as a pool of scratch 2399 // registers. These registers can be allocated on demand, and will be returned 2400 // at the end of the scope. 2401 // 2402 // When the scope ends, the MacroAssembler's lists will be restored to their 2403 // original state, even if the lists were modified by some other means. 2404 class UseScratchRegisterScope { 2405 public: 2406 // This constructor implicitly calls the `Open` function to initialise the 2407 // scope, so it is ready to use immediately after it has been constructed. 2408 explicit UseScratchRegisterScope(MacroAssembler* masm); 2409 // This constructor allows deferred and optional initialisation of the scope. 2410 // The user is required to explicitly call the `Open` function before using 2411 // the scope. 2412 UseScratchRegisterScope(); 2413 // This function performs the actual initialisation work. 2414 void Open(MacroAssembler* masm); 2415 2416 // The destructor always implicitly calls the `Close` function. 2417 ~UseScratchRegisterScope(); 2418 // This function performs the cleaning-up work. It must succeed even if the 2419 // scope has not been opened. It is safe to call multiple times. 2420 void Close(); 2421 2422 2423 bool IsAvailable(const CPURegister& reg) const; 2424 2425 2426 // Take a register from the appropriate temps list. It will be returned 2427 // automatically when the scope ends. AcquireW()2428 Register AcquireW() { return AcquireNextAvailable(available_).W(); } AcquireX()2429 Register AcquireX() { return AcquireNextAvailable(available_).X(); } AcquireS()2430 VRegister AcquireS() { return AcquireNextAvailable(availablefp_).S(); } AcquireD()2431 VRegister AcquireD() { return AcquireNextAvailable(availablefp_).D(); } AcquireQ()2432 VRegister AcquireQ() { return AcquireNextAvailable(availablefp_).Q(); } 2433 2434 2435 Register AcquireSameSizeAs(const Register& reg); 2436 VRegister AcquireSameSizeAs(const VRegister& reg); 2437 2438 2439 // Explicitly release an acquired (or excluded) register, putting it back in 2440 // the appropriate temps list. 2441 void Release(const CPURegister& reg); 2442 2443 2444 // Make the specified registers available as scratch registers for the 2445 // duration of this scope. 2446 void Include(const CPURegList& list); 2447 void Include(const Register& reg1, 2448 const Register& reg2 = NoReg, 2449 const Register& reg3 = NoReg, 2450 const Register& reg4 = NoReg); 2451 void Include(const VRegister& reg1, 2452 const VRegister& reg2 = NoVReg, 2453 const VRegister& reg3 = NoVReg, 2454 const VRegister& reg4 = NoVReg); 2455 2456 2457 // Make sure that the specified registers are not available in this scope. 2458 // This can be used to prevent helper functions from using sensitive 2459 // registers, for example. 2460 void Exclude(const CPURegList& list); 2461 void Exclude(const Register& reg1, 2462 const Register& reg2 = NoReg, 2463 const Register& reg3 = NoReg, 2464 const Register& reg4 = NoReg); 2465 void Exclude(const VRegister& reg1, 2466 const VRegister& reg2 = NoVReg, 2467 const VRegister& reg3 = NoVReg, 2468 const VRegister& reg4 = NoVReg); 2469 void Exclude(const CPURegister& reg1, 2470 const CPURegister& reg2 = NoCPUReg, 2471 const CPURegister& reg3 = NoCPUReg, 2472 const CPURegister& reg4 = NoCPUReg); 2473 2474 2475 // Prevent any scratch registers from being used in this scope. 2476 void ExcludeAll(); 2477 2478 2479 private: 2480 static CPURegister AcquireNextAvailable(CPURegList* available); 2481 2482 static void ReleaseByCode(CPURegList* available, int code); 2483 2484 static void ReleaseByRegList(CPURegList* available, 2485 RegList regs); 2486 2487 static void IncludeByRegList(CPURegList* available, 2488 RegList exclude); 2489 2490 static void ExcludeByRegList(CPURegList* available, 2491 RegList exclude); 2492 2493 // Available scratch registers. 2494 CPURegList* available_; // kRegister 2495 CPURegList* availablefp_; // kVRegister 2496 2497 // The state of the available lists at the start of this scope. 2498 RegList old_available_; // kRegister 2499 RegList old_availablefp_; // kVRegister 2500 #ifdef DEBUG 2501 bool initialised_; 2502 #endif 2503 2504 // Disallow copy constructor and operator=. UseScratchRegisterScope(const UseScratchRegisterScope &)2505 UseScratchRegisterScope(const UseScratchRegisterScope&) { 2506 VIXL_UNREACHABLE(); 2507 } 2508 void operator=(const UseScratchRegisterScope&) { 2509 VIXL_UNREACHABLE(); 2510 } 2511 }; 2512 2513 2514 } // namespace vixl 2515 2516 #endif // VIXL_A64_MACRO_ASSEMBLER_A64_H_ 2517