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 VIXL_ASSERT(!rn.IsZero()); 660 VIXL_ASSERT(!rm.IsZero()); 661 VIXL_ASSERT((cond != al) && (cond != nv)); 662 SingleEmissionCheckScope guard(this); 663 csinc(rd, rn, rm, cond); 664 } Csinv(const Register & rd,const Register & rn,const Register & rm,Condition cond)665 void Csinv(const Register& rd, 666 const Register& rn, 667 const Register& rm, 668 Condition cond) { 669 VIXL_ASSERT(!rd.IsZero()); 670 VIXL_ASSERT(!rn.IsZero()); 671 VIXL_ASSERT(!rm.IsZero()); 672 VIXL_ASSERT((cond != al) && (cond != nv)); 673 SingleEmissionCheckScope guard(this); 674 csinv(rd, rn, rm, cond); 675 } Csneg(const Register & rd,const Register & rn,const Register & rm,Condition cond)676 void Csneg(const Register& rd, 677 const Register& rn, 678 const Register& rm, 679 Condition cond) { 680 VIXL_ASSERT(!rd.IsZero()); 681 VIXL_ASSERT(!rn.IsZero()); 682 VIXL_ASSERT(!rm.IsZero()); 683 VIXL_ASSERT((cond != al) && (cond != nv)); 684 SingleEmissionCheckScope guard(this); 685 csneg(rd, rn, rm, cond); 686 } Dmb(BarrierDomain domain,BarrierType type)687 void Dmb(BarrierDomain domain, BarrierType type) { 688 SingleEmissionCheckScope guard(this); 689 dmb(domain, type); 690 } Dsb(BarrierDomain domain,BarrierType type)691 void Dsb(BarrierDomain domain, BarrierType type) { 692 SingleEmissionCheckScope guard(this); 693 dsb(domain, type); 694 } Extr(const Register & rd,const Register & rn,const Register & rm,unsigned lsb)695 void Extr(const Register& rd, 696 const Register& rn, 697 const Register& rm, 698 unsigned lsb) { 699 VIXL_ASSERT(!rd.IsZero()); 700 VIXL_ASSERT(!rn.IsZero()); 701 VIXL_ASSERT(!rm.IsZero()); 702 SingleEmissionCheckScope guard(this); 703 extr(rd, rn, rm, lsb); 704 } Fadd(const VRegister & vd,const VRegister & vn,const VRegister & vm)705 void Fadd(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 706 SingleEmissionCheckScope guard(this); 707 fadd(vd, vn, vm); 708 } 709 void Fccmp(const VRegister& vn, 710 const VRegister& vm, 711 StatusFlags nzcv, 712 Condition cond, 713 FPTrapFlags trap = DisableTrap) { 714 VIXL_ASSERT((cond != al) && (cond != nv)); 715 SingleEmissionCheckScope guard(this); 716 FPCCompareMacro(vn, vm, nzcv, cond, trap); 717 } Fccmpe(const VRegister & vn,const VRegister & vm,StatusFlags nzcv,Condition cond)718 void Fccmpe(const VRegister& vn, 719 const VRegister& vm, 720 StatusFlags nzcv, 721 Condition cond) { 722 Fccmp(vn, vm, nzcv, cond, EnableTrap); 723 } 724 void Fcmp(const VRegister& vn, const VRegister& vm, 725 FPTrapFlags trap = DisableTrap) { 726 SingleEmissionCheckScope guard(this); 727 FPCompareMacro(vn, vm, trap); 728 } 729 void Fcmp(const VRegister& vn, double value, 730 FPTrapFlags trap = DisableTrap); 731 void Fcmpe(const VRegister& vn, double value); Fcmpe(const VRegister & vn,const VRegister & vm)732 void Fcmpe(const VRegister& vn, const VRegister& vm) { 733 Fcmp(vn, vm, EnableTrap); 734 } Fcsel(const VRegister & vd,const VRegister & vn,const VRegister & vm,Condition cond)735 void Fcsel(const VRegister& vd, 736 const VRegister& vn, 737 const VRegister& vm, 738 Condition cond) { 739 VIXL_ASSERT((cond != al) && (cond != nv)); 740 SingleEmissionCheckScope guard(this); 741 fcsel(vd, vn, vm, cond); 742 } Fcvt(const VRegister & vd,const VRegister & vn)743 void Fcvt(const VRegister& vd, const VRegister& vn) { 744 SingleEmissionCheckScope guard(this); 745 fcvt(vd, vn); 746 } Fcvtl(const VRegister & vd,const VRegister & vn)747 void Fcvtl(const VRegister& vd, const VRegister& vn) { 748 SingleEmissionCheckScope guard(this); 749 fcvtl(vd, vn); 750 } Fcvtl2(const VRegister & vd,const VRegister & vn)751 void Fcvtl2(const VRegister& vd, const VRegister& vn) { 752 SingleEmissionCheckScope guard(this); 753 fcvtl2(vd, vn); 754 } Fcvtn(const VRegister & vd,const VRegister & vn)755 void Fcvtn(const VRegister& vd, const VRegister& vn) { 756 SingleEmissionCheckScope guard(this); 757 fcvtn(vd, vn); 758 } Fcvtn2(const VRegister & vd,const VRegister & vn)759 void Fcvtn2(const VRegister& vd, const VRegister& vn) { 760 SingleEmissionCheckScope guard(this); 761 fcvtn2(vd, vn); 762 } Fcvtxn(const VRegister & vd,const VRegister & vn)763 void Fcvtxn(const VRegister& vd, const VRegister& vn) { 764 SingleEmissionCheckScope guard(this); 765 fcvtxn(vd, vn); 766 } Fcvtxn2(const VRegister & vd,const VRegister & vn)767 void Fcvtxn2(const VRegister& vd, const VRegister& vn) { 768 SingleEmissionCheckScope guard(this); 769 fcvtxn2(vd, vn); 770 } Fcvtas(const Register & rd,const VRegister & vn)771 void Fcvtas(const Register& rd, const VRegister& vn) { 772 VIXL_ASSERT(!rd.IsZero()); 773 SingleEmissionCheckScope guard(this); 774 fcvtas(rd, vn); 775 } Fcvtau(const Register & rd,const VRegister & vn)776 void Fcvtau(const Register& rd, const VRegister& vn) { 777 VIXL_ASSERT(!rd.IsZero()); 778 SingleEmissionCheckScope guard(this); 779 fcvtau(rd, vn); 780 } Fcvtms(const Register & rd,const VRegister & vn)781 void Fcvtms(const Register& rd, const VRegister& vn) { 782 VIXL_ASSERT(!rd.IsZero()); 783 SingleEmissionCheckScope guard(this); 784 fcvtms(rd, vn); 785 } Fcvtmu(const Register & rd,const VRegister & vn)786 void Fcvtmu(const Register& rd, const VRegister& vn) { 787 VIXL_ASSERT(!rd.IsZero()); 788 SingleEmissionCheckScope guard(this); 789 fcvtmu(rd, vn); 790 } Fcvtns(const Register & rd,const VRegister & vn)791 void Fcvtns(const Register& rd, const VRegister& vn) { 792 VIXL_ASSERT(!rd.IsZero()); 793 SingleEmissionCheckScope guard(this); 794 fcvtns(rd, vn); 795 } Fcvtnu(const Register & rd,const VRegister & vn)796 void Fcvtnu(const Register& rd, const VRegister& vn) { 797 VIXL_ASSERT(!rd.IsZero()); 798 SingleEmissionCheckScope guard(this); 799 fcvtnu(rd, vn); 800 } Fcvtps(const Register & rd,const VRegister & vn)801 void Fcvtps(const Register& rd, const VRegister& vn) { 802 VIXL_ASSERT(!rd.IsZero()); 803 SingleEmissionCheckScope guard(this); 804 fcvtps(rd, vn); 805 } Fcvtpu(const Register & rd,const VRegister & vn)806 void Fcvtpu(const Register& rd, const VRegister& vn) { 807 VIXL_ASSERT(!rd.IsZero()); 808 SingleEmissionCheckScope guard(this); 809 fcvtpu(rd, vn); 810 } 811 void Fcvtzs(const Register& rd, const VRegister& vn, int fbits = 0) { 812 VIXL_ASSERT(!rd.IsZero()); 813 SingleEmissionCheckScope guard(this); 814 fcvtzs(rd, vn, fbits); 815 } 816 void Fcvtzu(const Register& rd, const VRegister& vn, int fbits = 0) { 817 VIXL_ASSERT(!rd.IsZero()); 818 SingleEmissionCheckScope guard(this); 819 fcvtzu(rd, vn, fbits); 820 } Fdiv(const VRegister & vd,const VRegister & vn,const VRegister & vm)821 void Fdiv(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 822 SingleEmissionCheckScope guard(this); 823 fdiv(vd, vn, vm); 824 } Fmax(const VRegister & vd,const VRegister & vn,const VRegister & vm)825 void Fmax(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 826 SingleEmissionCheckScope guard(this); 827 fmax(vd, vn, vm); 828 } Fmaxnm(const VRegister & vd,const VRegister & vn,const VRegister & vm)829 void Fmaxnm(const VRegister& vd, 830 const VRegister& vn, 831 const VRegister& vm) { 832 SingleEmissionCheckScope guard(this); 833 fmaxnm(vd, vn, vm); 834 } Fmin(const VRegister & vd,const VRegister & vn,const VRegister & vm)835 void Fmin(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 836 SingleEmissionCheckScope guard(this); 837 fmin(vd, vn, vm); 838 } Fminnm(const VRegister & vd,const VRegister & vn,const VRegister & vm)839 void Fminnm(const VRegister& vd, 840 const VRegister& vn, 841 const VRegister& vm) { 842 SingleEmissionCheckScope guard(this); 843 fminnm(vd, vn, vm); 844 } Fmov(VRegister vd,VRegister vn)845 void Fmov(VRegister vd, VRegister vn) { 846 SingleEmissionCheckScope guard(this); 847 // Only emit an instruction if vd and vn are different, and they are both D 848 // registers. fmov(s0, s0) is not a no-op because it clears the top word of 849 // d0. Technically, fmov(d0, d0) is not a no-op either because it clears 850 // the top of q0, but VRegister does not currently support Q registers. 851 if (!vd.Is(vn) || !vd.Is64Bits()) { 852 fmov(vd, vn); 853 } 854 } Fmov(VRegister vd,Register rn)855 void Fmov(VRegister vd, Register rn) { 856 VIXL_ASSERT(!rn.IsZero()); 857 SingleEmissionCheckScope guard(this); 858 fmov(vd, rn); 859 } Fmov(const VRegister & vd,int index,const Register & rn)860 void Fmov(const VRegister& vd, int index, const Register& rn) { 861 SingleEmissionCheckScope guard(this); 862 fmov(vd, index, rn); 863 } Fmov(const Register & rd,const VRegister & vn,int index)864 void Fmov(const Register& rd, const VRegister& vn, int index) { 865 SingleEmissionCheckScope guard(this); 866 fmov(rd, vn, index); 867 } 868 869 // Provide explicit double and float interfaces for FP immediate moves, rather 870 // than relying on implicit C++ casts. This allows signalling NaNs to be 871 // preserved when the immediate matches the format of vd. Most systems convert 872 // signalling NaNs to quiet NaNs when converting between float and double. 873 void Fmov(VRegister vd, double imm); 874 void Fmov(VRegister vd, float imm); 875 // Provide a template to allow other types to be converted automatically. 876 template<typename T> Fmov(VRegister vd,T imm)877 void Fmov(VRegister vd, T imm) { 878 Fmov(vd, static_cast<double>(imm)); 879 } Fmov(Register rd,VRegister vn)880 void Fmov(Register rd, VRegister vn) { 881 VIXL_ASSERT(!rd.IsZero()); 882 SingleEmissionCheckScope guard(this); 883 fmov(rd, vn); 884 } Fmul(const VRegister & vd,const VRegister & vn,const VRegister & vm)885 void Fmul(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 886 SingleEmissionCheckScope guard(this); 887 fmul(vd, vn, vm); 888 } Fnmul(const VRegister & vd,const VRegister & vn,const VRegister & vm)889 void Fnmul(const VRegister& vd, const VRegister& vn, 890 const VRegister& vm) { 891 SingleEmissionCheckScope guard(this); 892 fnmul(vd, vn, vm); 893 } Fmadd(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)894 void Fmadd(const VRegister& vd, 895 const VRegister& vn, 896 const VRegister& vm, 897 const VRegister& va) { 898 SingleEmissionCheckScope guard(this); 899 fmadd(vd, vn, vm, va); 900 } Fmsub(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)901 void Fmsub(const VRegister& vd, 902 const VRegister& vn, 903 const VRegister& vm, 904 const VRegister& va) { 905 SingleEmissionCheckScope guard(this); 906 fmsub(vd, vn, vm, va); 907 } Fnmadd(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)908 void Fnmadd(const VRegister& vd, 909 const VRegister& vn, 910 const VRegister& vm, 911 const VRegister& va) { 912 SingleEmissionCheckScope guard(this); 913 fnmadd(vd, vn, vm, va); 914 } Fnmsub(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)915 void Fnmsub(const VRegister& vd, 916 const VRegister& vn, 917 const VRegister& vm, 918 const VRegister& va) { 919 SingleEmissionCheckScope guard(this); 920 fnmsub(vd, vn, vm, va); 921 } Fsub(const VRegister & vd,const VRegister & vn,const VRegister & vm)922 void Fsub(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 923 SingleEmissionCheckScope guard(this); 924 fsub(vd, vn, vm); 925 } Hint(SystemHint code)926 void Hint(SystemHint code) { 927 SingleEmissionCheckScope guard(this); 928 hint(code); 929 } Hlt(int code)930 void Hlt(int code) { 931 SingleEmissionCheckScope guard(this); 932 hlt(code); 933 } Isb()934 void Isb() { 935 SingleEmissionCheckScope guard(this); 936 isb(); 937 } Ldar(const Register & rt,const MemOperand & src)938 void Ldar(const Register& rt, const MemOperand& src) { 939 SingleEmissionCheckScope guard(this); 940 ldar(rt, src); 941 } Ldarb(const Register & rt,const MemOperand & src)942 void Ldarb(const Register& rt, const MemOperand& src) { 943 SingleEmissionCheckScope guard(this); 944 ldarb(rt, src); 945 } Ldarh(const Register & rt,const MemOperand & src)946 void Ldarh(const Register& rt, const MemOperand& src) { 947 SingleEmissionCheckScope guard(this); 948 ldarh(rt, src); 949 } Ldaxp(const Register & rt,const Register & rt2,const MemOperand & src)950 void Ldaxp(const Register& rt, const Register& rt2, const MemOperand& src) { 951 VIXL_ASSERT(!rt.Aliases(rt2)); 952 SingleEmissionCheckScope guard(this); 953 ldaxp(rt, rt2, src); 954 } Ldaxr(const Register & rt,const MemOperand & src)955 void Ldaxr(const Register& rt, const MemOperand& src) { 956 SingleEmissionCheckScope guard(this); 957 ldaxr(rt, src); 958 } Ldaxrb(const Register & rt,const MemOperand & src)959 void Ldaxrb(const Register& rt, const MemOperand& src) { 960 SingleEmissionCheckScope guard(this); 961 ldaxrb(rt, src); 962 } Ldaxrh(const Register & rt,const MemOperand & src)963 void Ldaxrh(const Register& rt, const MemOperand& src) { 964 SingleEmissionCheckScope guard(this); 965 ldaxrh(rt, src); 966 } Ldnp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & src)967 void Ldnp(const CPURegister& rt, 968 const CPURegister& rt2, 969 const MemOperand& src) { 970 SingleEmissionCheckScope guard(this); 971 ldnp(rt, rt2, src); 972 } 973 // Provide both double and float interfaces for FP immediate loads, rather 974 // than relying on implicit C++ casts. This allows signalling NaNs to be 975 // preserved when the immediate matches the format of fd. Most systems convert 976 // signalling NaNs to quiet NaNs when converting between float and double. Ldr(const VRegister & vt,double imm)977 void Ldr(const VRegister& vt, double imm) { 978 SingleEmissionCheckScope guard(this); 979 if (vt.Is64Bits()) { 980 ldr(vt, imm); 981 } else { 982 ldr(vt, static_cast<float>(imm)); 983 } 984 } Ldr(const VRegister & vt,float imm)985 void Ldr(const VRegister& vt, float imm) { 986 SingleEmissionCheckScope guard(this); 987 if (vt.Is32Bits()) { 988 ldr(vt, imm); 989 } else { 990 ldr(vt, static_cast<double>(imm)); 991 } 992 } 993 /* 994 void Ldr(const VRegister& vt, uint64_t high64, uint64_t low64) { 995 VIXL_ASSERT(vt.IsQ()); 996 SingleEmissionCheckScope guard(this); 997 ldr(vt, new Literal<uint64_t>(high64, low64, 998 &literal_pool_, 999 RawLiteral::kDeletedOnPlacementByPool)); 1000 } 1001 */ Ldr(const Register & rt,uint64_t imm)1002 void Ldr(const Register& rt, uint64_t imm) { 1003 VIXL_ASSERT(!rt.IsZero()); 1004 SingleEmissionCheckScope guard(this); 1005 ldr(rt, imm); 1006 } Ldrsw(const Register & rt,uint32_t imm)1007 void Ldrsw(const Register& rt, uint32_t imm) { 1008 VIXL_ASSERT(!rt.IsZero()); 1009 SingleEmissionCheckScope guard(this); 1010 ldrsw(rt, imm); 1011 } Ldxp(const Register & rt,const Register & rt2,const MemOperand & src)1012 void Ldxp(const Register& rt, const Register& rt2, const MemOperand& src) { 1013 VIXL_ASSERT(!rt.Aliases(rt2)); 1014 SingleEmissionCheckScope guard(this); 1015 ldxp(rt, rt2, src); 1016 } Ldxr(const Register & rt,const MemOperand & src)1017 void Ldxr(const Register& rt, const MemOperand& src) { 1018 SingleEmissionCheckScope guard(this); 1019 ldxr(rt, src); 1020 } Ldxrb(const Register & rt,const MemOperand & src)1021 void Ldxrb(const Register& rt, const MemOperand& src) { 1022 SingleEmissionCheckScope guard(this); 1023 ldxrb(rt, src); 1024 } Ldxrh(const Register & rt,const MemOperand & src)1025 void Ldxrh(const Register& rt, const MemOperand& src) { 1026 SingleEmissionCheckScope guard(this); 1027 ldxrh(rt, src); 1028 } Lsl(const Register & rd,const Register & rn,unsigned shift)1029 void Lsl(const Register& rd, const Register& rn, unsigned shift) { 1030 VIXL_ASSERT(!rd.IsZero()); 1031 VIXL_ASSERT(!rn.IsZero()); 1032 SingleEmissionCheckScope guard(this); 1033 lsl(rd, rn, shift); 1034 } Lsl(const Register & rd,const Register & rn,const Register & rm)1035 void Lsl(const Register& rd, const Register& rn, const Register& rm) { 1036 VIXL_ASSERT(!rd.IsZero()); 1037 VIXL_ASSERT(!rn.IsZero()); 1038 VIXL_ASSERT(!rm.IsZero()); 1039 SingleEmissionCheckScope guard(this); 1040 lslv(rd, rn, rm); 1041 } Lsr(const Register & rd,const Register & rn,unsigned shift)1042 void Lsr(const Register& rd, const Register& rn, unsigned shift) { 1043 VIXL_ASSERT(!rd.IsZero()); 1044 VIXL_ASSERT(!rn.IsZero()); 1045 SingleEmissionCheckScope guard(this); 1046 lsr(rd, rn, shift); 1047 } Lsr(const Register & rd,const Register & rn,const Register & rm)1048 void Lsr(const Register& rd, const Register& rn, const Register& rm) { 1049 VIXL_ASSERT(!rd.IsZero()); 1050 VIXL_ASSERT(!rn.IsZero()); 1051 VIXL_ASSERT(!rm.IsZero()); 1052 SingleEmissionCheckScope guard(this); 1053 lsrv(rd, rn, rm); 1054 } Madd(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1055 void Madd(const Register& rd, 1056 const Register& rn, 1057 const Register& rm, 1058 const Register& ra) { 1059 VIXL_ASSERT(!rd.IsZero()); 1060 VIXL_ASSERT(!rn.IsZero()); 1061 VIXL_ASSERT(!rm.IsZero()); 1062 VIXL_ASSERT(!ra.IsZero()); 1063 SingleEmissionCheckScope guard(this); 1064 madd(rd, rn, rm, ra); 1065 } Mneg(const Register & rd,const Register & rn,const Register & rm)1066 void Mneg(const Register& rd, const Register& rn, const Register& rm) { 1067 VIXL_ASSERT(!rd.IsZero()); 1068 VIXL_ASSERT(!rn.IsZero()); 1069 VIXL_ASSERT(!rm.IsZero()); 1070 SingleEmissionCheckScope guard(this); 1071 mneg(rd, rn, rm); 1072 } Mov(const Register & rd,const Register & rn)1073 void Mov(const Register& rd, const Register& rn) { 1074 SingleEmissionCheckScope guard(this); 1075 mov(rd, rn); 1076 } 1077 void Movk(const Register& rd, uint64_t imm, int shift = -1) { 1078 VIXL_ASSERT(!rd.IsZero()); 1079 SingleEmissionCheckScope guard(this); 1080 movk(rd, imm, shift); 1081 } Mrs(const Register & rt,SystemRegister sysreg)1082 void Mrs(const Register& rt, SystemRegister sysreg) { 1083 VIXL_ASSERT(!rt.IsZero()); 1084 SingleEmissionCheckScope guard(this); 1085 mrs(rt, sysreg); 1086 } Msr(SystemRegister sysreg,const Register & rt)1087 void Msr(SystemRegister sysreg, const Register& rt) { 1088 VIXL_ASSERT(!rt.IsZero()); 1089 SingleEmissionCheckScope guard(this); 1090 msr(sysreg, rt); 1091 } 1092 void Sys(int op1, int crn, int crm, int op2, const Register& rt = xzr) { 1093 SingleEmissionCheckScope guard(this); 1094 sys(op1, crn, crm, op2, rt); 1095 } Dc(DataCacheOp op,const Register & rt)1096 void Dc(DataCacheOp op, const Register& rt) { 1097 SingleEmissionCheckScope guard(this); 1098 dc(op, rt); 1099 } Ic(InstructionCacheOp op,const Register & rt)1100 void Ic(InstructionCacheOp op, const Register& rt) { 1101 SingleEmissionCheckScope guard(this); 1102 ic(op, rt); 1103 } Msub(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1104 void Msub(const Register& rd, 1105 const Register& rn, 1106 const Register& rm, 1107 const Register& ra) { 1108 VIXL_ASSERT(!rd.IsZero()); 1109 VIXL_ASSERT(!rn.IsZero()); 1110 VIXL_ASSERT(!rm.IsZero()); 1111 VIXL_ASSERT(!ra.IsZero()); 1112 SingleEmissionCheckScope guard(this); 1113 msub(rd, rn, rm, ra); 1114 } Mul(const Register & rd,const Register & rn,const Register & rm)1115 void Mul(const Register& rd, const Register& rn, const Register& rm) { 1116 VIXL_ASSERT(!rd.IsZero()); 1117 VIXL_ASSERT(!rn.IsZero()); 1118 VIXL_ASSERT(!rm.IsZero()); 1119 SingleEmissionCheckScope guard(this); 1120 mul(rd, rn, rm); 1121 } Nop()1122 void Nop() { 1123 SingleEmissionCheckScope guard(this); 1124 nop(); 1125 } Csdb()1126 void Csdb() { 1127 SingleEmissionCheckScope guard(this); 1128 csdb(); 1129 } Rbit(const Register & rd,const Register & rn)1130 void Rbit(const Register& rd, const Register& rn) { 1131 VIXL_ASSERT(!rd.IsZero()); 1132 VIXL_ASSERT(!rn.IsZero()); 1133 SingleEmissionCheckScope guard(this); 1134 rbit(rd, rn); 1135 } 1136 void Ret(const Register& xn = lr) { 1137 VIXL_ASSERT(!xn.IsZero()); 1138 SingleEmissionCheckScope guard(this); 1139 ret(xn); 1140 } Rev(const Register & rd,const Register & rn)1141 void Rev(const Register& rd, const Register& rn) { 1142 VIXL_ASSERT(!rd.IsZero()); 1143 VIXL_ASSERT(!rn.IsZero()); 1144 SingleEmissionCheckScope guard(this); 1145 rev(rd, rn); 1146 } Rev16(const Register & rd,const Register & rn)1147 void Rev16(const Register& rd, const Register& rn) { 1148 VIXL_ASSERT(!rd.IsZero()); 1149 VIXL_ASSERT(!rn.IsZero()); 1150 SingleEmissionCheckScope guard(this); 1151 rev16(rd, rn); 1152 } Rev32(const Register & rd,const Register & rn)1153 void Rev32(const Register& rd, const Register& rn) { 1154 VIXL_ASSERT(!rd.IsZero()); 1155 VIXL_ASSERT(!rn.IsZero()); 1156 SingleEmissionCheckScope guard(this); 1157 rev32(rd, rn); 1158 } Ror(const Register & rd,const Register & rs,unsigned shift)1159 void Ror(const Register& rd, const Register& rs, unsigned shift) { 1160 VIXL_ASSERT(!rd.IsZero()); 1161 VIXL_ASSERT(!rs.IsZero()); 1162 SingleEmissionCheckScope guard(this); 1163 ror(rd, rs, shift); 1164 } Ror(const Register & rd,const Register & rn,const Register & rm)1165 void Ror(const Register& rd, const Register& rn, const Register& rm) { 1166 VIXL_ASSERT(!rd.IsZero()); 1167 VIXL_ASSERT(!rn.IsZero()); 1168 VIXL_ASSERT(!rm.IsZero()); 1169 SingleEmissionCheckScope guard(this); 1170 rorv(rd, rn, rm); 1171 } Sbfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1172 void Sbfiz(const Register& rd, 1173 const Register& rn, 1174 unsigned lsb, 1175 unsigned width) { 1176 VIXL_ASSERT(!rd.IsZero()); 1177 VIXL_ASSERT(!rn.IsZero()); 1178 SingleEmissionCheckScope guard(this); 1179 sbfiz(rd, rn, lsb, width); 1180 } Sbfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)1181 void Sbfm(const Register& rd, 1182 const Register& rn, 1183 unsigned immr, 1184 unsigned imms) { 1185 VIXL_ASSERT(!rd.IsZero()); 1186 VIXL_ASSERT(!rn.IsZero()); 1187 SingleEmissionCheckScope guard(this); 1188 sbfm(rd, rn, immr, imms); 1189 } Sbfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1190 void Sbfx(const Register& rd, 1191 const Register& rn, 1192 unsigned lsb, 1193 unsigned width) { 1194 VIXL_ASSERT(!rd.IsZero()); 1195 VIXL_ASSERT(!rn.IsZero()); 1196 SingleEmissionCheckScope guard(this); 1197 sbfx(rd, rn, lsb, width); 1198 } 1199 void Scvtf(const VRegister& vd, const Register& rn, int fbits = 0) { 1200 VIXL_ASSERT(!rn.IsZero()); 1201 SingleEmissionCheckScope guard(this); 1202 scvtf(vd, rn, fbits); 1203 } Sdiv(const Register & rd,const Register & rn,const Register & rm)1204 void Sdiv(const Register& rd, const Register& rn, const Register& rm) { 1205 VIXL_ASSERT(!rd.IsZero()); 1206 VIXL_ASSERT(!rn.IsZero()); 1207 VIXL_ASSERT(!rm.IsZero()); 1208 SingleEmissionCheckScope guard(this); 1209 sdiv(rd, rn, rm); 1210 } Smaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1211 void Smaddl(const Register& rd, 1212 const Register& rn, 1213 const Register& rm, 1214 const Register& ra) { 1215 VIXL_ASSERT(!rd.IsZero()); 1216 VIXL_ASSERT(!rn.IsZero()); 1217 VIXL_ASSERT(!rm.IsZero()); 1218 VIXL_ASSERT(!ra.IsZero()); 1219 SingleEmissionCheckScope guard(this); 1220 smaddl(rd, rn, rm, ra); 1221 } Smsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1222 void Smsubl(const Register& rd, 1223 const Register& rn, 1224 const Register& rm, 1225 const Register& ra) { 1226 VIXL_ASSERT(!rd.IsZero()); 1227 VIXL_ASSERT(!rn.IsZero()); 1228 VIXL_ASSERT(!rm.IsZero()); 1229 VIXL_ASSERT(!ra.IsZero()); 1230 SingleEmissionCheckScope guard(this); 1231 smsubl(rd, rn, rm, ra); 1232 } Smull(const Register & rd,const Register & rn,const Register & rm)1233 void Smull(const Register& rd, const Register& rn, const Register& rm) { 1234 VIXL_ASSERT(!rd.IsZero()); 1235 VIXL_ASSERT(!rn.IsZero()); 1236 VIXL_ASSERT(!rm.IsZero()); 1237 SingleEmissionCheckScope guard(this); 1238 smull(rd, rn, rm); 1239 } Smulh(const Register & xd,const Register & xn,const Register & xm)1240 void Smulh(const Register& xd, const Register& xn, const Register& xm) { 1241 VIXL_ASSERT(!xd.IsZero()); 1242 VIXL_ASSERT(!xn.IsZero()); 1243 VIXL_ASSERT(!xm.IsZero()); 1244 SingleEmissionCheckScope guard(this); 1245 smulh(xd, xn, xm); 1246 } Stlr(const Register & rt,const MemOperand & dst)1247 void Stlr(const Register& rt, const MemOperand& dst) { 1248 SingleEmissionCheckScope guard(this); 1249 stlr(rt, dst); 1250 } Stlrb(const Register & rt,const MemOperand & dst)1251 void Stlrb(const Register& rt, const MemOperand& dst) { 1252 SingleEmissionCheckScope guard(this); 1253 stlrb(rt, dst); 1254 } Stlrh(const Register & rt,const MemOperand & dst)1255 void Stlrh(const Register& rt, const MemOperand& dst) { 1256 SingleEmissionCheckScope guard(this); 1257 stlrh(rt, dst); 1258 } Stlxp(const Register & rs,const Register & rt,const Register & rt2,const MemOperand & dst)1259 void Stlxp(const Register& rs, 1260 const Register& rt, 1261 const Register& rt2, 1262 const MemOperand& dst) { 1263 VIXL_ASSERT(!rs.Aliases(dst.base())); 1264 VIXL_ASSERT(!rs.Aliases(rt)); 1265 VIXL_ASSERT(!rs.Aliases(rt2)); 1266 SingleEmissionCheckScope guard(this); 1267 stlxp(rs, rt, rt2, dst); 1268 } Stlxr(const Register & rs,const Register & rt,const MemOperand & dst)1269 void Stlxr(const Register& rs, const Register& rt, const MemOperand& dst) { 1270 VIXL_ASSERT(!rs.Aliases(dst.base())); 1271 VIXL_ASSERT(!rs.Aliases(rt)); 1272 SingleEmissionCheckScope guard(this); 1273 stlxr(rs, rt, dst); 1274 } Stlxrb(const Register & rs,const Register & rt,const MemOperand & dst)1275 void Stlxrb(const Register& rs, const Register& rt, const MemOperand& dst) { 1276 VIXL_ASSERT(!rs.Aliases(dst.base())); 1277 VIXL_ASSERT(!rs.Aliases(rt)); 1278 SingleEmissionCheckScope guard(this); 1279 stlxrb(rs, rt, dst); 1280 } Stlxrh(const Register & rs,const Register & rt,const MemOperand & dst)1281 void Stlxrh(const Register& rs, const Register& rt, const MemOperand& dst) { 1282 VIXL_ASSERT(!rs.Aliases(dst.base())); 1283 VIXL_ASSERT(!rs.Aliases(rt)); 1284 SingleEmissionCheckScope guard(this); 1285 stlxrh(rs, rt, dst); 1286 } Stnp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & dst)1287 void Stnp(const CPURegister& rt, 1288 const CPURegister& rt2, 1289 const MemOperand& dst) { 1290 SingleEmissionCheckScope guard(this); 1291 stnp(rt, rt2, dst); 1292 } Stxp(const Register & rs,const Register & rt,const Register & rt2,const MemOperand & dst)1293 void Stxp(const Register& rs, 1294 const Register& rt, 1295 const Register& rt2, 1296 const MemOperand& dst) { 1297 VIXL_ASSERT(!rs.Aliases(dst.base())); 1298 VIXL_ASSERT(!rs.Aliases(rt)); 1299 VIXL_ASSERT(!rs.Aliases(rt2)); 1300 SingleEmissionCheckScope guard(this); 1301 stxp(rs, rt, rt2, dst); 1302 } Stxr(const Register & rs,const Register & rt,const MemOperand & dst)1303 void Stxr(const Register& rs, const Register& rt, const MemOperand& dst) { 1304 VIXL_ASSERT(!rs.Aliases(dst.base())); 1305 VIXL_ASSERT(!rs.Aliases(rt)); 1306 SingleEmissionCheckScope guard(this); 1307 stxr(rs, rt, dst); 1308 } Stxrb(const Register & rs,const Register & rt,const MemOperand & dst)1309 void Stxrb(const Register& rs, const Register& rt, const MemOperand& dst) { 1310 VIXL_ASSERT(!rs.Aliases(dst.base())); 1311 VIXL_ASSERT(!rs.Aliases(rt)); 1312 SingleEmissionCheckScope guard(this); 1313 stxrb(rs, rt, dst); 1314 } Stxrh(const Register & rs,const Register & rt,const MemOperand & dst)1315 void Stxrh(const Register& rs, const Register& rt, const MemOperand& dst) { 1316 VIXL_ASSERT(!rs.Aliases(dst.base())); 1317 VIXL_ASSERT(!rs.Aliases(rt)); 1318 SingleEmissionCheckScope guard(this); 1319 stxrh(rs, rt, dst); 1320 } Svc(int code)1321 void Svc(int code) { 1322 SingleEmissionCheckScope guard(this); 1323 svc(code); 1324 } Sxtb(const Register & rd,const Register & rn)1325 void Sxtb(const Register& rd, const Register& rn) { 1326 VIXL_ASSERT(!rd.IsZero()); 1327 VIXL_ASSERT(!rn.IsZero()); 1328 SingleEmissionCheckScope guard(this); 1329 sxtb(rd, rn); 1330 } Sxth(const Register & rd,const Register & rn)1331 void Sxth(const Register& rd, const Register& rn) { 1332 VIXL_ASSERT(!rd.IsZero()); 1333 VIXL_ASSERT(!rn.IsZero()); 1334 SingleEmissionCheckScope guard(this); 1335 sxth(rd, rn); 1336 } Sxtw(const Register & rd,const Register & rn)1337 void Sxtw(const Register& rd, const Register& rn) { 1338 VIXL_ASSERT(!rd.IsZero()); 1339 VIXL_ASSERT(!rn.IsZero()); 1340 SingleEmissionCheckScope guard(this); 1341 sxtw(rd, rn); 1342 } Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vm)1343 void Tbl(const VRegister& vd, 1344 const VRegister& vn, 1345 const VRegister& vm) { 1346 SingleEmissionCheckScope guard(this); 1347 tbl(vd, vn, vm); 1348 } Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vm)1349 void Tbl(const VRegister& vd, 1350 const VRegister& vn, 1351 const VRegister& vn2, 1352 const VRegister& vm) { 1353 SingleEmissionCheckScope guard(this); 1354 tbl(vd, vn, vn2, vm); 1355 } Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vm)1356 void Tbl(const VRegister& vd, 1357 const VRegister& vn, 1358 const VRegister& vn2, 1359 const VRegister& vn3, 1360 const VRegister& vm) { 1361 SingleEmissionCheckScope guard(this); 1362 tbl(vd, vn, vn2, vn3, vm); 1363 } Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vn4,const VRegister & vm)1364 void Tbl(const VRegister& vd, 1365 const VRegister& vn, 1366 const VRegister& vn2, 1367 const VRegister& vn3, 1368 const VRegister& vn4, 1369 const VRegister& vm) { 1370 SingleEmissionCheckScope guard(this); 1371 tbl(vd, vn, vn2, vn3, vn4, vm); 1372 } Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vm)1373 void Tbx(const VRegister& vd, 1374 const VRegister& vn, 1375 const VRegister& vm) { 1376 SingleEmissionCheckScope guard(this); 1377 tbx(vd, vn, vm); 1378 } Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vm)1379 void Tbx(const VRegister& vd, 1380 const VRegister& vn, 1381 const VRegister& vn2, 1382 const VRegister& vm) { 1383 SingleEmissionCheckScope guard(this); 1384 tbx(vd, vn, vn2, vm); 1385 } Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vm)1386 void Tbx(const VRegister& vd, 1387 const VRegister& vn, 1388 const VRegister& vn2, 1389 const VRegister& vn3, 1390 const VRegister& vm) { 1391 SingleEmissionCheckScope guard(this); 1392 tbx(vd, vn, vn2, vn3, vm); 1393 } Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vn4,const VRegister & vm)1394 void Tbx(const VRegister& vd, 1395 const VRegister& vn, 1396 const VRegister& vn2, 1397 const VRegister& vn3, 1398 const VRegister& vn4, 1399 const VRegister& vm) { 1400 SingleEmissionCheckScope guard(this); 1401 tbx(vd, vn, vn2, vn3, vn4, vm); 1402 } 1403 void Tbnz(const Register& rt, unsigned bit_pos, Label* label); 1404 void Tbz(const Register& rt, unsigned bit_pos, Label* label); Ubfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1405 void Ubfiz(const Register& rd, 1406 const Register& rn, 1407 unsigned lsb, 1408 unsigned width) { 1409 VIXL_ASSERT(!rd.IsZero()); 1410 VIXL_ASSERT(!rn.IsZero()); 1411 SingleEmissionCheckScope guard(this); 1412 ubfiz(rd, rn, lsb, width); 1413 } Ubfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)1414 void Ubfm(const Register& rd, 1415 const Register& rn, 1416 unsigned immr, 1417 unsigned imms) { 1418 VIXL_ASSERT(!rd.IsZero()); 1419 VIXL_ASSERT(!rn.IsZero()); 1420 SingleEmissionCheckScope guard(this); 1421 ubfm(rd, rn, immr, imms); 1422 } Ubfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1423 void Ubfx(const Register& rd, 1424 const Register& rn, 1425 unsigned lsb, 1426 unsigned width) { 1427 VIXL_ASSERT(!rd.IsZero()); 1428 VIXL_ASSERT(!rn.IsZero()); 1429 SingleEmissionCheckScope guard(this); 1430 ubfx(rd, rn, lsb, width); 1431 } 1432 void Ucvtf(const VRegister& vd, const Register& rn, int fbits = 0) { 1433 VIXL_ASSERT(!rn.IsZero()); 1434 SingleEmissionCheckScope guard(this); 1435 ucvtf(vd, rn, fbits); 1436 } Udiv(const Register & rd,const Register & rn,const Register & rm)1437 void Udiv(const Register& rd, const Register& rn, const Register& rm) { 1438 VIXL_ASSERT(!rd.IsZero()); 1439 VIXL_ASSERT(!rn.IsZero()); 1440 VIXL_ASSERT(!rm.IsZero()); 1441 SingleEmissionCheckScope guard(this); 1442 udiv(rd, rn, rm); 1443 } Umaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1444 void Umaddl(const Register& rd, 1445 const Register& rn, 1446 const Register& rm, 1447 const Register& ra) { 1448 VIXL_ASSERT(!rd.IsZero()); 1449 VIXL_ASSERT(!rn.IsZero()); 1450 VIXL_ASSERT(!rm.IsZero()); 1451 VIXL_ASSERT(!ra.IsZero()); 1452 SingleEmissionCheckScope guard(this); 1453 umaddl(rd, rn, rm, ra); 1454 } Umull(const Register & rd,const Register & rn,const Register & rm)1455 void Umull(const Register& rd, 1456 const Register& rn, 1457 const Register& rm) { 1458 VIXL_ASSERT(!rd.IsZero()); 1459 VIXL_ASSERT(!rn.IsZero()); 1460 VIXL_ASSERT(!rm.IsZero()); 1461 SingleEmissionCheckScope guard(this); 1462 umull(rd, rn, rm); 1463 } Umulh(const Register & xd,const Register & xn,const Register & xm)1464 void Umulh(const Register& xd, const Register& xn, const Register& xm) { 1465 VIXL_ASSERT(!xd.IsZero()); 1466 VIXL_ASSERT(!xn.IsZero()); 1467 VIXL_ASSERT(!xm.IsZero()); 1468 SingleEmissionCheckScope guard(this); 1469 umulh(xd, xn, xm); 1470 } Umsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1471 void Umsubl(const Register& rd, 1472 const Register& rn, 1473 const Register& rm, 1474 const Register& ra) { 1475 VIXL_ASSERT(!rd.IsZero()); 1476 VIXL_ASSERT(!rn.IsZero()); 1477 VIXL_ASSERT(!rm.IsZero()); 1478 VIXL_ASSERT(!ra.IsZero()); 1479 SingleEmissionCheckScope guard(this); 1480 umsubl(rd, rn, rm, ra); 1481 } Unreachable()1482 void Unreachable() { 1483 SingleEmissionCheckScope guard(this); 1484 #ifdef JS_SIMULATOR_ARM64 1485 hlt(kUnreachableOpcode); 1486 #else 1487 // A couple of strategies we can use here. There are no unencoded 1488 // instructions in the instruction set that are guaranteed to remain that 1489 // way. However there are some currently (as of 2018) unencoded 1490 // instructions that are good candidates. 1491 // 1492 // Ideally, unencoded instructions should be non-destructive to the register 1493 // state, and should be unencoded at all exception levels. 1494 // 1495 // At the trap the pc will hold the address of the offending instruction. 1496 1497 // Some candidates for unencoded instructions: 1498 // 1499 // 0xd4a00000 (essentially dcps0, a good one since it is nonsensical and may 1500 // remain unencoded in the future for that reason) 1501 // 0x33000000 (bfm variant) 1502 // 0xd67f0000 (br variant) 1503 // 0x5ac00c00 (rbit variant) 1504 1505 Emit(0xd4a00000); // "dcps0", also has 16-bit payload if needed 1506 #endif 1507 } Uxtb(const Register & rd,const Register & rn)1508 void Uxtb(const Register& rd, const Register& rn) { 1509 VIXL_ASSERT(!rd.IsZero()); 1510 VIXL_ASSERT(!rn.IsZero()); 1511 SingleEmissionCheckScope guard(this); 1512 uxtb(rd, rn); 1513 } Uxth(const Register & rd,const Register & rn)1514 void Uxth(const Register& rd, const Register& rn) { 1515 VIXL_ASSERT(!rd.IsZero()); 1516 VIXL_ASSERT(!rn.IsZero()); 1517 SingleEmissionCheckScope guard(this); 1518 uxth(rd, rn); 1519 } Uxtw(const Register & rd,const Register & rn)1520 void Uxtw(const Register& rd, const Register& rn) { 1521 VIXL_ASSERT(!rd.IsZero()); 1522 VIXL_ASSERT(!rn.IsZero()); 1523 SingleEmissionCheckScope guard(this); 1524 uxtw(rd, rn); 1525 } 1526 1527 // NEON 3 vector register instructions. 1528 #define NEON_3VREG_MACRO_LIST(V) \ 1529 V(add, Add) \ 1530 V(addhn, Addhn) \ 1531 V(addhn2, Addhn2) \ 1532 V(addp, Addp) \ 1533 V(and_, And) \ 1534 V(bic, Bic) \ 1535 V(bif, Bif) \ 1536 V(bit, Bit) \ 1537 V(bsl, Bsl) \ 1538 V(cmeq, Cmeq) \ 1539 V(cmge, Cmge) \ 1540 V(cmgt, Cmgt) \ 1541 V(cmhi, Cmhi) \ 1542 V(cmhs, Cmhs) \ 1543 V(cmtst, Cmtst) \ 1544 V(eor, Eor) \ 1545 V(fabd, Fabd) \ 1546 V(facge, Facge) \ 1547 V(facgt, Facgt) \ 1548 V(faddp, Faddp) \ 1549 V(fcmeq, Fcmeq) \ 1550 V(fcmge, Fcmge) \ 1551 V(fcmgt, Fcmgt) \ 1552 V(fmaxnmp, Fmaxnmp) \ 1553 V(fmaxp, Fmaxp) \ 1554 V(fminnmp, Fminnmp) \ 1555 V(fminp, Fminp) \ 1556 V(fmla, Fmla) \ 1557 V(fmls, Fmls) \ 1558 V(fmulx, Fmulx) \ 1559 V(frecps, Frecps) \ 1560 V(frsqrts, Frsqrts) \ 1561 V(mla, Mla) \ 1562 V(mls, Mls) \ 1563 V(mul, Mul) \ 1564 V(orn, Orn) \ 1565 V(orr, Orr) \ 1566 V(pmul, Pmul) \ 1567 V(pmull, Pmull) \ 1568 V(pmull2, Pmull2) \ 1569 V(raddhn, Raddhn) \ 1570 V(raddhn2, Raddhn2) \ 1571 V(rsubhn, Rsubhn) \ 1572 V(rsubhn2, Rsubhn2) \ 1573 V(saba, Saba) \ 1574 V(sabal, Sabal) \ 1575 V(sabal2, Sabal2) \ 1576 V(sabd, Sabd) \ 1577 V(sabdl, Sabdl) \ 1578 V(sabdl2, Sabdl2) \ 1579 V(saddl, Saddl) \ 1580 V(saddl2, Saddl2) \ 1581 V(saddw, Saddw) \ 1582 V(saddw2, Saddw2) \ 1583 V(shadd, Shadd) \ 1584 V(shsub, Shsub) \ 1585 V(smax, Smax) \ 1586 V(smaxp, Smaxp) \ 1587 V(smin, Smin) \ 1588 V(sminp, Sminp) \ 1589 V(smlal, Smlal) \ 1590 V(smlal2, Smlal2) \ 1591 V(smlsl, Smlsl) \ 1592 V(smlsl2, Smlsl2) \ 1593 V(smull, Smull) \ 1594 V(smull2, Smull2) \ 1595 V(sqadd, Sqadd) \ 1596 V(sqdmlal, Sqdmlal) \ 1597 V(sqdmlal2, Sqdmlal2) \ 1598 V(sqdmlsl, Sqdmlsl) \ 1599 V(sqdmlsl2, Sqdmlsl2) \ 1600 V(sqdmulh, Sqdmulh) \ 1601 V(sqdmull, Sqdmull) \ 1602 V(sqdmull2, Sqdmull2) \ 1603 V(sqrdmulh, Sqrdmulh) \ 1604 V(sqrshl, Sqrshl) \ 1605 V(sqshl, Sqshl) \ 1606 V(sqsub, Sqsub) \ 1607 V(srhadd, Srhadd) \ 1608 V(srshl, Srshl) \ 1609 V(sshl, Sshl) \ 1610 V(ssubl, Ssubl) \ 1611 V(ssubl2, Ssubl2) \ 1612 V(ssubw, Ssubw) \ 1613 V(ssubw2, Ssubw2) \ 1614 V(sub, Sub) \ 1615 V(subhn, Subhn) \ 1616 V(subhn2, Subhn2) \ 1617 V(trn1, Trn1) \ 1618 V(trn2, Trn2) \ 1619 V(uaba, Uaba) \ 1620 V(uabal, Uabal) \ 1621 V(uabal2, Uabal2) \ 1622 V(uabd, Uabd) \ 1623 V(uabdl, Uabdl) \ 1624 V(uabdl2, Uabdl2) \ 1625 V(uaddl, Uaddl) \ 1626 V(uaddl2, Uaddl2) \ 1627 V(uaddw, Uaddw) \ 1628 V(uaddw2, Uaddw2) \ 1629 V(uhadd, Uhadd) \ 1630 V(uhsub, Uhsub) \ 1631 V(umax, Umax) \ 1632 V(umaxp, Umaxp) \ 1633 V(umin, Umin) \ 1634 V(uminp, Uminp) \ 1635 V(umlal, Umlal) \ 1636 V(umlal2, Umlal2) \ 1637 V(umlsl, Umlsl) \ 1638 V(umlsl2, Umlsl2) \ 1639 V(umull, Umull) \ 1640 V(umull2, Umull2) \ 1641 V(uqadd, Uqadd) \ 1642 V(uqrshl, Uqrshl) \ 1643 V(uqshl, Uqshl) \ 1644 V(uqsub, Uqsub) \ 1645 V(urhadd, Urhadd) \ 1646 V(urshl, Urshl) \ 1647 V(ushl, Ushl) \ 1648 V(usubl, Usubl) \ 1649 V(usubl2, Usubl2) \ 1650 V(usubw, Usubw) \ 1651 V(usubw2, Usubw2) \ 1652 V(uzp1, Uzp1) \ 1653 V(uzp2, Uzp2) \ 1654 V(zip1, Zip1) \ 1655 V(zip2, Zip2) 1656 1657 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 1658 void MASM(const VRegister& vd, \ 1659 const VRegister& vn, \ 1660 const VRegister& vm) { \ 1661 SingleEmissionCheckScope guard(this); \ 1662 ASM(vd, vn, vm); \ 1663 } 1664 NEON_3VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 1665 #undef DEFINE_MACRO_ASM_FUNC 1666 1667 // NEON 2 vector register instructions. 1668 #define NEON_2VREG_MACRO_LIST(V) \ 1669 V(abs, Abs) \ 1670 V(addp, Addp) \ 1671 V(addv, Addv) \ 1672 V(cls, Cls) \ 1673 V(clz, Clz) \ 1674 V(cnt, Cnt) \ 1675 V(fabs, Fabs) \ 1676 V(faddp, Faddp) \ 1677 V(fcvtas, Fcvtas) \ 1678 V(fcvtau, Fcvtau) \ 1679 V(fcvtms, Fcvtms) \ 1680 V(fcvtmu, Fcvtmu) \ 1681 V(fcvtns, Fcvtns) \ 1682 V(fcvtnu, Fcvtnu) \ 1683 V(fcvtps, Fcvtps) \ 1684 V(fcvtpu, Fcvtpu) \ 1685 V(fmaxnmp, Fmaxnmp) \ 1686 V(fmaxnmv, Fmaxnmv) \ 1687 V(fmaxp, Fmaxp) \ 1688 V(fmaxv, Fmaxv) \ 1689 V(fminnmp, Fminnmp) \ 1690 V(fminnmv, Fminnmv) \ 1691 V(fminp, Fminp) \ 1692 V(fminv, Fminv) \ 1693 V(fneg, Fneg) \ 1694 V(frecpe, Frecpe) \ 1695 V(frecpx, Frecpx) \ 1696 V(frinta, Frinta) \ 1697 V(frinti, Frinti) \ 1698 V(frintm, Frintm) \ 1699 V(frintn, Frintn) \ 1700 V(frintp, Frintp) \ 1701 V(frintx, Frintx) \ 1702 V(frintz, Frintz) \ 1703 V(frsqrte, Frsqrte) \ 1704 V(fsqrt, Fsqrt) \ 1705 V(mov, Mov) \ 1706 V(mvn, Mvn) \ 1707 V(neg, Neg) \ 1708 V(not_, Not) \ 1709 V(rbit, Rbit) \ 1710 V(rev16, Rev16) \ 1711 V(rev32, Rev32) \ 1712 V(rev64, Rev64) \ 1713 V(sadalp, Sadalp) \ 1714 V(saddlp, Saddlp) \ 1715 V(saddlv, Saddlv) \ 1716 V(smaxv, Smaxv) \ 1717 V(sminv, Sminv) \ 1718 V(sqabs, Sqabs) \ 1719 V(sqneg, Sqneg) \ 1720 V(sqxtn, Sqxtn) \ 1721 V(sqxtn2, Sqxtn2) \ 1722 V(sqxtun, Sqxtun) \ 1723 V(sqxtun2, Sqxtun2) \ 1724 V(suqadd, Suqadd) \ 1725 V(sxtl, Sxtl) \ 1726 V(sxtl2, Sxtl2) \ 1727 V(uadalp, Uadalp) \ 1728 V(uaddlp, Uaddlp) \ 1729 V(uaddlv, Uaddlv) \ 1730 V(umaxv, Umaxv) \ 1731 V(uminv, Uminv) \ 1732 V(uqxtn, Uqxtn) \ 1733 V(uqxtn2, Uqxtn2) \ 1734 V(urecpe, Urecpe) \ 1735 V(ursqrte, Ursqrte) \ 1736 V(usqadd, Usqadd) \ 1737 V(uxtl, Uxtl) \ 1738 V(uxtl2, Uxtl2) \ 1739 V(xtn, Xtn) \ 1740 V(xtn2, Xtn2) 1741 1742 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 1743 void MASM(const VRegister& vd, \ 1744 const VRegister& vn) { \ 1745 SingleEmissionCheckScope guard(this); \ 1746 ASM(vd, vn); \ 1747 } NEON_2VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)1748 NEON_2VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 1749 #undef DEFINE_MACRO_ASM_FUNC 1750 1751 // NEON 2 vector register with immediate instructions. 1752 #define NEON_2VREG_FPIMM_MACRO_LIST(V) \ 1753 V(fcmeq, Fcmeq) \ 1754 V(fcmge, Fcmge) \ 1755 V(fcmgt, Fcmgt) \ 1756 V(fcmle, Fcmle) \ 1757 V(fcmlt, Fcmlt) 1758 1759 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 1760 void MASM(const VRegister& vd, \ 1761 const VRegister& vn, \ 1762 double imm) { \ 1763 SingleEmissionCheckScope guard(this); \ 1764 ASM(vd, vn, imm); \ 1765 } 1766 NEON_2VREG_FPIMM_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 1767 #undef DEFINE_MACRO_ASM_FUNC 1768 1769 // NEON by element instructions. 1770 #define NEON_BYELEMENT_MACRO_LIST(V) \ 1771 V(fmul, Fmul) \ 1772 V(fmla, Fmla) \ 1773 V(fmls, Fmls) \ 1774 V(fmulx, Fmulx) \ 1775 V(mul, Mul) \ 1776 V(mla, Mla) \ 1777 V(mls, Mls) \ 1778 V(sqdmulh, Sqdmulh) \ 1779 V(sqrdmulh, Sqrdmulh) \ 1780 V(sqdmull, Sqdmull) \ 1781 V(sqdmull2, Sqdmull2) \ 1782 V(sqdmlal, Sqdmlal) \ 1783 V(sqdmlal2, Sqdmlal2) \ 1784 V(sqdmlsl, Sqdmlsl) \ 1785 V(sqdmlsl2, Sqdmlsl2) \ 1786 V(smull, Smull) \ 1787 V(smull2, Smull2) \ 1788 V(smlal, Smlal) \ 1789 V(smlal2, Smlal2) \ 1790 V(smlsl, Smlsl) \ 1791 V(smlsl2, Smlsl2) \ 1792 V(umull, Umull) \ 1793 V(umull2, Umull2) \ 1794 V(umlal, Umlal) \ 1795 V(umlal2, Umlal2) \ 1796 V(umlsl, Umlsl) \ 1797 V(umlsl2, Umlsl2) 1798 1799 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 1800 void MASM(const VRegister& vd, \ 1801 const VRegister& vn, \ 1802 const VRegister& vm, \ 1803 int vm_index \ 1804 ) { \ 1805 SingleEmissionCheckScope guard(this); \ 1806 ASM(vd, vn, vm, vm_index); \ 1807 } 1808 NEON_BYELEMENT_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 1809 #undef DEFINE_MACRO_ASM_FUNC 1810 1811 #define NEON_2VREG_SHIFT_MACRO_LIST(V) \ 1812 V(rshrn, Rshrn) \ 1813 V(rshrn2, Rshrn2) \ 1814 V(shl, Shl) \ 1815 V(shll, Shll) \ 1816 V(shll2, Shll2) \ 1817 V(shrn, Shrn) \ 1818 V(shrn2, Shrn2) \ 1819 V(sli, Sli) \ 1820 V(sqrshrn, Sqrshrn) \ 1821 V(sqrshrn2, Sqrshrn2) \ 1822 V(sqrshrun, Sqrshrun) \ 1823 V(sqrshrun2, Sqrshrun2) \ 1824 V(sqshl, Sqshl) \ 1825 V(sqshlu, Sqshlu) \ 1826 V(sqshrn, Sqshrn) \ 1827 V(sqshrn2, Sqshrn2) \ 1828 V(sqshrun, Sqshrun) \ 1829 V(sqshrun2, Sqshrun2) \ 1830 V(sri, Sri) \ 1831 V(srshr, Srshr) \ 1832 V(srsra, Srsra) \ 1833 V(sshll, Sshll) \ 1834 V(sshll2, Sshll2) \ 1835 V(sshr, Sshr) \ 1836 V(ssra, Ssra) \ 1837 V(uqrshrn, Uqrshrn) \ 1838 V(uqrshrn2, Uqrshrn2) \ 1839 V(uqshl, Uqshl) \ 1840 V(uqshrn, Uqshrn) \ 1841 V(uqshrn2, Uqshrn2) \ 1842 V(urshr, Urshr) \ 1843 V(ursra, Ursra) \ 1844 V(ushll, Ushll) \ 1845 V(ushll2, Ushll2) \ 1846 V(ushr, Ushr) \ 1847 V(usra, Usra) \ 1848 1849 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 1850 void MASM(const VRegister& vd, \ 1851 const VRegister& vn, \ 1852 int shift) { \ 1853 SingleEmissionCheckScope guard(this); \ 1854 ASM(vd, vn, shift); \ 1855 } 1856 NEON_2VREG_SHIFT_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 1857 #undef DEFINE_MACRO_ASM_FUNC 1858 1859 void Bic(const VRegister& vd, 1860 const int imm8, 1861 const int left_shift = 0) { 1862 SingleEmissionCheckScope guard(this); 1863 bic(vd, imm8, left_shift); 1864 } Cmeq(const VRegister & vd,const VRegister & vn,int imm)1865 void Cmeq(const VRegister& vd, 1866 const VRegister& vn, 1867 int imm) { 1868 SingleEmissionCheckScope guard(this); 1869 cmeq(vd, vn, imm); 1870 } Cmge(const VRegister & vd,const VRegister & vn,int imm)1871 void Cmge(const VRegister& vd, 1872 const VRegister& vn, 1873 int imm) { 1874 SingleEmissionCheckScope guard(this); 1875 cmge(vd, vn, imm); 1876 } Cmgt(const VRegister & vd,const VRegister & vn,int imm)1877 void Cmgt(const VRegister& vd, 1878 const VRegister& vn, 1879 int imm) { 1880 SingleEmissionCheckScope guard(this); 1881 cmgt(vd, vn, imm); 1882 } Cmle(const VRegister & vd,const VRegister & vn,int imm)1883 void Cmle(const VRegister& vd, 1884 const VRegister& vn, 1885 int imm) { 1886 SingleEmissionCheckScope guard(this); 1887 cmle(vd, vn, imm); 1888 } Cmlt(const VRegister & vd,const VRegister & vn,int imm)1889 void Cmlt(const VRegister& vd, 1890 const VRegister& vn, 1891 int imm) { 1892 SingleEmissionCheckScope guard(this); 1893 cmlt(vd, vn, imm); 1894 } Dup(const VRegister & vd,const VRegister & vn,int index)1895 void Dup(const VRegister& vd, 1896 const VRegister& vn, 1897 int index) { 1898 SingleEmissionCheckScope guard(this); 1899 dup(vd, vn, index); 1900 } Dup(const VRegister & vd,const Register & rn)1901 void Dup(const VRegister& vd, 1902 const Register& rn) { 1903 SingleEmissionCheckScope guard(this); 1904 dup(vd, rn); 1905 } Ext(const VRegister & vd,const VRegister & vn,const VRegister & vm,int index)1906 void Ext(const VRegister& vd, 1907 const VRegister& vn, 1908 const VRegister& vm, 1909 int index) { 1910 SingleEmissionCheckScope guard(this); 1911 ext(vd, vn, vm, index); 1912 } Ins(const VRegister & vd,int vd_index,const VRegister & vn,int vn_index)1913 void Ins(const VRegister& vd, 1914 int vd_index, 1915 const VRegister& vn, 1916 int vn_index) { 1917 SingleEmissionCheckScope guard(this); 1918 ins(vd, vd_index, vn, vn_index); 1919 } Ins(const VRegister & vd,int vd_index,const Register & rn)1920 void Ins(const VRegister& vd, 1921 int vd_index, 1922 const Register& rn) { 1923 SingleEmissionCheckScope guard(this); 1924 ins(vd, vd_index, rn); 1925 } Ld1(const VRegister & vt,const MemOperand & src)1926 void Ld1(const VRegister& vt, 1927 const MemOperand& src) { 1928 SingleEmissionCheckScope guard(this); 1929 ld1(vt, src); 1930 } Ld1(const VRegister & vt,const VRegister & vt2,const MemOperand & src)1931 void Ld1(const VRegister& vt, 1932 const VRegister& vt2, 1933 const MemOperand& src) { 1934 SingleEmissionCheckScope guard(this); 1935 ld1(vt, vt2, src); 1936 } Ld1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)1937 void Ld1(const VRegister& vt, 1938 const VRegister& vt2, 1939 const VRegister& vt3, 1940 const MemOperand& src) { 1941 SingleEmissionCheckScope guard(this); 1942 ld1(vt, vt2, vt3, src); 1943 } Ld1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)1944 void Ld1(const VRegister& vt, 1945 const VRegister& vt2, 1946 const VRegister& vt3, 1947 const VRegister& vt4, 1948 const MemOperand& src) { 1949 SingleEmissionCheckScope guard(this); 1950 ld1(vt, vt2, vt3, vt4, src); 1951 } Ld1(const VRegister & vt,int lane,const MemOperand & src)1952 void Ld1(const VRegister& vt, 1953 int lane, 1954 const MemOperand& src) { 1955 SingleEmissionCheckScope guard(this); 1956 ld1(vt, lane, src); 1957 } Ld1r(const VRegister & vt,const MemOperand & src)1958 void Ld1r(const VRegister& vt, 1959 const MemOperand& src) { 1960 SingleEmissionCheckScope guard(this); 1961 ld1r(vt, src); 1962 } Ld2(const VRegister & vt,const VRegister & vt2,const MemOperand & src)1963 void Ld2(const VRegister& vt, 1964 const VRegister& vt2, 1965 const MemOperand& src) { 1966 SingleEmissionCheckScope guard(this); 1967 ld2(vt, vt2, src); 1968 } Ld2(const VRegister & vt,const VRegister & vt2,int lane,const MemOperand & src)1969 void Ld2(const VRegister& vt, 1970 const VRegister& vt2, 1971 int lane, 1972 const MemOperand& src) { 1973 SingleEmissionCheckScope guard(this); 1974 ld2(vt, vt2, lane, src); 1975 } Ld2r(const VRegister & vt,const VRegister & vt2,const MemOperand & src)1976 void Ld2r(const VRegister& vt, 1977 const VRegister& vt2, 1978 const MemOperand& src) { 1979 SingleEmissionCheckScope guard(this); 1980 ld2r(vt, vt2, src); 1981 } Ld3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)1982 void Ld3(const VRegister& vt, 1983 const VRegister& vt2, 1984 const VRegister& vt3, 1985 const MemOperand& src) { 1986 SingleEmissionCheckScope guard(this); 1987 ld3(vt, vt2, vt3, src); 1988 } Ld3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,int lane,const MemOperand & src)1989 void Ld3(const VRegister& vt, 1990 const VRegister& vt2, 1991 const VRegister& vt3, 1992 int lane, 1993 const MemOperand& src) { 1994 SingleEmissionCheckScope guard(this); 1995 ld3(vt, vt2, vt3, lane, src); 1996 } Ld3r(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)1997 void Ld3r(const VRegister& vt, 1998 const VRegister& vt2, 1999 const VRegister& vt3, 2000 const MemOperand& src) { 2001 SingleEmissionCheckScope guard(this); 2002 ld3r(vt, vt2, vt3, src); 2003 } Ld4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)2004 void Ld4(const VRegister& vt, 2005 const VRegister& vt2, 2006 const VRegister& vt3, 2007 const VRegister& vt4, 2008 const MemOperand& src) { 2009 SingleEmissionCheckScope guard(this); 2010 ld4(vt, vt2, vt3, vt4, src); 2011 } Ld4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,int lane,const MemOperand & src)2012 void Ld4(const VRegister& vt, 2013 const VRegister& vt2, 2014 const VRegister& vt3, 2015 const VRegister& vt4, 2016 int lane, 2017 const MemOperand& src) { 2018 SingleEmissionCheckScope guard(this); 2019 ld4(vt, vt2, vt3, vt4, lane, src); 2020 } Ld4r(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)2021 void Ld4r(const VRegister& vt, 2022 const VRegister& vt2, 2023 const VRegister& vt3, 2024 const VRegister& vt4, 2025 const MemOperand& src) { 2026 SingleEmissionCheckScope guard(this); 2027 ld4r(vt, vt2, vt3, vt4, src); 2028 } Mov(const VRegister & vd,int vd_index,const VRegister & vn,int vn_index)2029 void Mov(const VRegister& vd, 2030 int vd_index, 2031 const VRegister& vn, 2032 int vn_index) { 2033 SingleEmissionCheckScope guard(this); 2034 mov(vd, vd_index, vn, vn_index); 2035 } Mov(const VRegister & vd,const VRegister & vn,int index)2036 void Mov(const VRegister& vd, 2037 const VRegister& vn, 2038 int index) { 2039 SingleEmissionCheckScope guard(this); 2040 mov(vd, vn, index); 2041 } Mov(const VRegister & vd,int vd_index,const Register & rn)2042 void Mov(const VRegister& vd, 2043 int vd_index, 2044 const Register& rn) { 2045 SingleEmissionCheckScope guard(this); 2046 mov(vd, vd_index, rn); 2047 } Mov(const Register & rd,const VRegister & vn,int vn_index)2048 void Mov(const Register& rd, 2049 const VRegister& vn, 2050 int vn_index) { 2051 SingleEmissionCheckScope guard(this); 2052 mov(rd, vn, vn_index); 2053 } 2054 void Movi(const VRegister& vd, 2055 uint64_t imm, 2056 Shift shift = LSL, 2057 int shift_amount = 0); 2058 void Movi(const VRegister& vd, uint64_t hi, uint64_t lo); 2059 void Mvni(const VRegister& vd, 2060 const int imm8, 2061 Shift shift = LSL, 2062 const int shift_amount = 0) { 2063 SingleEmissionCheckScope guard(this); 2064 mvni(vd, imm8, shift, shift_amount); 2065 } 2066 void Orr(const VRegister& vd, 2067 const int imm8, 2068 const int left_shift = 0) { 2069 SingleEmissionCheckScope guard(this); 2070 orr(vd, imm8, left_shift); 2071 } 2072 void Scvtf(const VRegister& vd, 2073 const VRegister& vn, 2074 int fbits = 0) { 2075 SingleEmissionCheckScope guard(this); 2076 scvtf(vd, vn, fbits); 2077 } 2078 void Ucvtf(const VRegister& vd, 2079 const VRegister& vn, 2080 int fbits = 0) { 2081 SingleEmissionCheckScope guard(this); 2082 ucvtf(vd, vn, fbits); 2083 } 2084 void Fcvtzs(const VRegister& vd, 2085 const VRegister& vn, 2086 int fbits = 0) { 2087 SingleEmissionCheckScope guard(this); 2088 fcvtzs(vd, vn, fbits); 2089 } 2090 void Fcvtzu(const VRegister& vd, 2091 const VRegister& vn, 2092 int fbits = 0) { 2093 SingleEmissionCheckScope guard(this); 2094 fcvtzu(vd, vn, fbits); 2095 } St1(const VRegister & vt,const MemOperand & dst)2096 void St1(const VRegister& vt, 2097 const MemOperand& dst) { 2098 SingleEmissionCheckScope guard(this); 2099 st1(vt, dst); 2100 } St1(const VRegister & vt,const VRegister & vt2,const MemOperand & dst)2101 void St1(const VRegister& vt, 2102 const VRegister& vt2, 2103 const MemOperand& dst) { 2104 SingleEmissionCheckScope guard(this); 2105 st1(vt, vt2, dst); 2106 } St1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & dst)2107 void St1(const VRegister& vt, 2108 const VRegister& vt2, 2109 const VRegister& vt3, 2110 const MemOperand& dst) { 2111 SingleEmissionCheckScope guard(this); 2112 st1(vt, vt2, vt3, dst); 2113 } St1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & dst)2114 void St1(const VRegister& vt, 2115 const VRegister& vt2, 2116 const VRegister& vt3, 2117 const VRegister& vt4, 2118 const MemOperand& dst) { 2119 SingleEmissionCheckScope guard(this); 2120 st1(vt, vt2, vt3, vt4, dst); 2121 } St1(const VRegister & vt,int lane,const MemOperand & dst)2122 void St1(const VRegister& vt, 2123 int lane, 2124 const MemOperand& dst) { 2125 SingleEmissionCheckScope guard(this); 2126 st1(vt, lane, dst); 2127 } St2(const VRegister & vt,const VRegister & vt2,const MemOperand & dst)2128 void St2(const VRegister& vt, 2129 const VRegister& vt2, 2130 const MemOperand& dst) { 2131 SingleEmissionCheckScope guard(this); 2132 st2(vt, vt2, dst); 2133 } St3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & dst)2134 void St3(const VRegister& vt, 2135 const VRegister& vt2, 2136 const VRegister& vt3, 2137 const MemOperand& dst) { 2138 SingleEmissionCheckScope guard(this); 2139 st3(vt, vt2, vt3, dst); 2140 } St4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & dst)2141 void St4(const VRegister& vt, 2142 const VRegister& vt2, 2143 const VRegister& vt3, 2144 const VRegister& vt4, 2145 const MemOperand& dst) { 2146 SingleEmissionCheckScope guard(this); 2147 st4(vt, vt2, vt3, vt4, dst); 2148 } St2(const VRegister & vt,const VRegister & vt2,int lane,const MemOperand & dst)2149 void St2(const VRegister& vt, 2150 const VRegister& vt2, 2151 int lane, 2152 const MemOperand& dst) { 2153 SingleEmissionCheckScope guard(this); 2154 st2(vt, vt2, lane, dst); 2155 } St3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,int lane,const MemOperand & dst)2156 void St3(const VRegister& vt, 2157 const VRegister& vt2, 2158 const VRegister& vt3, 2159 int lane, 2160 const MemOperand& dst) { 2161 SingleEmissionCheckScope guard(this); 2162 st3(vt, vt2, vt3, lane, dst); 2163 } St4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,int lane,const MemOperand & dst)2164 void St4(const VRegister& vt, 2165 const VRegister& vt2, 2166 const VRegister& vt3, 2167 const VRegister& vt4, 2168 int lane, 2169 const MemOperand& dst) { 2170 SingleEmissionCheckScope guard(this); 2171 st4(vt, vt2, vt3, vt4, lane, dst); 2172 } Smov(const Register & rd,const VRegister & vn,int vn_index)2173 void Smov(const Register& rd, 2174 const VRegister& vn, 2175 int vn_index) { 2176 SingleEmissionCheckScope guard(this); 2177 smov(rd, vn, vn_index); 2178 } Umov(const Register & rd,const VRegister & vn,int vn_index)2179 void Umov(const Register& rd, 2180 const VRegister& vn, 2181 int vn_index) { 2182 SingleEmissionCheckScope guard(this); 2183 umov(rd, vn, vn_index); 2184 } Crc32b(const Register & rd,const Register & rn,const Register & rm)2185 void Crc32b(const Register& rd, 2186 const Register& rn, 2187 const Register& rm) { 2188 SingleEmissionCheckScope guard(this); 2189 crc32b(rd, rn, rm); 2190 } Crc32h(const Register & rd,const Register & rn,const Register & rm)2191 void Crc32h(const Register& rd, 2192 const Register& rn, 2193 const Register& rm) { 2194 SingleEmissionCheckScope guard(this); 2195 crc32h(rd, rn, rm); 2196 } Crc32w(const Register & rd,const Register & rn,const Register & rm)2197 void Crc32w(const Register& rd, 2198 const Register& rn, 2199 const Register& rm) { 2200 SingleEmissionCheckScope guard(this); 2201 crc32w(rd, rn, rm); 2202 } Crc32x(const Register & rd,const Register & rn,const Register & rm)2203 void Crc32x(const Register& rd, 2204 const Register& rn, 2205 const Register& rm) { 2206 SingleEmissionCheckScope guard(this); 2207 crc32x(rd, rn, rm); 2208 } Crc32cb(const Register & rd,const Register & rn,const Register & rm)2209 void Crc32cb(const Register& rd, 2210 const Register& rn, 2211 const Register& rm) { 2212 SingleEmissionCheckScope guard(this); 2213 crc32cb(rd, rn, rm); 2214 } Crc32ch(const Register & rd,const Register & rn,const Register & rm)2215 void Crc32ch(const Register& rd, 2216 const Register& rn, 2217 const Register& rm) { 2218 SingleEmissionCheckScope guard(this); 2219 crc32ch(rd, rn, rm); 2220 } Crc32cw(const Register & rd,const Register & rn,const Register & rm)2221 void Crc32cw(const Register& rd, 2222 const Register& rn, 2223 const Register& rm) { 2224 SingleEmissionCheckScope guard(this); 2225 crc32cw(rd, rn, rm); 2226 } Crc32cx(const Register & rd,const Register & rn,const Register & rm)2227 void Crc32cx(const Register& rd, 2228 const Register& rn, 2229 const Register& rm) { 2230 SingleEmissionCheckScope guard(this); 2231 crc32cx(rd, rn, rm); 2232 } 2233 2234 // Push the system stack pointer (sp) down to allow the same to be done to 2235 // the current stack pointer (according to StackPointer()). This must be 2236 // called _before_ accessing the memory. 2237 // 2238 // This is necessary when pushing or otherwise adding things to the stack, to 2239 // satisfy the AAPCS64 constraint that the memory below the system stack 2240 // pointer is not accessed. 2241 // 2242 // This method asserts that StackPointer() is not sp, since the call does 2243 // not make sense in that context. 2244 // 2245 // TODO: This method can only accept values of 'space' that can be encoded in 2246 // one instruction. Refer to the implementation for details. 2247 void BumpSystemStackPointer(const Operand& space); 2248 2249 // Set the current stack pointer, but don't generate any code. SetStackPointer64(const Register & stack_pointer)2250 void SetStackPointer64(const Register& stack_pointer) { 2251 VIXL_ASSERT(!TmpList()->IncludesAliasOf(stack_pointer)); 2252 sp_ = stack_pointer; 2253 } 2254 2255 // Return the current stack pointer, as set by SetStackPointer. StackPointer()2256 const Register& StackPointer() const { 2257 return sp_; 2258 } 2259 GetStackPointer64()2260 const Register& GetStackPointer64() const { 2261 return sp_; 2262 } 2263 getStackPointer()2264 const js::jit::RegisterOrSP getStackPointer() const { 2265 return js::jit::RegisterOrSP(sp_.code()); 2266 } 2267 TmpList()2268 CPURegList* TmpList() { return &tmp_list_; } FPTmpList()2269 CPURegList* FPTmpList() { return &fptmp_list_; } 2270 2271 // Trace control when running the debug simulator. 2272 // 2273 // For example: 2274 // 2275 // __ Trace(LOG_REGS, TRACE_ENABLE); 2276 // Will add registers to the trace if it wasn't already the case. 2277 // 2278 // __ Trace(LOG_DISASM, TRACE_DISABLE); 2279 // Will stop logging disassembly. It has no effect if the disassembly wasn't 2280 // already being logged. 2281 void Trace(TraceParameters parameters, TraceCommand command); 2282 2283 // Log the requested data independently of what is being traced. 2284 // 2285 // For example: 2286 // 2287 // __ Log(LOG_FLAGS) 2288 // Will output the flags. 2289 void Log(TraceParameters parameters); 2290 2291 // Enable or disable instrumentation when an Instrument visitor is attached to 2292 // the simulator. 2293 void EnableInstrumentation(); 2294 void DisableInstrumentation(); 2295 2296 // Add a marker to the instrumentation data produced by an Instrument visitor. 2297 // The name is a two character string that will be attached to the marker in 2298 // the output data. 2299 void AnnotateInstrumentation(const char* marker_name); 2300 2301 private: 2302 // The actual Push and Pop implementations. These don't generate any code 2303 // other than that required for the push or pop. This allows 2304 // (Push|Pop)CPURegList to bundle together setup code for a large block of 2305 // registers. 2306 // 2307 // Note that size is per register, and is specified in bytes. 2308 void PushHelper(int count, int size, 2309 const CPURegister& src0, const CPURegister& src1, 2310 const CPURegister& src2, const CPURegister& src3); 2311 void PopHelper(int count, int size, 2312 const CPURegister& dst0, const CPURegister& dst1, 2313 const CPURegister& dst2, const CPURegister& dst3); 2314 2315 void Movi16bitHelper(const VRegister& vd, uint64_t imm); 2316 void Movi32bitHelper(const VRegister& vd, uint64_t imm); 2317 void Movi64bitHelper(const VRegister& vd, uint64_t imm); 2318 2319 // Perform necessary maintenance operations before a push or pop. 2320 // 2321 // Note that size is per register, and is specified in bytes. 2322 void PrepareForPush(int count, int size); 2323 void PrepareForPop(int count, int size); 2324 2325 // The actual implementation of load and store operations for CPURegList. 2326 enum LoadStoreCPURegListAction { 2327 kLoad, 2328 kStore 2329 }; 2330 void LoadStoreCPURegListHelper(LoadStoreCPURegListAction operation, 2331 CPURegList registers, 2332 const MemOperand& mem); 2333 // Returns a MemOperand suitable for loading or storing a CPURegList at `dst`. 2334 // This helper may allocate registers from `scratch_scope` and generate code 2335 // to compute an intermediate address. The resulting MemOperand is only valid 2336 // as long as `scratch_scope` remains valid. 2337 MemOperand BaseMemOperandForLoadStoreCPURegList( 2338 const CPURegList& registers, 2339 const MemOperand& mem, 2340 UseScratchRegisterScope* scratch_scope); 2341 LabelIsOutOfRange(Label * label,ImmBranchType branch_type)2342 bool LabelIsOutOfRange(Label* label, ImmBranchType branch_type) { 2343 return !Instruction::IsValidImmPCOffset(branch_type, nextOffset().getOffset() - label->offset()); 2344 } 2345 2346 // The register to use as a stack pointer for stack operations. 2347 Register sp_; 2348 2349 // Scratch registers available for use by the MacroAssembler. 2350 CPURegList tmp_list_; 2351 CPURegList fptmp_list_; 2352 2353 ptrdiff_t checkpoint_; 2354 ptrdiff_t recommended_checkpoint_; 2355 }; 2356 2357 2358 // All Assembler emits MUST acquire/release the underlying code buffer. The 2359 // helper scope below will do so and optionally ensure the buffer is big enough 2360 // to receive the emit. It is possible to request the scope not to perform any 2361 // checks (kNoCheck) if for example it is known in advance the buffer size is 2362 // adequate or there is some other size checking mechanism in place. 2363 class CodeBufferCheckScope { 2364 public: 2365 // Tell whether or not the scope needs to ensure the associated CodeBuffer 2366 // has enough space for the requested size. 2367 enum CheckPolicy { 2368 kNoCheck, 2369 kCheck 2370 }; 2371 2372 // Tell whether or not the scope should assert the amount of code emitted 2373 // within the scope is consistent with the requested amount. 2374 enum AssertPolicy { 2375 kNoAssert, // No assert required. 2376 kExactSize, // The code emitted must be exactly size bytes. 2377 kMaximumSize // The code emitted must be at most size bytes. 2378 }; 2379 2380 CodeBufferCheckScope(Assembler* assm, 2381 size_t size, 2382 CheckPolicy check_policy = kCheck, 2383 AssertPolicy assert_policy = kMaximumSize) 2384 { } 2385 2386 // This is a shortcut for CodeBufferCheckScope(assm, 0, kNoCheck, kNoAssert). CodeBufferCheckScope(Assembler * assm)2387 explicit CodeBufferCheckScope(Assembler* assm) {} 2388 }; 2389 2390 2391 // Use this scope when you need a one-to-one mapping between methods and 2392 // instructions. This scope prevents the MacroAssembler from being called and 2393 // literal pools from being emitted. It also asserts the number of instructions 2394 // emitted is what you specified when creating the scope. 2395 // FIXME: Because of the disabled calls below, this class asserts nothing. 2396 class InstructionAccurateScope : public CodeBufferCheckScope { 2397 public: 2398 InstructionAccurateScope(MacroAssembler* masm, 2399 int64_t count, 2400 AssertPolicy policy = kExactSize) 2401 : CodeBufferCheckScope(masm, 2402 (count * kInstructionSize), 2403 kCheck, 2404 policy) { 2405 } 2406 }; 2407 2408 2409 // This scope utility allows scratch registers to be managed safely. The 2410 // MacroAssembler's TmpList() (and FPTmpList()) is used as a pool of scratch 2411 // registers. These registers can be allocated on demand, and will be returned 2412 // at the end of the scope. 2413 // 2414 // When the scope ends, the MacroAssembler's lists will be restored to their 2415 // original state, even if the lists were modified by some other means. 2416 class UseScratchRegisterScope { 2417 public: 2418 // This constructor implicitly calls the `Open` function to initialise the 2419 // scope, so it is ready to use immediately after it has been constructed. 2420 explicit UseScratchRegisterScope(MacroAssembler* masm); 2421 // This constructor allows deferred and optional initialisation of the scope. 2422 // The user is required to explicitly call the `Open` function before using 2423 // the scope. 2424 UseScratchRegisterScope(); 2425 // This function performs the actual initialisation work. 2426 void Open(MacroAssembler* masm); 2427 2428 // The destructor always implicitly calls the `Close` function. 2429 ~UseScratchRegisterScope(); 2430 // This function performs the cleaning-up work. It must succeed even if the 2431 // scope has not been opened. It is safe to call multiple times. 2432 void Close(); 2433 2434 2435 bool IsAvailable(const CPURegister& reg) const; 2436 2437 2438 // Take a register from the appropriate temps list. It will be returned 2439 // automatically when the scope ends. AcquireW()2440 Register AcquireW() { return AcquireNextAvailable(available_).W(); } AcquireX()2441 Register AcquireX() { return AcquireNextAvailable(available_).X(); } AcquireS()2442 VRegister AcquireS() { return AcquireNextAvailable(availablefp_).S(); } AcquireD()2443 VRegister AcquireD() { return AcquireNextAvailable(availablefp_).D(); } 2444 2445 2446 Register AcquireSameSizeAs(const Register& reg); 2447 VRegister AcquireSameSizeAs(const VRegister& reg); 2448 2449 2450 // Explicitly release an acquired (or excluded) register, putting it back in 2451 // the appropriate temps list. 2452 void Release(const CPURegister& reg); 2453 2454 2455 // Make the specified registers available as scratch registers for the 2456 // duration of this scope. 2457 void Include(const CPURegList& list); 2458 void Include(const Register& reg1, 2459 const Register& reg2 = NoReg, 2460 const Register& reg3 = NoReg, 2461 const Register& reg4 = NoReg); 2462 void Include(const VRegister& reg1, 2463 const VRegister& reg2 = NoVReg, 2464 const VRegister& reg3 = NoVReg, 2465 const VRegister& reg4 = NoVReg); 2466 2467 2468 // Make sure that the specified registers are not available in this scope. 2469 // This can be used to prevent helper functions from using sensitive 2470 // registers, for example. 2471 void Exclude(const CPURegList& list); 2472 void Exclude(const Register& reg1, 2473 const Register& reg2 = NoReg, 2474 const Register& reg3 = NoReg, 2475 const Register& reg4 = NoReg); 2476 void Exclude(const VRegister& reg1, 2477 const VRegister& reg2 = NoVReg, 2478 const VRegister& reg3 = NoVReg, 2479 const VRegister& reg4 = NoVReg); 2480 void Exclude(const CPURegister& reg1, 2481 const CPURegister& reg2 = NoCPUReg, 2482 const CPURegister& reg3 = NoCPUReg, 2483 const CPURegister& reg4 = NoCPUReg); 2484 2485 2486 // Prevent any scratch registers from being used in this scope. 2487 void ExcludeAll(); 2488 2489 2490 private: 2491 static CPURegister AcquireNextAvailable(CPURegList* available); 2492 2493 static void ReleaseByCode(CPURegList* available, int code); 2494 2495 static void ReleaseByRegList(CPURegList* available, 2496 RegList regs); 2497 2498 static void IncludeByRegList(CPURegList* available, 2499 RegList exclude); 2500 2501 static void ExcludeByRegList(CPURegList* available, 2502 RegList exclude); 2503 2504 // Available scratch registers. 2505 CPURegList* available_; // kRegister 2506 CPURegList* availablefp_; // kVRegister 2507 2508 // The state of the available lists at the start of this scope. 2509 RegList old_available_; // kRegister 2510 RegList old_availablefp_; // kVRegister 2511 #ifdef DEBUG 2512 bool initialised_; 2513 #endif 2514 2515 // Disallow copy constructor and operator=. UseScratchRegisterScope(const UseScratchRegisterScope &)2516 UseScratchRegisterScope(const UseScratchRegisterScope&) { 2517 VIXL_UNREACHABLE(); 2518 } 2519 void operator=(const UseScratchRegisterScope&) { 2520 VIXL_UNREACHABLE(); 2521 } 2522 }; 2523 2524 2525 } // namespace vixl 2526 2527 #endif // VIXL_A64_MACRO_ASSEMBLER_A64_H_ 2528