1 // Copyright 2013, ARM Limited 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #ifndef VIXL_A64_MACRO_ASSEMBLER_A64_H_ 28 #define VIXL_A64_MACRO_ASSEMBLER_A64_H_ 29 30 #include "globals-vixl.h" 31 #include "a64/assembler-a64.h" 32 #include "a64/debugger-a64.h" 33 34 35 #define LS_MACRO_LIST(V) \ 36 V(Ldrb, Register&, rt, LDRB_w) \ 37 V(Strb, Register&, rt, STRB_w) \ 38 V(Ldrsb, Register&, rt, rt.Is64Bits() ? LDRSB_x : LDRSB_w) \ 39 V(Ldrh, Register&, rt, LDRH_w) \ 40 V(Strh, Register&, rt, STRH_w) \ 41 V(Ldrsh, Register&, rt, rt.Is64Bits() ? LDRSH_x : LDRSH_w) \ 42 V(Ldr, CPURegister&, rt, LoadOpFor(rt)) \ 43 V(Str, CPURegister&, rt, StoreOpFor(rt)) \ 44 V(Ldrsw, Register&, rt, LDRSW_x) 45 46 namespace vixl { 47 48 enum BranchType { 49 // Copies of architectural conditions. 50 // The associated conditions can be used in place of those, the code will 51 // take care of reinterpreting them with the correct type. 52 integer_eq = eq, 53 integer_ne = ne, 54 integer_hs = hs, 55 integer_lo = lo, 56 integer_mi = mi, 57 integer_pl = pl, 58 integer_vs = vs, 59 integer_vc = vc, 60 integer_hi = hi, 61 integer_ls = ls, 62 integer_ge = ge, 63 integer_lt = lt, 64 integer_gt = gt, 65 integer_le = le, 66 integer_al = al, 67 integer_nv = nv, 68 69 // These two are *different* from the architectural codes al and nv. 70 // 'always' is used to generate unconditional branches. 71 // 'never' is used to not generate a branch (generally as the inverse 72 // branch type of 'always). 73 always, never, 74 // cbz and cbnz 75 reg_zero, reg_not_zero, 76 // tbz and tbnz 77 reg_bit_clear, reg_bit_set, 78 79 // Aliases. 80 kBranchTypeFirstCondition = eq, 81 kBranchTypeLastCondition = nv, 82 kBranchTypeFirstUsingReg = reg_zero, 83 kBranchTypeFirstUsingBit = reg_bit_clear 84 }; 85 86 87 enum DiscardMoveMode { kDontDiscardForSameWReg, kDiscardForSameWReg }; 88 89 class MacroAssembler : public Assembler { 90 public: 91 MacroAssembler(byte * buffer, unsigned buffer_size) 92 : Assembler(buffer, buffer_size), 93 #ifdef DEBUG 94 allow_macro_instructions_(true), 95 #endif 96 sp_(sp), tmp_list_(ip0, ip1), fptmp_list_(d31) {} 97 98 // Logical macros. 99 void And(const Register& rd, 100 const Register& rn, 101 const Operand& operand); 102 void Ands(const Register& rd, 103 const Register& rn, 104 const Operand& operand); 105 void Bic(const Register& rd, 106 const Register& rn, 107 const Operand& operand); 108 void Bics(const Register& rd, 109 const Register& rn, 110 const Operand& operand); 111 void Orr(const Register& rd, 112 const Register& rn, 113 const Operand& operand); 114 void Orn(const Register& rd, 115 const Register& rn, 116 const Operand& operand); 117 void Eor(const Register& rd, 118 const Register& rn, 119 const Operand& operand); 120 void Eon(const Register& rd, 121 const Register& rn, 122 const Operand& operand); 123 void Tst(const Register& rn, const Operand& operand); 124 void LogicalMacro(const Register& rd, 125 const Register& rn, 126 const Operand& operand, 127 LogicalOp op); 128 129 // Add and sub macros. 130 void Add(const Register& rd, 131 const Register& rn, 132 const Operand& operand); 133 void Adds(const Register& rd, 134 const Register& rn, 135 const Operand& operand); 136 void Sub(const Register& rd, 137 const Register& rn, 138 const Operand& operand); 139 void Subs(const Register& rd, 140 const Register& rn, 141 const Operand& operand); 142 void Cmn(const Register& rn, const Operand& operand); 143 void Cmp(const Register& rn, const Operand& operand); 144 void Neg(const Register& rd, 145 const Operand& operand); 146 void Negs(const Register& rd, 147 const Operand& operand); 148 149 void AddSubMacro(const Register& rd, 150 const Register& rn, 151 const Operand& operand, 152 FlagsUpdate S, 153 AddSubOp op); 154 155 // Add/sub with carry macros. 156 void Adc(const Register& rd, 157 const Register& rn, 158 const Operand& operand); 159 void Adcs(const Register& rd, 160 const Register& rn, 161 const Operand& operand); 162 void Sbc(const Register& rd, 163 const Register& rn, 164 const Operand& operand); 165 void Sbcs(const Register& rd, 166 const Register& rn, 167 const Operand& operand); 168 void Ngc(const Register& rd, 169 const Operand& operand); 170 void Ngcs(const Register& rd, 171 const Operand& operand); 172 void AddSubWithCarryMacro(const Register& rd, 173 const Register& rn, 174 const Operand& operand, 175 FlagsUpdate S, 176 AddSubWithCarryOp op); 177 178 // Move macros. 179 void Mov(const Register& rd, uint64_t imm); 180 void Mov(const Register& rd, 181 const Operand& operand, 182 DiscardMoveMode discard_mode = kDontDiscardForSameWReg); 183 void Mvn(const Register& rd, uint64_t imm) { 184 Mov(rd, (rd.size() == kXRegSize) ? ~imm : (~imm & kWRegMask)); 185 }; 186 void Mvn(const Register& rd, const Operand& operand); 187 bool IsImmMovz(uint64_t imm, unsigned reg_size); 188 bool IsImmMovn(uint64_t imm, unsigned reg_size); 189 unsigned CountClearHalfWords(uint64_t imm, unsigned reg_size); 190 191 // Conditional macros. 192 void Ccmp(const Register& rn, 193 const Operand& operand, 194 StatusFlags nzcv, 195 Condition cond); 196 void Ccmn(const Register& rn, 197 const Operand& operand, 198 StatusFlags nzcv, 199 Condition cond); 200 void ConditionalCompareMacro(const Register& rn, 201 const Operand& operand, 202 StatusFlags nzcv, 203 Condition cond, 204 ConditionalCompareOp op); 205 void Csel(const Register& rd, 206 const Register& rn, 207 const Operand& operand, 208 Condition cond); 209 210 // Load/store macros. 211 #define DECLARE_FUNCTION(FN, REGTYPE, REG, OP) \ 212 void FN(const REGTYPE REG, const MemOperand& addr); 213 LS_MACRO_LIST(DECLARE_FUNCTION) 214 #undef DECLARE_FUNCTION 215 216 void LoadStoreMacro(const CPURegister& rt, 217 const MemOperand& addr, 218 LoadStoreOp op); 219 220 // Push or pop up to 4 registers of the same width to or from the stack, 221 // using the current stack pointer as set by SetStackPointer. 222 // 223 // If an argument register is 'NoReg', all further arguments are also assumed 224 // to be 'NoReg', and are thus not pushed or popped. 225 // 226 // Arguments are ordered such that "Push(a, b);" is functionally equivalent 227 // to "Push(a); Push(b);". 228 // 229 // It is valid to push the same register more than once, and there is no 230 // restriction on the order in which registers are specified. 231 // 232 // It is not valid to pop into the same register more than once in one 233 // operation, not even into the zero register. 234 // 235 // If the current stack pointer (as set by SetStackPointer) is sp, then it 236 // must be aligned to 16 bytes on entry and the total size of the specified 237 // registers must also be a multiple of 16 bytes. 238 // 239 // Even if the current stack pointer is not the system stack pointer (sp), 240 // Push (and derived methods) will still modify the system stack pointer in 241 // order to comply with ABI rules about accessing memory below the system 242 // stack pointer. 243 // 244 // Other than the registers passed into Pop, the stack pointer and (possibly) 245 // the system stack pointer, these methods do not modify any other registers. 246 void Push(const CPURegister& src0, const CPURegister& src1 = NoReg, 247 const CPURegister& src2 = NoReg, const CPURegister& src3 = NoReg); 248 void Pop(const CPURegister& dst0, const CPURegister& dst1 = NoReg, 249 const CPURegister& dst2 = NoReg, const CPURegister& dst3 = NoReg); 250 251 // Alternative forms of Push and Pop, taking a RegList or CPURegList that 252 // specifies the registers that are to be pushed or popped. Higher-numbered 253 // registers are associated with higher memory addresses (as in the A32 push 254 // and pop instructions). 255 // 256 // (Push|Pop)SizeRegList allow you to specify the register size as a 257 // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are 258 // supported. 259 // 260 // Otherwise, (Push|Pop)(CPU|X|W|D|S)RegList is preferred. 261 void PushCPURegList(CPURegList registers); 262 void PopCPURegList(CPURegList registers); 263 264 void PushSizeRegList(RegList registers, unsigned reg_size, 265 CPURegister::RegisterType type = CPURegister::kRegister) { 266 PushCPURegList(CPURegList(type, reg_size, registers)); 267 } 268 void PopSizeRegList(RegList registers, unsigned reg_size, 269 CPURegister::RegisterType type = CPURegister::kRegister) { 270 PopCPURegList(CPURegList(type, reg_size, registers)); 271 } 272 void PushXRegList(RegList regs) { 273 PushSizeRegList(regs, kXRegSize); 274 } 275 void PopXRegList(RegList regs) { 276 PopSizeRegList(regs, kXRegSize); 277 } 278 void PushWRegList(RegList regs) { 279 PushSizeRegList(regs, kWRegSize); 280 } 281 void PopWRegList(RegList regs) { 282 PopSizeRegList(regs, kWRegSize); 283 } 284 inline void PushDRegList(RegList regs) { 285 PushSizeRegList(regs, kDRegSize, CPURegister::kFPRegister); 286 } 287 inline void PopDRegList(RegList regs) { 288 PopSizeRegList(regs, kDRegSize, CPURegister::kFPRegister); 289 } 290 inline void PushSRegList(RegList regs) { 291 PushSizeRegList(regs, kSRegSize, CPURegister::kFPRegister); 292 } 293 inline void PopSRegList(RegList regs) { 294 PopSizeRegList(regs, kSRegSize, CPURegister::kFPRegister); 295 } 296 297 // Push the specified register 'count' times. 298 void PushMultipleTimes(int count, Register src); 299 300 // Poke 'src' onto the stack. The offset is in bytes. 301 // 302 // If the current stack pointer (as set by SetStackPointer) is sp, then sp 303 // must be aligned to 16 bytes. 304 void Poke(const Register& src, const Operand& offset); 305 306 // Peek at a value on the stack, and put it in 'dst'. The offset is in bytes. 307 // 308 // If the current stack pointer (as set by SetStackPointer) is sp, then sp 309 // must be aligned to 16 bytes. 310 void Peek(const Register& dst, const Operand& offset); 311 312 // Claim or drop stack space without actually accessing memory. 313 // 314 // If the current stack pointer (as set by SetStackPointer) is sp, then it 315 // must be aligned to 16 bytes and the size claimed or dropped must be a 316 // multiple of 16 bytes. 317 void Claim(const Operand& size); 318 void Drop(const Operand& size); 319 320 // Preserve the callee-saved registers (as defined by AAPCS64). 321 // 322 // Higher-numbered registers are pushed before lower-numbered registers, and 323 // thus get higher addresses. 324 // Floating-point registers are pushed before general-purpose registers, and 325 // thus get higher addresses. 326 // 327 // This method must not be called unless StackPointer() is sp, and it is 328 // aligned to 16 bytes. 329 void PushCalleeSavedRegisters(); 330 331 // Restore the callee-saved registers (as defined by AAPCS64). 332 // 333 // Higher-numbered registers are popped after lower-numbered registers, and 334 // thus come from higher addresses. 335 // Floating-point registers are popped after general-purpose registers, and 336 // thus come from higher addresses. 337 // 338 // This method must not be called unless StackPointer() is sp, and it is 339 // aligned to 16 bytes. 340 void PopCalleeSavedRegisters(); 341 342 // Remaining instructions are simple pass-through calls to the assembler. 343 void Adr(const Register& rd, Label* label) { 344 VIXL_ASSERT(allow_macro_instructions_); 345 VIXL_ASSERT(!rd.IsZero()); 346 adr(rd, label); 347 } 348 void Asr(const Register& rd, const Register& rn, unsigned shift) { 349 VIXL_ASSERT(allow_macro_instructions_); 350 VIXL_ASSERT(!rd.IsZero()); 351 VIXL_ASSERT(!rn.IsZero()); 352 asr(rd, rn, shift); 353 } 354 void Asr(const Register& rd, const Register& rn, const Register& rm) { 355 VIXL_ASSERT(allow_macro_instructions_); 356 VIXL_ASSERT(!rd.IsZero()); 357 VIXL_ASSERT(!rn.IsZero()); 358 VIXL_ASSERT(!rm.IsZero()); 359 asrv(rd, rn, rm); 360 } 361 362 // Branch type inversion relies on these relations. 363 VIXL_STATIC_ASSERT((reg_zero == (reg_not_zero ^ 1)) && 364 (reg_bit_clear == (reg_bit_set ^ 1)) && 365 (always == (never ^ 1))); 366 367 BranchType InvertBranchType(BranchType type) { 368 if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) { 369 return static_cast<BranchType>( 370 InvertCondition(static_cast<Condition>(type))); 371 } else { 372 return static_cast<BranchType>(type ^ 1); 373 } 374 } 375 376 void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1); 377 378 void B(Label* label) { 379 b(label); 380 } 381 void B(Label* label, Condition cond) { 382 VIXL_ASSERT(allow_macro_instructions_); 383 VIXL_ASSERT((cond != al) && (cond != nv)); 384 b(label, cond); 385 } 386 void B(Condition cond, Label* label) { 387 B(label, cond); 388 } 389 void Bfi(const Register& rd, 390 const Register& rn, 391 unsigned lsb, 392 unsigned width) { 393 VIXL_ASSERT(allow_macro_instructions_); 394 VIXL_ASSERT(!rd.IsZero()); 395 VIXL_ASSERT(!rn.IsZero()); 396 bfi(rd, rn, lsb, width); 397 } 398 void Bfxil(const Register& rd, 399 const Register& rn, 400 unsigned lsb, 401 unsigned width) { 402 VIXL_ASSERT(allow_macro_instructions_); 403 VIXL_ASSERT(!rd.IsZero()); 404 VIXL_ASSERT(!rn.IsZero()); 405 bfxil(rd, rn, lsb, width); 406 } 407 void Bind(Label* label) { 408 VIXL_ASSERT(allow_macro_instructions_); 409 bind(label); 410 } 411 void Bl(Label* label) { 412 VIXL_ASSERT(allow_macro_instructions_); 413 bl(label); 414 } 415 void Blr(const Register& xn) { 416 VIXL_ASSERT(allow_macro_instructions_); 417 VIXL_ASSERT(!xn.IsZero()); 418 blr(xn); 419 } 420 void Br(const Register& xn) { 421 VIXL_ASSERT(allow_macro_instructions_); 422 VIXL_ASSERT(!xn.IsZero()); 423 br(xn); 424 } 425 void Brk(int code = 0) { 426 VIXL_ASSERT(allow_macro_instructions_); 427 brk(code); 428 } 429 void Cbnz(const Register& rt, Label* label) { 430 VIXL_ASSERT(allow_macro_instructions_); 431 VIXL_ASSERT(!rt.IsZero()); 432 cbnz(rt, label); 433 } 434 void Cbz(const Register& rt, Label* label) { 435 VIXL_ASSERT(allow_macro_instructions_); 436 VIXL_ASSERT(!rt.IsZero()); 437 cbz(rt, label); 438 } 439 void Cinc(const Register& rd, const Register& rn, Condition cond) { 440 VIXL_ASSERT(allow_macro_instructions_); 441 VIXL_ASSERT(!rd.IsZero()); 442 VIXL_ASSERT(!rn.IsZero()); 443 cinc(rd, rn, cond); 444 } 445 void Cinv(const Register& rd, const Register& rn, Condition cond) { 446 VIXL_ASSERT(allow_macro_instructions_); 447 VIXL_ASSERT(!rd.IsZero()); 448 VIXL_ASSERT(!rn.IsZero()); 449 cinv(rd, rn, cond); 450 } 451 void Cls(const Register& rd, const Register& rn) { 452 VIXL_ASSERT(allow_macro_instructions_); 453 VIXL_ASSERT(!rd.IsZero()); 454 VIXL_ASSERT(!rn.IsZero()); 455 cls(rd, rn); 456 } 457 void Clz(const Register& rd, const Register& rn) { 458 VIXL_ASSERT(allow_macro_instructions_); 459 VIXL_ASSERT(!rd.IsZero()); 460 VIXL_ASSERT(!rn.IsZero()); 461 clz(rd, rn); 462 } 463 void Cneg(const Register& rd, const Register& rn, Condition cond) { 464 VIXL_ASSERT(allow_macro_instructions_); 465 VIXL_ASSERT(!rd.IsZero()); 466 VIXL_ASSERT(!rn.IsZero()); 467 cneg(rd, rn, cond); 468 } 469 void Cset(const Register& rd, Condition cond) { 470 VIXL_ASSERT(allow_macro_instructions_); 471 VIXL_ASSERT(!rd.IsZero()); 472 cset(rd, cond); 473 } 474 void Csetm(const Register& rd, Condition cond) { 475 VIXL_ASSERT(allow_macro_instructions_); 476 VIXL_ASSERT(!rd.IsZero()); 477 csetm(rd, cond); 478 } 479 void Csinc(const Register& rd, 480 const Register& rn, 481 const Register& rm, 482 Condition cond) { 483 VIXL_ASSERT(allow_macro_instructions_); 484 VIXL_ASSERT(!rd.IsZero()); 485 VIXL_ASSERT(!rn.IsZero()); 486 VIXL_ASSERT(!rm.IsZero()); 487 VIXL_ASSERT((cond != al) && (cond != nv)); 488 csinc(rd, rn, rm, cond); 489 } 490 void Csinv(const Register& rd, 491 const Register& rn, 492 const Register& rm, 493 Condition cond) { 494 VIXL_ASSERT(allow_macro_instructions_); 495 VIXL_ASSERT(!rd.IsZero()); 496 VIXL_ASSERT(!rn.IsZero()); 497 VIXL_ASSERT(!rm.IsZero()); 498 VIXL_ASSERT((cond != al) && (cond != nv)); 499 csinv(rd, rn, rm, cond); 500 } 501 void Csneg(const Register& rd, 502 const Register& rn, 503 const Register& rm, 504 Condition cond) { 505 VIXL_ASSERT(allow_macro_instructions_); 506 VIXL_ASSERT(!rd.IsZero()); 507 VIXL_ASSERT(!rn.IsZero()); 508 VIXL_ASSERT(!rm.IsZero()); 509 VIXL_ASSERT((cond != al) && (cond != nv)); 510 csneg(rd, rn, rm, cond); 511 } 512 void Dmb(BarrierDomain domain, BarrierType type) { 513 VIXL_ASSERT(allow_macro_instructions_); 514 dmb(domain, type); 515 } 516 void Dsb(BarrierDomain domain, BarrierType type) { 517 VIXL_ASSERT(allow_macro_instructions_); 518 dsb(domain, type); 519 } 520 void Extr(const Register& rd, 521 const Register& rn, 522 const Register& rm, 523 unsigned lsb) { 524 VIXL_ASSERT(allow_macro_instructions_); 525 VIXL_ASSERT(!rd.IsZero()); 526 VIXL_ASSERT(!rn.IsZero()); 527 VIXL_ASSERT(!rm.IsZero()); 528 extr(rd, rn, rm, lsb); 529 } 530 void Fabs(const FPRegister& fd, const FPRegister& fn) { 531 VIXL_ASSERT(allow_macro_instructions_); 532 fabs(fd, fn); 533 } 534 void Fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) { 535 VIXL_ASSERT(allow_macro_instructions_); 536 fadd(fd, fn, fm); 537 } 538 void Fccmp(const FPRegister& fn, 539 const FPRegister& fm, 540 StatusFlags nzcv, 541 Condition cond) { 542 VIXL_ASSERT(allow_macro_instructions_); 543 VIXL_ASSERT((cond != al) && (cond != nv)); 544 fccmp(fn, fm, nzcv, cond); 545 } 546 void Fcmp(const FPRegister& fn, const FPRegister& fm) { 547 VIXL_ASSERT(allow_macro_instructions_); 548 fcmp(fn, fm); 549 } 550 void Fcmp(const FPRegister& fn, double value); 551 void Fcsel(const FPRegister& fd, 552 const FPRegister& fn, 553 const FPRegister& fm, 554 Condition cond) { 555 VIXL_ASSERT(allow_macro_instructions_); 556 VIXL_ASSERT((cond != al) && (cond != nv)); 557 fcsel(fd, fn, fm, cond); 558 } 559 void Fcvt(const FPRegister& fd, const FPRegister& fn) { 560 VIXL_ASSERT(allow_macro_instructions_); 561 fcvt(fd, fn); 562 } 563 void Fcvtas(const Register& rd, const FPRegister& fn) { 564 VIXL_ASSERT(allow_macro_instructions_); 565 VIXL_ASSERT(!rd.IsZero()); 566 fcvtas(rd, fn); 567 } 568 void Fcvtau(const Register& rd, const FPRegister& fn) { 569 VIXL_ASSERT(allow_macro_instructions_); 570 VIXL_ASSERT(!rd.IsZero()); 571 fcvtau(rd, fn); 572 } 573 void Fcvtms(const Register& rd, const FPRegister& fn) { 574 VIXL_ASSERT(allow_macro_instructions_); 575 VIXL_ASSERT(!rd.IsZero()); 576 fcvtms(rd, fn); 577 } 578 void Fcvtmu(const Register& rd, const FPRegister& fn) { 579 VIXL_ASSERT(allow_macro_instructions_); 580 VIXL_ASSERT(!rd.IsZero()); 581 fcvtmu(rd, fn); 582 } 583 void Fcvtns(const Register& rd, const FPRegister& fn) { 584 VIXL_ASSERT(allow_macro_instructions_); 585 VIXL_ASSERT(!rd.IsZero()); 586 fcvtns(rd, fn); 587 } 588 void Fcvtnu(const Register& rd, const FPRegister& fn) { 589 VIXL_ASSERT(allow_macro_instructions_); 590 VIXL_ASSERT(!rd.IsZero()); 591 fcvtnu(rd, fn); 592 } 593 void Fcvtzs(const Register& rd, const FPRegister& fn) { 594 VIXL_ASSERT(allow_macro_instructions_); 595 VIXL_ASSERT(!rd.IsZero()); 596 fcvtzs(rd, fn); 597 } 598 void Fcvtzu(const Register& rd, const FPRegister& fn) { 599 VIXL_ASSERT(allow_macro_instructions_); 600 VIXL_ASSERT(!rd.IsZero()); 601 fcvtzu(rd, fn); 602 } 603 void Fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) { 604 VIXL_ASSERT(allow_macro_instructions_); 605 fdiv(fd, fn, fm); 606 } 607 void Fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) { 608 VIXL_ASSERT(allow_macro_instructions_); 609 fmax(fd, fn, fm); 610 } 611 void Fmaxnm(const FPRegister& fd, 612 const FPRegister& fn, 613 const FPRegister& fm) { 614 VIXL_ASSERT(allow_macro_instructions_); 615 fmaxnm(fd, fn, fm); 616 } 617 void Fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) { 618 VIXL_ASSERT(allow_macro_instructions_); 619 fmin(fd, fn, fm); 620 } 621 void Fminnm(const FPRegister& fd, 622 const FPRegister& fn, 623 const FPRegister& fm) { 624 VIXL_ASSERT(allow_macro_instructions_); 625 fminnm(fd, fn, fm); 626 } 627 void Fmov(FPRegister fd, FPRegister fn) { 628 VIXL_ASSERT(allow_macro_instructions_); 629 // Only emit an instruction if fd and fn are different, and they are both D 630 // registers. fmov(s0, s0) is not a no-op because it clears the top word of 631 // d0. Technically, fmov(d0, d0) is not a no-op either because it clears 632 // the top of q0, but FPRegister does not currently support Q registers. 633 if (!fd.Is(fn) || !fd.Is64Bits()) { 634 fmov(fd, fn); 635 } 636 } 637 void Fmov(FPRegister fd, Register rn) { 638 VIXL_ASSERT(allow_macro_instructions_); 639 VIXL_ASSERT(!rn.IsZero()); 640 fmov(fd, rn); 641 } 642 // Provide explicit double and float interfaces for FP immediate moves, rather 643 // than relying on implicit C++ casts. This allows signalling NaNs to be 644 // preserved when the immediate matches the format of fd. Most systems convert 645 // signalling NaNs to quiet NaNs when converting between float and double. 646 void Fmov(FPRegister fd, double imm); 647 void Fmov(FPRegister fd, float imm); 648 // Provide a template to allow other types to be converted automatically. 649 template<typename T> 650 void Fmov(FPRegister fd, T imm) { 651 VIXL_ASSERT(allow_macro_instructions_); 652 Fmov(fd, static_cast<double>(imm)); 653 } 654 void Fmov(Register rd, FPRegister fn) { 655 VIXL_ASSERT(allow_macro_instructions_); 656 VIXL_ASSERT(!rd.IsZero()); 657 fmov(rd, fn); 658 } 659 void Fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) { 660 VIXL_ASSERT(allow_macro_instructions_); 661 fmul(fd, fn, fm); 662 } 663 void Fmadd(const FPRegister& fd, 664 const FPRegister& fn, 665 const FPRegister& fm, 666 const FPRegister& fa) { 667 VIXL_ASSERT(allow_macro_instructions_); 668 fmadd(fd, fn, fm, fa); 669 } 670 void Fmsub(const FPRegister& fd, 671 const FPRegister& fn, 672 const FPRegister& fm, 673 const FPRegister& fa) { 674 VIXL_ASSERT(allow_macro_instructions_); 675 fmsub(fd, fn, fm, fa); 676 } 677 void Fnmadd(const FPRegister& fd, 678 const FPRegister& fn, 679 const FPRegister& fm, 680 const FPRegister& fa) { 681 VIXL_ASSERT(allow_macro_instructions_); 682 fnmadd(fd, fn, fm, fa); 683 } 684 void Fnmsub(const FPRegister& fd, 685 const FPRegister& fn, 686 const FPRegister& fm, 687 const FPRegister& fa) { 688 VIXL_ASSERT(allow_macro_instructions_); 689 fnmsub(fd, fn, fm, fa); 690 } 691 void Fneg(const FPRegister& fd, const FPRegister& fn) { 692 VIXL_ASSERT(allow_macro_instructions_); 693 fneg(fd, fn); 694 } 695 void Frinta(const FPRegister& fd, const FPRegister& fn) { 696 VIXL_ASSERT(allow_macro_instructions_); 697 frinta(fd, fn); 698 } 699 void Frintm(const FPRegister& fd, const FPRegister& fn) { 700 VIXL_ASSERT(allow_macro_instructions_); 701 frintm(fd, fn); 702 } 703 void Frintn(const FPRegister& fd, const FPRegister& fn) { 704 VIXL_ASSERT(allow_macro_instructions_); 705 frintn(fd, fn); 706 } 707 void Frintz(const FPRegister& fd, const FPRegister& fn) { 708 VIXL_ASSERT(allow_macro_instructions_); 709 frintz(fd, fn); 710 } 711 void Fsqrt(const FPRegister& fd, const FPRegister& fn) { 712 VIXL_ASSERT(allow_macro_instructions_); 713 fsqrt(fd, fn); 714 } 715 void Fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) { 716 VIXL_ASSERT(allow_macro_instructions_); 717 fsub(fd, fn, fm); 718 } 719 void Hint(SystemHint code) { 720 VIXL_ASSERT(allow_macro_instructions_); 721 hint(code); 722 } 723 void Hlt(int code) { 724 VIXL_ASSERT(allow_macro_instructions_); 725 hlt(code); 726 } 727 void Isb() { 728 VIXL_ASSERT(allow_macro_instructions_); 729 isb(); 730 } 731 void Ldnp(const CPURegister& rt, 732 const CPURegister& rt2, 733 const MemOperand& src) { 734 VIXL_ASSERT(allow_macro_instructions_); 735 ldnp(rt, rt2, src); 736 } 737 void Ldp(const CPURegister& rt, 738 const CPURegister& rt2, 739 const MemOperand& src) { 740 VIXL_ASSERT(allow_macro_instructions_); 741 ldp(rt, rt2, src); 742 } 743 void Ldpsw(const Register& rt, const Register& rt2, const MemOperand& src) { 744 VIXL_ASSERT(allow_macro_instructions_); 745 ldpsw(rt, rt2, src); 746 } 747 // Provide both double and float interfaces for FP immediate loads, rather 748 // than relying on implicit C++ casts. This allows signalling NaNs to be 749 // preserved when the immediate matches the format of fd. Most systems convert 750 // signalling NaNs to quiet NaNs when converting between float and double. 751 void Ldr(const FPRegister& ft, double imm) { 752 VIXL_ASSERT(allow_macro_instructions_); 753 if (ft.Is64Bits()) { 754 ldr(ft, imm); 755 } else { 756 ldr(ft, static_cast<float>(imm)); 757 } 758 } 759 void Ldr(const FPRegister& ft, float imm) { 760 VIXL_ASSERT(allow_macro_instructions_); 761 if (ft.Is32Bits()) { 762 ldr(ft, imm); 763 } else { 764 ldr(ft, static_cast<double>(imm)); 765 } 766 } 767 void Ldr(const Register& rt, uint64_t imm) { 768 VIXL_ASSERT(allow_macro_instructions_); 769 VIXL_ASSERT(!rt.IsZero()); 770 ldr(rt, imm); 771 } 772 void Lsl(const Register& rd, const Register& rn, unsigned shift) { 773 VIXL_ASSERT(allow_macro_instructions_); 774 VIXL_ASSERT(!rd.IsZero()); 775 VIXL_ASSERT(!rn.IsZero()); 776 lsl(rd, rn, shift); 777 } 778 void Lsl(const Register& rd, const Register& rn, const Register& rm) { 779 VIXL_ASSERT(allow_macro_instructions_); 780 VIXL_ASSERT(!rd.IsZero()); 781 VIXL_ASSERT(!rn.IsZero()); 782 VIXL_ASSERT(!rm.IsZero()); 783 lslv(rd, rn, rm); 784 } 785 void Lsr(const Register& rd, const Register& rn, unsigned shift) { 786 VIXL_ASSERT(allow_macro_instructions_); 787 VIXL_ASSERT(!rd.IsZero()); 788 VIXL_ASSERT(!rn.IsZero()); 789 lsr(rd, rn, shift); 790 } 791 void Lsr(const Register& rd, const Register& rn, const Register& rm) { 792 VIXL_ASSERT(allow_macro_instructions_); 793 VIXL_ASSERT(!rd.IsZero()); 794 VIXL_ASSERT(!rn.IsZero()); 795 VIXL_ASSERT(!rm.IsZero()); 796 lsrv(rd, rn, rm); 797 } 798 void Madd(const Register& rd, 799 const Register& rn, 800 const Register& rm, 801 const Register& ra) { 802 VIXL_ASSERT(allow_macro_instructions_); 803 VIXL_ASSERT(!rd.IsZero()); 804 VIXL_ASSERT(!rn.IsZero()); 805 VIXL_ASSERT(!rm.IsZero()); 806 VIXL_ASSERT(!ra.IsZero()); 807 madd(rd, rn, rm, ra); 808 } 809 void Mneg(const Register& rd, const Register& rn, const Register& rm) { 810 VIXL_ASSERT(allow_macro_instructions_); 811 VIXL_ASSERT(!rd.IsZero()); 812 VIXL_ASSERT(!rn.IsZero()); 813 VIXL_ASSERT(!rm.IsZero()); 814 mneg(rd, rn, rm); 815 } 816 void Mov(const Register& rd, const Register& rn) { 817 VIXL_ASSERT(allow_macro_instructions_); 818 mov(rd, rn); 819 } 820 void Movk(const Register& rd, uint64_t imm, int shift = -1) { 821 VIXL_ASSERT(allow_macro_instructions_); 822 VIXL_ASSERT(!rd.IsZero()); 823 movk(rd, imm, shift); 824 } 825 void Mrs(const Register& rt, SystemRegister sysreg) { 826 VIXL_ASSERT(allow_macro_instructions_); 827 VIXL_ASSERT(!rt.IsZero()); 828 mrs(rt, sysreg); 829 } 830 void Msr(SystemRegister sysreg, const Register& rt) { 831 VIXL_ASSERT(allow_macro_instructions_); 832 VIXL_ASSERT(!rt.IsZero()); 833 msr(sysreg, rt); 834 } 835 void Msub(const Register& rd, 836 const Register& rn, 837 const Register& rm, 838 const Register& ra) { 839 VIXL_ASSERT(allow_macro_instructions_); 840 VIXL_ASSERT(!rd.IsZero()); 841 VIXL_ASSERT(!rn.IsZero()); 842 VIXL_ASSERT(!rm.IsZero()); 843 VIXL_ASSERT(!ra.IsZero()); 844 msub(rd, rn, rm, ra); 845 } 846 void Mul(const Register& rd, const Register& rn, const Register& rm) { 847 VIXL_ASSERT(allow_macro_instructions_); 848 VIXL_ASSERT(!rd.IsZero()); 849 VIXL_ASSERT(!rn.IsZero()); 850 VIXL_ASSERT(!rm.IsZero()); 851 mul(rd, rn, rm); 852 } 853 void Nop() { 854 VIXL_ASSERT(allow_macro_instructions_); 855 nop(); 856 } 857 void Rbit(const Register& rd, const Register& rn) { 858 VIXL_ASSERT(allow_macro_instructions_); 859 VIXL_ASSERT(!rd.IsZero()); 860 VIXL_ASSERT(!rn.IsZero()); 861 rbit(rd, rn); 862 } 863 void Ret(const Register& xn = lr) { 864 VIXL_ASSERT(allow_macro_instructions_); 865 VIXL_ASSERT(!xn.IsZero()); 866 ret(xn); 867 } 868 void Rev(const Register& rd, const Register& rn) { 869 VIXL_ASSERT(allow_macro_instructions_); 870 VIXL_ASSERT(!rd.IsZero()); 871 VIXL_ASSERT(!rn.IsZero()); 872 rev(rd, rn); 873 } 874 void Rev16(const Register& rd, const Register& rn) { 875 VIXL_ASSERT(allow_macro_instructions_); 876 VIXL_ASSERT(!rd.IsZero()); 877 VIXL_ASSERT(!rn.IsZero()); 878 rev16(rd, rn); 879 } 880 void Rev32(const Register& rd, const Register& rn) { 881 VIXL_ASSERT(allow_macro_instructions_); 882 VIXL_ASSERT(!rd.IsZero()); 883 VIXL_ASSERT(!rn.IsZero()); 884 rev32(rd, rn); 885 } 886 void Ror(const Register& rd, const Register& rs, unsigned shift) { 887 VIXL_ASSERT(allow_macro_instructions_); 888 VIXL_ASSERT(!rd.IsZero()); 889 VIXL_ASSERT(!rs.IsZero()); 890 ror(rd, rs, shift); 891 } 892 void Ror(const Register& rd, const Register& rn, const Register& rm) { 893 VIXL_ASSERT(allow_macro_instructions_); 894 VIXL_ASSERT(!rd.IsZero()); 895 VIXL_ASSERT(!rn.IsZero()); 896 VIXL_ASSERT(!rm.IsZero()); 897 rorv(rd, rn, rm); 898 } 899 void Sbfiz(const Register& rd, 900 const Register& rn, 901 unsigned lsb, 902 unsigned width) { 903 VIXL_ASSERT(allow_macro_instructions_); 904 VIXL_ASSERT(!rd.IsZero()); 905 VIXL_ASSERT(!rn.IsZero()); 906 sbfiz(rd, rn, lsb, width); 907 } 908 void Sbfx(const Register& rd, 909 const Register& rn, 910 unsigned lsb, 911 unsigned width) { 912 VIXL_ASSERT(allow_macro_instructions_); 913 VIXL_ASSERT(!rd.IsZero()); 914 VIXL_ASSERT(!rn.IsZero()); 915 sbfx(rd, rn, lsb, width); 916 } 917 void Scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) { 918 VIXL_ASSERT(allow_macro_instructions_); 919 VIXL_ASSERT(!rn.IsZero()); 920 scvtf(fd, rn, fbits); 921 } 922 void Sdiv(const Register& rd, const Register& rn, const Register& rm) { 923 VIXL_ASSERT(allow_macro_instructions_); 924 VIXL_ASSERT(!rd.IsZero()); 925 VIXL_ASSERT(!rn.IsZero()); 926 VIXL_ASSERT(!rm.IsZero()); 927 sdiv(rd, rn, rm); 928 } 929 void Smaddl(const Register& rd, 930 const Register& rn, 931 const Register& rm, 932 const Register& ra) { 933 VIXL_ASSERT(allow_macro_instructions_); 934 VIXL_ASSERT(!rd.IsZero()); 935 VIXL_ASSERT(!rn.IsZero()); 936 VIXL_ASSERT(!rm.IsZero()); 937 VIXL_ASSERT(!ra.IsZero()); 938 smaddl(rd, rn, rm, ra); 939 } 940 void Smsubl(const Register& rd, 941 const Register& rn, 942 const Register& rm, 943 const Register& ra) { 944 VIXL_ASSERT(allow_macro_instructions_); 945 VIXL_ASSERT(!rd.IsZero()); 946 VIXL_ASSERT(!rn.IsZero()); 947 VIXL_ASSERT(!rm.IsZero()); 948 VIXL_ASSERT(!ra.IsZero()); 949 smsubl(rd, rn, rm, ra); 950 } 951 void Smull(const Register& rd, const Register& rn, const Register& rm) { 952 VIXL_ASSERT(allow_macro_instructions_); 953 VIXL_ASSERT(!rd.IsZero()); 954 VIXL_ASSERT(!rn.IsZero()); 955 VIXL_ASSERT(!rm.IsZero()); 956 smull(rd, rn, rm); 957 } 958 void Smulh(const Register& xd, const Register& xn, const Register& xm) { 959 VIXL_ASSERT(allow_macro_instructions_); 960 VIXL_ASSERT(!xd.IsZero()); 961 VIXL_ASSERT(!xn.IsZero()); 962 VIXL_ASSERT(!xm.IsZero()); 963 smulh(xd, xn, xm); 964 } 965 void Stnp(const CPURegister& rt, 966 const CPURegister& rt2, 967 const MemOperand& dst) { 968 VIXL_ASSERT(allow_macro_instructions_); 969 stnp(rt, rt2, dst); 970 } 971 void Stp(const CPURegister& rt, 972 const CPURegister& rt2, 973 const MemOperand& dst) { 974 VIXL_ASSERT(allow_macro_instructions_); 975 stp(rt, rt2, dst); 976 } 977 void Sxtb(const Register& rd, const Register& rn) { 978 VIXL_ASSERT(allow_macro_instructions_); 979 VIXL_ASSERT(!rd.IsZero()); 980 VIXL_ASSERT(!rn.IsZero()); 981 sxtb(rd, rn); 982 } 983 void Sxth(const Register& rd, const Register& rn) { 984 VIXL_ASSERT(allow_macro_instructions_); 985 VIXL_ASSERT(!rd.IsZero()); 986 VIXL_ASSERT(!rn.IsZero()); 987 sxth(rd, rn); 988 } 989 void Sxtw(const Register& rd, const Register& rn) { 990 VIXL_ASSERT(allow_macro_instructions_); 991 VIXL_ASSERT(!rd.IsZero()); 992 VIXL_ASSERT(!rn.IsZero()); 993 sxtw(rd, rn); 994 } 995 void Tbnz(const Register& rt, unsigned bit_pos, Label* label) { 996 VIXL_ASSERT(allow_macro_instructions_); 997 VIXL_ASSERT(!rt.IsZero()); 998 tbnz(rt, bit_pos, label); 999 } 1000 void Tbz(const Register& rt, unsigned bit_pos, Label* label) { 1001 VIXL_ASSERT(allow_macro_instructions_); 1002 VIXL_ASSERT(!rt.IsZero()); 1003 tbz(rt, bit_pos, label); 1004 } 1005 void Ubfiz(const Register& rd, 1006 const Register& rn, 1007 unsigned lsb, 1008 unsigned width) { 1009 VIXL_ASSERT(allow_macro_instructions_); 1010 VIXL_ASSERT(!rd.IsZero()); 1011 VIXL_ASSERT(!rn.IsZero()); 1012 ubfiz(rd, rn, lsb, width); 1013 } 1014 void Ubfx(const Register& rd, 1015 const Register& rn, 1016 unsigned lsb, 1017 unsigned width) { 1018 VIXL_ASSERT(allow_macro_instructions_); 1019 VIXL_ASSERT(!rd.IsZero()); 1020 VIXL_ASSERT(!rn.IsZero()); 1021 ubfx(rd, rn, lsb, width); 1022 } 1023 void Ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) { 1024 VIXL_ASSERT(allow_macro_instructions_); 1025 VIXL_ASSERT(!rn.IsZero()); 1026 ucvtf(fd, rn, fbits); 1027 } 1028 void Udiv(const Register& rd, const Register& rn, const Register& rm) { 1029 VIXL_ASSERT(allow_macro_instructions_); 1030 VIXL_ASSERT(!rd.IsZero()); 1031 VIXL_ASSERT(!rn.IsZero()); 1032 VIXL_ASSERT(!rm.IsZero()); 1033 udiv(rd, rn, rm); 1034 } 1035 void Umaddl(const Register& rd, 1036 const Register& rn, 1037 const Register& rm, 1038 const Register& ra) { 1039 VIXL_ASSERT(allow_macro_instructions_); 1040 VIXL_ASSERT(!rd.IsZero()); 1041 VIXL_ASSERT(!rn.IsZero()); 1042 VIXL_ASSERT(!rm.IsZero()); 1043 VIXL_ASSERT(!ra.IsZero()); 1044 umaddl(rd, rn, rm, ra); 1045 } 1046 void Umsubl(const Register& rd, 1047 const Register& rn, 1048 const Register& rm, 1049 const Register& ra) { 1050 VIXL_ASSERT(allow_macro_instructions_); 1051 VIXL_ASSERT(!rd.IsZero()); 1052 VIXL_ASSERT(!rn.IsZero()); 1053 VIXL_ASSERT(!rm.IsZero()); 1054 VIXL_ASSERT(!ra.IsZero()); 1055 umsubl(rd, rn, rm, ra); 1056 } 1057 void Unreachable() { 1058 VIXL_ASSERT(allow_macro_instructions_); 1059 #ifdef USE_SIMULATOR 1060 hlt(kUnreachableOpcode); 1061 #else 1062 // Branch to 0 to generate a segfault. 1063 // lr - kInstructionSize is the address of the offending instruction. 1064 blr(xzr); 1065 #endif 1066 } 1067 void Uxtb(const Register& rd, const Register& rn) { 1068 VIXL_ASSERT(allow_macro_instructions_); 1069 VIXL_ASSERT(!rd.IsZero()); 1070 VIXL_ASSERT(!rn.IsZero()); 1071 uxtb(rd, rn); 1072 } 1073 void Uxth(const Register& rd, const Register& rn) { 1074 VIXL_ASSERT(allow_macro_instructions_); 1075 VIXL_ASSERT(!rd.IsZero()); 1076 VIXL_ASSERT(!rn.IsZero()); 1077 uxth(rd, rn); 1078 } 1079 void Uxtw(const Register& rd, const Register& rn) { 1080 VIXL_ASSERT(allow_macro_instructions_); 1081 VIXL_ASSERT(!rd.IsZero()); 1082 VIXL_ASSERT(!rn.IsZero()); 1083 uxtw(rd, rn); 1084 } 1085 1086 // Push the system stack pointer (sp) down to allow the same to be done to 1087 // the current stack pointer (according to StackPointer()). This must be 1088 // called _before_ accessing the memory. 1089 // 1090 // This is necessary when pushing or otherwise adding things to the stack, to 1091 // satisfy the AAPCS64 constraint that the memory below the system stack 1092 // pointer is not accessed. 1093 // 1094 // This method asserts that StackPointer() is not sp, since the call does 1095 // not make sense in that context. 1096 // 1097 // TODO: This method can only accept values of 'space' that can be encoded in 1098 // one instruction. Refer to the implementation for details. 1099 void BumpSystemStackPointer(const Operand& space); 1100 1101 #if DEBUG 1102 void SetAllowMacroInstructions(bool value) { 1103 allow_macro_instructions_ = value; 1104 } 1105 1106 bool AllowMacroInstructions() const { 1107 return allow_macro_instructions_; 1108 } 1109 #endif 1110 1111 // Set the current stack pointer, but don't generate any code. 1112 void SetStackPointer(const Register& stack_pointer) { 1113 VIXL_ASSERT(!TmpList()->IncludesAliasOf(stack_pointer)); 1114 sp_ = stack_pointer; 1115 } 1116 1117 // Return the current stack pointer, as set by SetStackPointer. 1118 const Register& StackPointer() const { 1119 return sp_; 1120 } 1121 1122 CPURegList* TmpList() { return &tmp_list_; } 1123 CPURegList* FPTmpList() { return &fptmp_list_; } 1124 1125 // Like printf, but print at run-time from generated code. 1126 // 1127 // The caller must ensure that arguments for floating-point placeholders 1128 // (such as %e, %f or %g) are FPRegisters, and that arguments for integer 1129 // placeholders are Registers. 1130 // 1131 // At the moment it is only possible to print the value of sp if it is the 1132 // current stack pointer. Otherwise, the MacroAssembler will automatically 1133 // update sp on every push (using BumpSystemStackPointer), so determining its 1134 // value is difficult. 1135 // 1136 // Format placeholders that refer to more than one argument, or to a specific 1137 // argument, are not supported. This includes formats like "%1$d" or "%.*d". 1138 // 1139 // This function automatically preserves caller-saved registers so that 1140 // calling code can use Printf at any point without having to worry about 1141 // corruption. The preservation mechanism generates a lot of code. If this is 1142 // a problem, preserve the important registers manually and then call 1143 // PrintfNoPreserve. Callee-saved registers are not used by Printf, and are 1144 // implicitly preserved. 1145 void Printf(const char * format, 1146 CPURegister arg0 = NoCPUReg, 1147 CPURegister arg1 = NoCPUReg, 1148 CPURegister arg2 = NoCPUReg, 1149 CPURegister arg3 = NoCPUReg); 1150 1151 // Like Printf, but don't preserve any caller-saved registers, not even 'lr'. 1152 // 1153 // The return code from the system printf call will be returned in x0. 1154 void PrintfNoPreserve(const char * format, 1155 const CPURegister& arg0 = NoCPUReg, 1156 const CPURegister& arg1 = NoCPUReg, 1157 const CPURegister& arg2 = NoCPUReg, 1158 const CPURegister& arg3 = NoCPUReg); 1159 1160 // Trace control when running the debug simulator. 1161 // 1162 // For example: 1163 // 1164 // __ Trace(LOG_REGS, TRACE_ENABLE); 1165 // Will add registers to the trace if it wasn't already the case. 1166 // 1167 // __ Trace(LOG_DISASM, TRACE_DISABLE); 1168 // Will stop logging disassembly. It has no effect if the disassembly wasn't 1169 // already being logged. 1170 void Trace(TraceParameters parameters, TraceCommand command); 1171 1172 // Log the requested data independently of what is being traced. 1173 // 1174 // For example: 1175 // 1176 // __ Log(LOG_FLAGS) 1177 // Will output the flags. 1178 void Log(TraceParameters parameters); 1179 1180 // Enable or disable instrumentation when an Instrument visitor is attached to 1181 // the simulator. 1182 void EnableInstrumentation(); 1183 void DisableInstrumentation(); 1184 1185 // Add a marker to the instrumentation data produced by an Instrument visitor. 1186 // The name is a two character string that will be attached to the marker in 1187 // the output data. 1188 void AnnotateInstrumentation(const char* marker_name); 1189 1190 private: 1191 // The actual Push and Pop implementations. These don't generate any code 1192 // other than that required for the push or pop. This allows 1193 // (Push|Pop)CPURegList to bundle together setup code for a large block of 1194 // registers. 1195 // 1196 // Note that size is per register, and is specified in bytes. 1197 void PushHelper(int count, int size, 1198 const CPURegister& src0, const CPURegister& src1, 1199 const CPURegister& src2, const CPURegister& src3); 1200 void PopHelper(int count, int size, 1201 const CPURegister& dst0, const CPURegister& dst1, 1202 const CPURegister& dst2, const CPURegister& dst3); 1203 1204 // Perform necessary maintenance operations before a push or pop. 1205 // 1206 // Note that size is per register, and is specified in bytes. 1207 void PrepareForPush(int count, int size); 1208 void PrepareForPop(int count, int size); 1209 1210 #if DEBUG 1211 // Tell whether any of the macro instruction can be used. When false the 1212 // MacroAssembler will assert if a method which can emit a variable number 1213 // of instructions is called. 1214 bool allow_macro_instructions_; 1215 #endif 1216 1217 // The register to use as a stack pointer for stack operations. 1218 Register sp_; 1219 1220 // Scratch registers available for use by the MacroAssembler. 1221 CPURegList tmp_list_; 1222 CPURegList fptmp_list_; 1223 }; 1224 1225 1226 // Use this scope when you need a one-to-one mapping between methods and 1227 // instructions. This scope prevents the MacroAssembler from being called and 1228 // literal pools from being emitted. It also asserts the number of instructions 1229 // emitted is what you specified when creating the scope. 1230 class InstructionAccurateScope { 1231 public: 1232 explicit InstructionAccurateScope(MacroAssembler* masm) 1233 : masm_(masm) { 1234 masm_->BlockLiteralPool(); 1235 #ifdef DEBUG 1236 size_ = 0; 1237 old_allow_macro_instructions_ = masm_->AllowMacroInstructions(); 1238 masm_->SetAllowMacroInstructions(false); 1239 #endif 1240 } 1241 1242 InstructionAccurateScope(MacroAssembler* masm, int count) 1243 : masm_(masm) { 1244 USE(count); 1245 masm_->BlockLiteralPool(); 1246 #ifdef DEBUG 1247 size_ = count * kInstructionSize; 1248 masm_->bind(&start_); 1249 old_allow_macro_instructions_ = masm_->AllowMacroInstructions(); 1250 masm_->SetAllowMacroInstructions(false); 1251 #endif 1252 } 1253 1254 ~InstructionAccurateScope() { 1255 masm_->ReleaseLiteralPool(); 1256 #ifdef DEBUG 1257 if (start_.IsBound()) { 1258 VIXL_ASSERT(masm_->SizeOfCodeGeneratedSince(&start_) == size_); 1259 } 1260 masm_->SetAllowMacroInstructions(old_allow_macro_instructions_); 1261 #endif 1262 } 1263 1264 private: 1265 MacroAssembler* masm_; 1266 #ifdef DEBUG 1267 uint64_t size_; 1268 Label start_; 1269 bool old_allow_macro_instructions_; 1270 #endif 1271 }; 1272 1273 1274 // This scope utility allows scratch registers to be managed safely. The 1275 // MacroAssembler's TmpList() (and FPTmpList()) is used as a pool of scratch 1276 // registers. These registers can be allocated on demand, and will be returned 1277 // at the end of the scope. 1278 // 1279 // When the scope ends, the MacroAssembler's lists will be restored to their 1280 // original state, even if the lists were modified by some other means. 1281 class UseScratchRegisterScope { 1282 public: 1283 explicit UseScratchRegisterScope(MacroAssembler* masm) 1284 : available_(masm->TmpList()), 1285 availablefp_(masm->FPTmpList()), 1286 old_available_(available_->list()), 1287 old_availablefp_(availablefp_->list()) { 1288 VIXL_ASSERT(available_->type() == CPURegister::kRegister); 1289 VIXL_ASSERT(availablefp_->type() == CPURegister::kFPRegister); 1290 } 1291 1292 1293 ~UseScratchRegisterScope(); 1294 1295 1296 bool IsAvailable(const CPURegister& reg) const; 1297 1298 1299 // Take a register from the appropriate temps list. It will be returned 1300 // automatically when the scope ends. 1301 Register AcquireW() { return AcquireNextAvailable(available_).W(); } 1302 Register AcquireX() { return AcquireNextAvailable(available_).X(); } 1303 FPRegister AcquireS() { return AcquireNextAvailable(availablefp_).S(); } 1304 FPRegister AcquireD() { return AcquireNextAvailable(availablefp_).D(); } 1305 1306 1307 Register AcquireSameSizeAs(const Register& reg); 1308 FPRegister AcquireSameSizeAs(const FPRegister& reg); 1309 1310 1311 // Explicitly release an acquired (or excluded) register, putting it back in 1312 // the appropriate temps list. 1313 void Release(const CPURegister& reg); 1314 1315 1316 // Make the specified registers available as scratch registers for the 1317 // duration of this scope. 1318 void Include(const CPURegList& list); 1319 void Include(const Register& reg1, 1320 const Register& reg2 = NoReg, 1321 const Register& reg3 = NoReg, 1322 const Register& reg4 = NoReg); 1323 void Include(const FPRegister& reg1, 1324 const FPRegister& reg2 = NoFPReg, 1325 const FPRegister& reg3 = NoFPReg, 1326 const FPRegister& reg4 = NoFPReg); 1327 1328 1329 // Make sure that the specified registers are not available in this scope. 1330 // This can be used to prevent helper functions from using sensitive 1331 // registers, for example. 1332 void Exclude(const CPURegList& list); 1333 void Exclude(const Register& reg1, 1334 const Register& reg2 = NoReg, 1335 const Register& reg3 = NoReg, 1336 const Register& reg4 = NoReg); 1337 void Exclude(const FPRegister& reg1, 1338 const FPRegister& reg2 = NoFPReg, 1339 const FPRegister& reg3 = NoFPReg, 1340 const FPRegister& reg4 = NoFPReg); 1341 void Exclude(const CPURegister& reg1, 1342 const CPURegister& reg2 = NoCPUReg, 1343 const CPURegister& reg3 = NoCPUReg, 1344 const CPURegister& reg4 = NoCPUReg); 1345 1346 1347 // Prevent any scratch registers from being used in this scope. 1348 void ExcludeAll(); 1349 1350 1351 private: 1352 static CPURegister AcquireNextAvailable(CPURegList* available); 1353 1354 static void ReleaseByCode(CPURegList* available, int code); 1355 1356 static void ReleaseByRegList(CPURegList* available, 1357 RegList regs); 1358 1359 static void IncludeByRegList(CPURegList* available, 1360 RegList exclude); 1361 1362 static void ExcludeByRegList(CPURegList* available, 1363 RegList exclude); 1364 1365 // Available scratch registers. 1366 CPURegList* available_; // kRegister 1367 CPURegList* availablefp_; // kFPRegister 1368 1369 // The state of the available lists at the start of this scope. 1370 RegList old_available_; // kRegister 1371 RegList old_availablefp_; // kFPRegister 1372 }; 1373 1374 1375 } // namespace vixl 1376 1377 #endif // VIXL_A64_MACRO_ASSEMBLER_A64_H_ 1378