assembler-arm.h revision 8defd9ff6930b4e24729971a61cf7469daf119be
1// Copyright (c) 1994-2006 Sun Microsystems Inc. 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 6// are met: 7// 8// - Redistributions of source code must retain the above copyright notice, 9// this list of conditions and the following disclaimer. 10// 11// - Redistribution in binary form must reproduce the above copyright 12// notice, this list of conditions and the following disclaimer in the 13// documentation and/or other materials provided with the 14// distribution. 15// 16// - Neither the name of Sun Microsystems or the names of contributors may 17// be used to endorse or promote products derived from this software without 18// specific prior written permission. 19// 20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31// OF THE POSSIBILITY OF SUCH DAMAGE. 32 33// The original source code covered by the above license above has been 34// modified significantly by Google Inc. 35// Copyright 2010 the V8 project authors. All rights reserved. 36 37// A light-weight ARM Assembler 38// Generates user mode instructions for the ARM architecture up to version 5 39 40#ifndef V8_ARM_ASSEMBLER_ARM_H_ 41#define V8_ARM_ASSEMBLER_ARM_H_ 42#include <stdio.h> 43#include "assembler.h" 44#include "serialize.h" 45 46namespace v8 { 47namespace internal { 48 49// CPU Registers. 50// 51// 1) We would prefer to use an enum, but enum values are assignment- 52// compatible with int, which has caused code-generation bugs. 53// 54// 2) We would prefer to use a class instead of a struct but we don't like 55// the register initialization to depend on the particular initialization 56// order (which appears to be different on OS X, Linux, and Windows for the 57// installed versions of C++ we tried). Using a struct permits C-style 58// "initialization". Also, the Register objects cannot be const as this 59// forces initialization stubs in MSVC, making us dependent on initialization 60// order. 61// 62// 3) By not using an enum, we are possibly preventing the compiler from 63// doing certain constant folds, which may significantly reduce the 64// code generated for some assembly instructions (because they boil down 65// to a few constants). If this is a problem, we could change the code 66// such that we use an enum in optimized mode, and the struct in debug 67// mode. This way we get the compile-time error checking in debug mode 68// and best performance in optimized code. 69// 70// Core register 71struct Register { 72 bool is_valid() const { return 0 <= code_ && code_ < 16; } 73 bool is(Register reg) const { return code_ == reg.code_; } 74 int code() const { 75 ASSERT(is_valid()); 76 return code_; 77 } 78 int bit() const { 79 ASSERT(is_valid()); 80 return 1 << code_; 81 } 82 83 void set_code(int code) { 84 code_ = code; 85 ASSERT(is_valid()); 86 } 87 88 // Unfortunately we can't make this private in a struct. 89 int code_; 90}; 91 92const Register no_reg = { -1 }; 93 94const Register r0 = { 0 }; 95const Register r1 = { 1 }; 96const Register r2 = { 2 }; 97const Register r3 = { 3 }; 98const Register r4 = { 4 }; 99const Register r5 = { 5 }; 100const Register r6 = { 6 }; 101const Register r7 = { 7 }; 102const Register r8 = { 8 }; // Used as context register. 103const Register r9 = { 9 }; 104const Register r10 = { 10 }; // Used as roots register. 105const Register fp = { 11 }; 106const Register ip = { 12 }; 107const Register sp = { 13 }; 108const Register lr = { 14 }; 109const Register pc = { 15 }; 110 111// Single word VFP register. 112struct SwVfpRegister { 113 bool is_valid() const { return 0 <= code_ && code_ < 32; } 114 bool is(SwVfpRegister reg) const { return code_ == reg.code_; } 115 int code() const { 116 ASSERT(is_valid()); 117 return code_; 118 } 119 int bit() const { 120 ASSERT(is_valid()); 121 return 1 << code_; 122 } 123 124 int code_; 125}; 126 127 128// Double word VFP register. 129struct DwVfpRegister { 130 // Supporting d0 to d15, can be later extended to d31. 131 bool is_valid() const { return 0 <= code_ && code_ < 16; } 132 bool is(DwVfpRegister reg) const { return code_ == reg.code_; } 133 int code() const { 134 ASSERT(is_valid()); 135 return code_; 136 } 137 int bit() const { 138 ASSERT(is_valid()); 139 return 1 << code_; 140 } 141 142 int code_; 143}; 144 145 146// Support for the VFP registers s0 to s31 (d0 to d15). 147// Note that "s(N):s(N+1)" is the same as "d(N/2)". 148const SwVfpRegister s0 = { 0 }; 149const SwVfpRegister s1 = { 1 }; 150const SwVfpRegister s2 = { 2 }; 151const SwVfpRegister s3 = { 3 }; 152const SwVfpRegister s4 = { 4 }; 153const SwVfpRegister s5 = { 5 }; 154const SwVfpRegister s6 = { 6 }; 155const SwVfpRegister s7 = { 7 }; 156const SwVfpRegister s8 = { 8 }; 157const SwVfpRegister s9 = { 9 }; 158const SwVfpRegister s10 = { 10 }; 159const SwVfpRegister s11 = { 11 }; 160const SwVfpRegister s12 = { 12 }; 161const SwVfpRegister s13 = { 13 }; 162const SwVfpRegister s14 = { 14 }; 163const SwVfpRegister s15 = { 15 }; 164const SwVfpRegister s16 = { 16 }; 165const SwVfpRegister s17 = { 17 }; 166const SwVfpRegister s18 = { 18 }; 167const SwVfpRegister s19 = { 19 }; 168const SwVfpRegister s20 = { 20 }; 169const SwVfpRegister s21 = { 21 }; 170const SwVfpRegister s22 = { 22 }; 171const SwVfpRegister s23 = { 23 }; 172const SwVfpRegister s24 = { 24 }; 173const SwVfpRegister s25 = { 25 }; 174const SwVfpRegister s26 = { 26 }; 175const SwVfpRegister s27 = { 27 }; 176const SwVfpRegister s28 = { 28 }; 177const SwVfpRegister s29 = { 29 }; 178const SwVfpRegister s30 = { 30 }; 179const SwVfpRegister s31 = { 31 }; 180 181const DwVfpRegister d0 = { 0 }; 182const DwVfpRegister d1 = { 1 }; 183const DwVfpRegister d2 = { 2 }; 184const DwVfpRegister d3 = { 3 }; 185const DwVfpRegister d4 = { 4 }; 186const DwVfpRegister d5 = { 5 }; 187const DwVfpRegister d6 = { 6 }; 188const DwVfpRegister d7 = { 7 }; 189const DwVfpRegister d8 = { 8 }; 190const DwVfpRegister d9 = { 9 }; 191const DwVfpRegister d10 = { 10 }; 192const DwVfpRegister d11 = { 11 }; 193const DwVfpRegister d12 = { 12 }; 194const DwVfpRegister d13 = { 13 }; 195const DwVfpRegister d14 = { 14 }; 196const DwVfpRegister d15 = { 15 }; 197 198 199// Coprocessor register 200struct CRegister { 201 bool is_valid() const { return 0 <= code_ && code_ < 16; } 202 bool is(CRegister creg) const { return code_ == creg.code_; } 203 int code() const { 204 ASSERT(is_valid()); 205 return code_; 206 } 207 int bit() const { 208 ASSERT(is_valid()); 209 return 1 << code_; 210 } 211 212 // Unfortunately we can't make this private in a struct. 213 int code_; 214}; 215 216 217const CRegister no_creg = { -1 }; 218 219const CRegister cr0 = { 0 }; 220const CRegister cr1 = { 1 }; 221const CRegister cr2 = { 2 }; 222const CRegister cr3 = { 3 }; 223const CRegister cr4 = { 4 }; 224const CRegister cr5 = { 5 }; 225const CRegister cr6 = { 6 }; 226const CRegister cr7 = { 7 }; 227const CRegister cr8 = { 8 }; 228const CRegister cr9 = { 9 }; 229const CRegister cr10 = { 10 }; 230const CRegister cr11 = { 11 }; 231const CRegister cr12 = { 12 }; 232const CRegister cr13 = { 13 }; 233const CRegister cr14 = { 14 }; 234const CRegister cr15 = { 15 }; 235 236 237// Coprocessor number 238enum Coprocessor { 239 p0 = 0, 240 p1 = 1, 241 p2 = 2, 242 p3 = 3, 243 p4 = 4, 244 p5 = 5, 245 p6 = 6, 246 p7 = 7, 247 p8 = 8, 248 p9 = 9, 249 p10 = 10, 250 p11 = 11, 251 p12 = 12, 252 p13 = 13, 253 p14 = 14, 254 p15 = 15 255}; 256 257 258// Condition field in instructions. 259enum Condition { 260 eq = 0 << 28, // Z set equal. 261 ne = 1 << 28, // Z clear not equal. 262 nz = 1 << 28, // Z clear not zero. 263 cs = 2 << 28, // C set carry set. 264 hs = 2 << 28, // C set unsigned higher or same. 265 cc = 3 << 28, // C clear carry clear. 266 lo = 3 << 28, // C clear unsigned lower. 267 mi = 4 << 28, // N set negative. 268 pl = 5 << 28, // N clear positive or zero. 269 vs = 6 << 28, // V set overflow. 270 vc = 7 << 28, // V clear no overflow. 271 hi = 8 << 28, // C set, Z clear unsigned higher. 272 ls = 9 << 28, // C clear or Z set unsigned lower or same. 273 ge = 10 << 28, // N == V greater or equal. 274 lt = 11 << 28, // N != V less than. 275 gt = 12 << 28, // Z clear, N == V greater than. 276 le = 13 << 28, // Z set or N != V less then or equal 277 al = 14 << 28 // always. 278}; 279 280 281// Returns the equivalent of !cc. 282inline Condition NegateCondition(Condition cc) { 283 ASSERT(cc != al); 284 return static_cast<Condition>(cc ^ ne); 285} 286 287 288// Corresponds to transposing the operands of a comparison. 289inline Condition ReverseCondition(Condition cc) { 290 switch (cc) { 291 case lo: 292 return hi; 293 case hi: 294 return lo; 295 case hs: 296 return ls; 297 case ls: 298 return hs; 299 case lt: 300 return gt; 301 case gt: 302 return lt; 303 case ge: 304 return le; 305 case le: 306 return ge; 307 default: 308 return cc; 309 }; 310} 311 312 313// Branch hints are not used on the ARM. They are defined so that they can 314// appear in shared function signatures, but will be ignored in ARM 315// implementations. 316enum Hint { no_hint }; 317 318// Hints are not used on the arm. Negating is trivial. 319inline Hint NegateHint(Hint ignored) { return no_hint; } 320 321 322// ----------------------------------------------------------------------------- 323// Addressing modes and instruction variants 324 325// Shifter operand shift operation 326enum ShiftOp { 327 LSL = 0 << 5, 328 LSR = 1 << 5, 329 ASR = 2 << 5, 330 ROR = 3 << 5, 331 RRX = -1 332}; 333 334 335// Condition code updating mode 336enum SBit { 337 SetCC = 1 << 20, // set condition code 338 LeaveCC = 0 << 20 // leave condition code unchanged 339}; 340 341 342// Status register selection 343enum SRegister { 344 CPSR = 0 << 22, 345 SPSR = 1 << 22 346}; 347 348 349// Status register fields 350enum SRegisterField { 351 CPSR_c = CPSR | 1 << 16, 352 CPSR_x = CPSR | 1 << 17, 353 CPSR_s = CPSR | 1 << 18, 354 CPSR_f = CPSR | 1 << 19, 355 SPSR_c = SPSR | 1 << 16, 356 SPSR_x = SPSR | 1 << 17, 357 SPSR_s = SPSR | 1 << 18, 358 SPSR_f = SPSR | 1 << 19 359}; 360 361// Status register field mask (or'ed SRegisterField enum values) 362typedef uint32_t SRegisterFieldMask; 363 364 365// Memory operand addressing mode 366enum AddrMode { 367 // bit encoding P U W 368 Offset = (8|4|0) << 21, // offset (without writeback to base) 369 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback 370 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback 371 NegOffset = (8|0|0) << 21, // negative offset (without writeback to base) 372 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback 373 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback 374}; 375 376 377// Load/store multiple addressing mode 378enum BlockAddrMode { 379 // bit encoding P U W 380 da = (0|0|0) << 21, // decrement after 381 ia = (0|4|0) << 21, // increment after 382 db = (8|0|0) << 21, // decrement before 383 ib = (8|4|0) << 21, // increment before 384 da_w = (0|0|1) << 21, // decrement after with writeback to base 385 ia_w = (0|4|1) << 21, // increment after with writeback to base 386 db_w = (8|0|1) << 21, // decrement before with writeback to base 387 ib_w = (8|4|1) << 21 // increment before with writeback to base 388}; 389 390 391// Coprocessor load/store operand size 392enum LFlag { 393 Long = 1 << 22, // long load/store coprocessor 394 Short = 0 << 22 // short load/store coprocessor 395}; 396 397 398// ----------------------------------------------------------------------------- 399// Machine instruction Operands 400 401// Class Operand represents a shifter operand in data processing instructions 402class Operand BASE_EMBEDDED { 403 public: 404 // immediate 405 INLINE(explicit Operand(int32_t immediate, 406 RelocInfo::Mode rmode = RelocInfo::NONE)); 407 INLINE(explicit Operand(const ExternalReference& f)); 408 INLINE(explicit Operand(const char* s)); 409 explicit Operand(Handle<Object> handle); 410 INLINE(explicit Operand(Smi* value)); 411 412 // rm 413 INLINE(explicit Operand(Register rm)); 414 415 // rm <shift_op> shift_imm 416 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm); 417 418 // rm <shift_op> rs 419 explicit Operand(Register rm, ShiftOp shift_op, Register rs); 420 421 // Return true if this is a register operand. 422 INLINE(bool is_reg() const); 423 424 // Return true of this operand fits in one instruction so that no 425 // 2-instruction solution with a load into the ip register is necessary. 426 bool is_single_instruction() const; 427 428 inline int32_t immediate() const { 429 ASSERT(!rm_.is_valid()); 430 return imm32_; 431 } 432 433 Register rm() const { return rm_; } 434 435 private: 436 Register rm_; 437 Register rs_; 438 ShiftOp shift_op_; 439 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 440 int32_t imm32_; // valid if rm_ == no_reg 441 RelocInfo::Mode rmode_; 442 443 friend class Assembler; 444}; 445 446 447// Class MemOperand represents a memory operand in load and store instructions 448class MemOperand BASE_EMBEDDED { 449 public: 450 // [rn +/- offset] Offset/NegOffset 451 // [rn +/- offset]! PreIndex/NegPreIndex 452 // [rn], +/- offset PostIndex/NegPostIndex 453 // offset is any signed 32-bit value; offset is first loaded to register ip if 454 // it does not fit the addressing mode (12-bit unsigned and sign bit) 455 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset); 456 457 // [rn +/- rm] Offset/NegOffset 458 // [rn +/- rm]! PreIndex/NegPreIndex 459 // [rn], +/- rm PostIndex/NegPostIndex 460 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset); 461 462 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset 463 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex 464 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex 465 explicit MemOperand(Register rn, Register rm, 466 ShiftOp shift_op, int shift_imm, AddrMode am = Offset); 467 468 void set_offset(int32_t offset) { 469 ASSERT(rm_.is(no_reg)); 470 offset_ = offset; 471 } 472 473 uint32_t offset() { 474 ASSERT(rm_.is(no_reg)); 475 return offset_; 476 } 477 478 Register rn() const { return rn_; } 479 Register rm() const { return rm_; } 480 481 private: 482 Register rn_; // base 483 Register rm_; // register offset 484 int32_t offset_; // valid if rm_ == no_reg 485 ShiftOp shift_op_; 486 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 487 AddrMode am_; // bits P, U, and W 488 489 friend class Assembler; 490}; 491 492// CpuFeatures keeps track of which features are supported by the target CPU. 493// Supported features must be enabled by a Scope before use. 494class CpuFeatures : public AllStatic { 495 public: 496 // Detect features of the target CPU. Set safe defaults if the serializer 497 // is enabled (snapshots must be portable). 498 static void Probe(); 499 500 // Check whether a feature is supported by the target CPU. 501 static bool IsSupported(CpuFeature f) { 502 if (f == VFP3 && !FLAG_enable_vfp3) return false; 503 return (supported_ & (1u << f)) != 0; 504 } 505 506 // Check whether a feature is currently enabled. 507 static bool IsEnabled(CpuFeature f) { 508 return (enabled_ & (1u << f)) != 0; 509 } 510 511 // Enable a specified feature within a scope. 512 class Scope BASE_EMBEDDED { 513#ifdef DEBUG 514 public: 515 explicit Scope(CpuFeature f) { 516 ASSERT(CpuFeatures::IsSupported(f)); 517 ASSERT(!Serializer::enabled() || 518 (found_by_runtime_probing_ & (1u << f)) == 0); 519 old_enabled_ = CpuFeatures::enabled_; 520 CpuFeatures::enabled_ |= 1u << f; 521 } 522 ~Scope() { CpuFeatures::enabled_ = old_enabled_; } 523 private: 524 unsigned old_enabled_; 525#else 526 public: 527 explicit Scope(CpuFeature f) {} 528#endif 529 }; 530 531 private: 532 static unsigned supported_; 533 static unsigned enabled_; 534 static unsigned found_by_runtime_probing_; 535}; 536 537 538typedef int32_t Instr; 539 540 541extern const Instr kMovLrPc; 542extern const Instr kLdrPCMask; 543extern const Instr kLdrPCPattern; 544extern const Instr kBlxRegMask; 545extern const Instr kBlxRegPattern; 546 547extern const Instr kMovMvnMask; 548extern const Instr kMovMvnPattern; 549extern const Instr kMovMvnFlip; 550 551extern const Instr kMovLeaveCCMask; 552extern const Instr kMovLeaveCCPattern; 553extern const Instr kMovwMask; 554extern const Instr kMovwPattern; 555extern const Instr kMovwLeaveCCFlip; 556 557extern const Instr kCmpCmnMask; 558extern const Instr kCmpCmnPattern; 559extern const Instr kCmpCmnFlip; 560 561extern const Instr kALUMask; 562extern const Instr kAddPattern; 563extern const Instr kSubPattern; 564extern const Instr kAndPattern; 565extern const Instr kBicPattern; 566extern const Instr kAddSubFlip; 567extern const Instr kAndBicFlip; 568 569class Assembler : public Malloced { 570 public: 571 // Create an assembler. Instructions and relocation information are emitted 572 // into a buffer, with the instructions starting from the beginning and the 573 // relocation information starting from the end of the buffer. See CodeDesc 574 // for a detailed comment on the layout (globals.h). 575 // 576 // If the provided buffer is NULL, the assembler allocates and grows its own 577 // buffer, and buffer_size determines the initial buffer size. The buffer is 578 // owned by the assembler and deallocated upon destruction of the assembler. 579 // 580 // If the provided buffer is not NULL, the assembler uses the provided buffer 581 // for code generation and assumes its size to be buffer_size. If the buffer 582 // is too small, a fatal error occurs. No deallocation of the buffer is done 583 // upon destruction of the assembler. 584 Assembler(void* buffer, int buffer_size); 585 ~Assembler(); 586 587 // GetCode emits any pending (non-emitted) code and fills the descriptor 588 // desc. GetCode() is idempotent; it returns the same result if no other 589 // Assembler functions are invoked in between GetCode() calls. 590 void GetCode(CodeDesc* desc); 591 592 // Label operations & relative jumps (PPUM Appendix D) 593 // 594 // Takes a branch opcode (cc) and a label (L) and generates 595 // either a backward branch or a forward branch and links it 596 // to the label fixup chain. Usage: 597 // 598 // Label L; // unbound label 599 // j(cc, &L); // forward branch to unbound label 600 // bind(&L); // bind label to the current pc 601 // j(cc, &L); // backward branch to bound label 602 // bind(&L); // illegal: a label may be bound only once 603 // 604 // Note: The same Label can be used for forward and backward branches 605 // but it may be bound only once. 606 607 void bind(Label* L); // binds an unbound label L to the current code position 608 609 // Returns the branch offset to the given label from the current code position 610 // Links the label to the current position if it is still unbound 611 // Manages the jump elimination optimization if the second parameter is true. 612 int branch_offset(Label* L, bool jump_elimination_allowed); 613 614 // Puts a labels target address at the given position. 615 // The high 8 bits are set to zero. 616 void label_at_put(Label* L, int at_offset); 617 618 // Return the address in the constant pool of the code target address used by 619 // the branch/call instruction at pc. 620 INLINE(static Address target_address_address_at(Address pc)); 621 622 // Read/Modify the code target address in the branch/call instruction at pc. 623 INLINE(static Address target_address_at(Address pc)); 624 INLINE(static void set_target_address_at(Address pc, Address target)); 625 626 // This sets the branch destination (which is in the constant pool on ARM). 627 // This is for calls and branches within generated code. 628 inline static void set_target_at(Address constant_pool_entry, Address target); 629 630 // This sets the branch destination (which is in the constant pool on ARM). 631 // This is for calls and branches to runtime code. 632 inline static void set_external_target_at(Address constant_pool_entry, 633 Address target) { 634 set_target_at(constant_pool_entry, target); 635 } 636 637 // Here we are patching the address in the constant pool, not the actual call 638 // instruction. The address in the constant pool is the same size as a 639 // pointer. 640 static const int kCallTargetSize = kPointerSize; 641 static const int kExternalTargetSize = kPointerSize; 642 643 // Size of an instruction. 644 static const int kInstrSize = sizeof(Instr); 645 646 // Distance between the instruction referring to the address of the call 647 // target and the return address. 648#ifdef USE_BLX 649 // Call sequence is: 650 // ldr ip, [pc, #...] @ call address 651 // blx ip 652 // @ return address 653 static const int kCallTargetAddressOffset = 2 * kInstrSize; 654#else 655 // Call sequence is: 656 // mov lr, pc 657 // ldr pc, [pc, #...] @ call address 658 // @ return address 659 static const int kCallTargetAddressOffset = kInstrSize; 660#endif 661 662 // Distance between start of patched return sequence and the emitted address 663 // to jump to. 664#ifdef USE_BLX 665 // Patched return sequence is: 666 // ldr ip, [pc, #0] @ emited address and start 667 // blx ip 668 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize; 669#else 670 // Patched return sequence is: 671 // mov lr, pc @ start of sequence 672 // ldr pc, [pc, #-4] @ emited address 673 static const int kPatchReturnSequenceAddressOffset = kInstrSize; 674#endif 675 676 // Distance between start of patched debug break slot and the emitted address 677 // to jump to. 678#ifdef USE_BLX 679 // Patched debug break slot code is: 680 // ldr ip, [pc, #0] @ emited address and start 681 // blx ip 682 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; 683#else 684 // Patched debug break slot code is: 685 // mov lr, pc @ start of sequence 686 // ldr pc, [pc, #-4] @ emited address 687 static const int kPatchDebugBreakSlotAddressOffset = kInstrSize; 688#endif 689 690 // Difference between address of current opcode and value read from pc 691 // register. 692 static const int kPcLoadDelta = 8; 693 694 static const int kJSReturnSequenceInstructions = 4; 695 static const int kDebugBreakSlotInstructions = 3; 696 static const int kDebugBreakSlotLength = 697 kDebugBreakSlotInstructions * kInstrSize; 698 699 // --------------------------------------------------------------------------- 700 // Code generation 701 702 // Insert the smallest number of nop instructions 703 // possible to align the pc offset to a multiple 704 // of m. m must be a power of 2 (>= 4). 705 void Align(int m); 706 // Aligns code to something that's optimal for a jump target for the platform. 707 void CodeTargetAlign(); 708 709 // Branch instructions 710 void b(int branch_offset, Condition cond = al); 711 void bl(int branch_offset, Condition cond = al); 712 void blx(int branch_offset); // v5 and above 713 void blx(Register target, Condition cond = al); // v5 and above 714 void bx(Register target, Condition cond = al); // v5 and above, plus v4t 715 716 // Convenience branch instructions using labels 717 void b(Label* L, Condition cond = al) { 718 b(branch_offset(L, cond == al), cond); 719 } 720 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); } 721 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); } 722 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); } 723 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above 724 725 // Data-processing instructions 726 727 void and_(Register dst, Register src1, const Operand& src2, 728 SBit s = LeaveCC, Condition cond = al); 729 730 void eor(Register dst, Register src1, const Operand& src2, 731 SBit s = LeaveCC, Condition cond = al); 732 733 void sub(Register dst, Register src1, const Operand& src2, 734 SBit s = LeaveCC, Condition cond = al); 735 void sub(Register dst, Register src1, Register src2, 736 SBit s = LeaveCC, Condition cond = al) { 737 sub(dst, src1, Operand(src2), s, cond); 738 } 739 740 void rsb(Register dst, Register src1, const Operand& src2, 741 SBit s = LeaveCC, Condition cond = al); 742 743 void add(Register dst, Register src1, const Operand& src2, 744 SBit s = LeaveCC, Condition cond = al); 745 void add(Register dst, Register src1, Register src2, 746 SBit s = LeaveCC, Condition cond = al) { 747 add(dst, src1, Operand(src2), s, cond); 748 } 749 750 void adc(Register dst, Register src1, const Operand& src2, 751 SBit s = LeaveCC, Condition cond = al); 752 753 void sbc(Register dst, Register src1, const Operand& src2, 754 SBit s = LeaveCC, Condition cond = al); 755 756 void rsc(Register dst, Register src1, const Operand& src2, 757 SBit s = LeaveCC, Condition cond = al); 758 759 void tst(Register src1, const Operand& src2, Condition cond = al); 760 void tst(Register src1, Register src2, Condition cond = al) { 761 tst(src1, Operand(src2), cond); 762 } 763 764 void teq(Register src1, const Operand& src2, Condition cond = al); 765 766 void cmp(Register src1, const Operand& src2, Condition cond = al); 767 void cmp(Register src1, Register src2, Condition cond = al) { 768 cmp(src1, Operand(src2), cond); 769 } 770 771 void cmn(Register src1, const Operand& src2, Condition cond = al); 772 773 void orr(Register dst, Register src1, const Operand& src2, 774 SBit s = LeaveCC, Condition cond = al); 775 void orr(Register dst, Register src1, Register src2, 776 SBit s = LeaveCC, Condition cond = al) { 777 orr(dst, src1, Operand(src2), s, cond); 778 } 779 780 void mov(Register dst, const Operand& src, 781 SBit s = LeaveCC, Condition cond = al); 782 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) { 783 mov(dst, Operand(src), s, cond); 784 } 785 786 // ARMv7 instructions for loading a 32 bit immediate in two instructions. 787 // This may actually emit a different mov instruction, but on an ARMv7 it 788 // is guaranteed to only emit one instruction. 789 void movw(Register reg, uint32_t immediate, Condition cond = al); 790 // The constant for movt should be in the range 0-0xffff. 791 void movt(Register reg, uint32_t immediate, Condition cond = al); 792 793 void bic(Register dst, Register src1, const Operand& src2, 794 SBit s = LeaveCC, Condition cond = al); 795 796 void mvn(Register dst, const Operand& src, 797 SBit s = LeaveCC, Condition cond = al); 798 799 // Multiply instructions 800 801 void mla(Register dst, Register src1, Register src2, Register srcA, 802 SBit s = LeaveCC, Condition cond = al); 803 804 void mul(Register dst, Register src1, Register src2, 805 SBit s = LeaveCC, Condition cond = al); 806 807 void smlal(Register dstL, Register dstH, Register src1, Register src2, 808 SBit s = LeaveCC, Condition cond = al); 809 810 void smull(Register dstL, Register dstH, Register src1, Register src2, 811 SBit s = LeaveCC, Condition cond = al); 812 813 void umlal(Register dstL, Register dstH, Register src1, Register src2, 814 SBit s = LeaveCC, Condition cond = al); 815 816 void umull(Register dstL, Register dstH, Register src1, Register src2, 817 SBit s = LeaveCC, Condition cond = al); 818 819 // Miscellaneous arithmetic instructions 820 821 void clz(Register dst, Register src, Condition cond = al); // v5 and above 822 823 // Bitfield manipulation instructions. v7 and above. 824 825 void ubfx(Register dst, Register src, int lsb, int width, 826 Condition cond = al); 827 828 void sbfx(Register dst, Register src, int lsb, int width, 829 Condition cond = al); 830 831 void bfc(Register dst, int lsb, int width, Condition cond = al); 832 833 void bfi(Register dst, Register src, int lsb, int width, 834 Condition cond = al); 835 836 // Status register access instructions 837 838 void mrs(Register dst, SRegister s, Condition cond = al); 839 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al); 840 841 // Load/Store instructions 842 void ldr(Register dst, const MemOperand& src, Condition cond = al); 843 void str(Register src, const MemOperand& dst, Condition cond = al); 844 void ldrb(Register dst, const MemOperand& src, Condition cond = al); 845 void strb(Register src, const MemOperand& dst, Condition cond = al); 846 void ldrh(Register dst, const MemOperand& src, Condition cond = al); 847 void strh(Register src, const MemOperand& dst, Condition cond = al); 848 void ldrsb(Register dst, const MemOperand& src, Condition cond = al); 849 void ldrsh(Register dst, const MemOperand& src, Condition cond = al); 850 void ldrd(Register dst1, 851 Register dst2, 852 const MemOperand& src, Condition cond = al); 853 void strd(Register src1, 854 Register src2, 855 const MemOperand& dst, Condition cond = al); 856 857 // Load/Store multiple instructions 858 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al); 859 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al); 860 861 // Exception-generating instructions and debugging support 862 void stop(const char* msg); 863 864 void bkpt(uint32_t imm16); // v5 and above 865 void swi(uint32_t imm24, Condition cond = al); 866 867 // Coprocessor instructions 868 869 void cdp(Coprocessor coproc, int opcode_1, 870 CRegister crd, CRegister crn, CRegister crm, 871 int opcode_2, Condition cond = al); 872 873 void cdp2(Coprocessor coproc, int opcode_1, 874 CRegister crd, CRegister crn, CRegister crm, 875 int opcode_2); // v5 and above 876 877 void mcr(Coprocessor coproc, int opcode_1, 878 Register rd, CRegister crn, CRegister crm, 879 int opcode_2 = 0, Condition cond = al); 880 881 void mcr2(Coprocessor coproc, int opcode_1, 882 Register rd, CRegister crn, CRegister crm, 883 int opcode_2 = 0); // v5 and above 884 885 void mrc(Coprocessor coproc, int opcode_1, 886 Register rd, CRegister crn, CRegister crm, 887 int opcode_2 = 0, Condition cond = al); 888 889 void mrc2(Coprocessor coproc, int opcode_1, 890 Register rd, CRegister crn, CRegister crm, 891 int opcode_2 = 0); // v5 and above 892 893 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src, 894 LFlag l = Short, Condition cond = al); 895 void ldc(Coprocessor coproc, CRegister crd, Register base, int option, 896 LFlag l = Short, Condition cond = al); 897 898 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src, 899 LFlag l = Short); // v5 and above 900 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option, 901 LFlag l = Short); // v5 and above 902 903 void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst, 904 LFlag l = Short, Condition cond = al); 905 void stc(Coprocessor coproc, CRegister crd, Register base, int option, 906 LFlag l = Short, Condition cond = al); 907 908 void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst, 909 LFlag l = Short); // v5 and above 910 void stc2(Coprocessor coproc, CRegister crd, Register base, int option, 911 LFlag l = Short); // v5 and above 912 913 // Support for VFP. 914 // All these APIs support S0 to S31 and D0 to D15. 915 // Currently these APIs do not support extended D registers, i.e, D16 to D31. 916 // However, some simple modifications can allow 917 // these APIs to support D16 to D31. 918 919 void vldr(const DwVfpRegister dst, 920 const Register base, 921 int offset, // Offset must be a multiple of 4. 922 const Condition cond = al); 923 924 void vldr(const SwVfpRegister dst, 925 const Register base, 926 int offset, // Offset must be a multiple of 4. 927 const Condition cond = al); 928 929 void vstr(const DwVfpRegister src, 930 const Register base, 931 int offset, // Offset must be a multiple of 4. 932 const Condition cond = al); 933 934 void vmov(const DwVfpRegister dst, 935 const DwVfpRegister src, 936 const Condition cond = al); 937 void vmov(const DwVfpRegister dst, 938 const Register src1, 939 const Register src2, 940 const Condition cond = al); 941 void vmov(const Register dst1, 942 const Register dst2, 943 const DwVfpRegister src, 944 const Condition cond = al); 945 void vmov(const SwVfpRegister dst, 946 const Register src, 947 const Condition cond = al); 948 void vmov(const Register dst, 949 const SwVfpRegister src, 950 const Condition cond = al); 951 void vcvt_f64_s32(const DwVfpRegister dst, 952 const SwVfpRegister src, 953 const Condition cond = al); 954 void vcvt_f32_s32(const SwVfpRegister dst, 955 const SwVfpRegister src, 956 const Condition cond = al); 957 void vcvt_f64_u32(const DwVfpRegister dst, 958 const SwVfpRegister src, 959 const Condition cond = al); 960 void vcvt_s32_f64(const SwVfpRegister dst, 961 const DwVfpRegister src, 962 const Condition cond = al); 963 void vcvt_u32_f64(const SwVfpRegister dst, 964 const DwVfpRegister src, 965 const Condition cond = al); 966 void vcvt_f64_f32(const DwVfpRegister dst, 967 const SwVfpRegister src, 968 const Condition cond = al); 969 void vcvt_f32_f64(const SwVfpRegister dst, 970 const DwVfpRegister src, 971 const Condition cond = al); 972 973 void vadd(const DwVfpRegister dst, 974 const DwVfpRegister src1, 975 const DwVfpRegister src2, 976 const Condition cond = al); 977 void vsub(const DwVfpRegister dst, 978 const DwVfpRegister src1, 979 const DwVfpRegister src2, 980 const Condition cond = al); 981 void vmul(const DwVfpRegister dst, 982 const DwVfpRegister src1, 983 const DwVfpRegister src2, 984 const Condition cond = al); 985 void vdiv(const DwVfpRegister dst, 986 const DwVfpRegister src1, 987 const DwVfpRegister src2, 988 const Condition cond = al); 989 void vcmp(const DwVfpRegister src1, 990 const DwVfpRegister src2, 991 const SBit s = LeaveCC, 992 const Condition cond = al); 993 void vmrs(const Register dst, 994 const Condition cond = al); 995 void vsqrt(const DwVfpRegister dst, 996 const DwVfpRegister src, 997 const Condition cond = al); 998 999 // Pseudo instructions 1000 void nop(int type = 0); 1001 1002 void push(Register src, Condition cond = al) { 1003 str(src, MemOperand(sp, 4, NegPreIndex), cond); 1004 } 1005 1006 void pop(Register dst, Condition cond = al) { 1007 ldr(dst, MemOperand(sp, 4, PostIndex), cond); 1008 } 1009 1010 void pop() { 1011 add(sp, sp, Operand(kPointerSize)); 1012 } 1013 1014 // Jump unconditionally to given label. 1015 void jmp(Label* L) { b(L, al); } 1016 1017 // Check the code size generated from label to here. 1018 int InstructionsGeneratedSince(Label* l) { 1019 return (pc_offset() - l->pos()) / kInstrSize; 1020 } 1021 1022 // Check whether an immediate fits an addressing mode 1 instruction. 1023 bool ImmediateFitsAddrMode1Instruction(int32_t imm32); 1024 1025 // Class for scoping postponing the constant pool generation. 1026 class BlockConstPoolScope { 1027 public: 1028 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) { 1029 assem_->StartBlockConstPool(); 1030 } 1031 ~BlockConstPoolScope() { 1032 assem_->EndBlockConstPool(); 1033 } 1034 1035 private: 1036 Assembler* assem_; 1037 1038 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope); 1039 }; 1040 1041 // Postpone the generation of the constant pool for the specified number of 1042 // instructions. 1043 void BlockConstPoolFor(int instructions); 1044 1045 // Debugging 1046 1047 // Mark address of the ExitJSFrame code. 1048 void RecordJSReturn(); 1049 1050 // Mark address of a debug break slot. 1051 void RecordDebugBreakSlot(); 1052 1053 // Record a comment relocation entry that can be used by a disassembler. 1054 // Use --debug_code to enable. 1055 void RecordComment(const char* msg); 1056 1057 void RecordPosition(int pos); 1058 void RecordStatementPosition(int pos); 1059 bool WriteRecordedPositions(); 1060 1061 int pc_offset() const { return pc_ - buffer_; } 1062 int current_position() const { return current_position_; } 1063 int current_statement_position() const { return current_statement_position_; } 1064 1065 bool can_peephole_optimize(int instructions) { 1066 if (!FLAG_peephole_optimization) return false; 1067 if (last_bound_pos_ > pc_offset() - instructions * kInstrSize) return false; 1068 return reloc_info_writer.last_pc() <= pc_ - instructions * kInstrSize; 1069 } 1070 1071 // Read/patch instructions 1072 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } 1073 static void instr_at_put(byte* pc, Instr instr) { 1074 *reinterpret_cast<Instr*>(pc) = instr; 1075 } 1076 static bool IsNop(Instr instr, int type = 0); 1077 static bool IsBranch(Instr instr); 1078 static int GetBranchOffset(Instr instr); 1079 static bool IsLdrRegisterImmediate(Instr instr); 1080 static int GetLdrRegisterImmediateOffset(Instr instr); 1081 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset); 1082 static Register GetRd(Instr instr); 1083 static bool IsPush(Instr instr); 1084 static bool IsPop(Instr instr); 1085 static bool IsStrRegFpOffset(Instr instr); 1086 static bool IsLdrRegFpOffset(Instr instr); 1087 static bool IsStrRegFpNegOffset(Instr instr); 1088 static bool IsLdrRegFpNegOffset(Instr instr); 1089 1090 1091 protected: 1092 int buffer_space() const { return reloc_info_writer.pos() - pc_; } 1093 1094 // Read/patch instructions 1095 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } 1096 void instr_at_put(int pos, Instr instr) { 1097 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 1098 } 1099 1100 // Decode branch instruction at pos and return branch target pos 1101 int target_at(int pos); 1102 1103 // Patch branch instruction at pos to branch to given branch target pos 1104 void target_at_put(int pos, int target_pos); 1105 1106 // Check if is time to emit a constant pool for pending reloc info entries 1107 void CheckConstPool(bool force_emit, bool require_jump); 1108 1109 // Block the emission of the constant pool before pc_offset 1110 void BlockConstPoolBefore(int pc_offset) { 1111 if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset; 1112 } 1113 1114 void StartBlockConstPool() { 1115 const_pool_blocked_nesting_++; 1116 } 1117 void EndBlockConstPool() { 1118 const_pool_blocked_nesting_--; 1119 } 1120 bool is_const_pool_blocked() const { return const_pool_blocked_nesting_ > 0; } 1121 1122 private: 1123 // Code buffer: 1124 // The buffer into which code and relocation info are generated. 1125 byte* buffer_; 1126 int buffer_size_; 1127 // True if the assembler owns the buffer, false if buffer is external. 1128 bool own_buffer_; 1129 1130 // Buffer size and constant pool distance are checked together at regular 1131 // intervals of kBufferCheckInterval emitted bytes 1132 static const int kBufferCheckInterval = 1*KB/2; 1133 int next_buffer_check_; // pc offset of next buffer check 1134 1135 // Code generation 1136 // The relocation writer's position is at least kGap bytes below the end of 1137 // the generated instructions. This is so that multi-instruction sequences do 1138 // not have to check for overflow. The same is true for writes of large 1139 // relocation info entries. 1140 static const int kGap = 32; 1141 byte* pc_; // the program counter; moves forward 1142 1143 // Constant pool generation 1144 // Pools are emitted in the instruction stream, preferably after unconditional 1145 // jumps or after returns from functions (in dead code locations). 1146 // If a long code sequence does not contain unconditional jumps, it is 1147 // necessary to emit the constant pool before the pool gets too far from the 1148 // location it is accessed from. In this case, we emit a jump over the emitted 1149 // constant pool. 1150 // Constants in the pool may be addresses of functions that gets relocated; 1151 // if so, a relocation info entry is associated to the constant pool entry. 1152 1153 // Repeated checking whether the constant pool should be emitted is rather 1154 // expensive. By default we only check again once a number of instructions 1155 // has been generated. That also means that the sizing of the buffers is not 1156 // an exact science, and that we rely on some slop to not overrun buffers. 1157 static const int kCheckConstIntervalInst = 32; 1158 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; 1159 1160 1161 // Pools are emitted after function return and in dead code at (more or less) 1162 // regular intervals of kDistBetweenPools bytes 1163 static const int kDistBetweenPools = 1*KB; 1164 1165 // Constants in pools are accessed via pc relative addressing, which can 1166 // reach +/-4KB thereby defining a maximum distance between the instruction 1167 // and the accessed constant. We satisfy this constraint by limiting the 1168 // distance between pools. 1169 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval; 1170 1171 // Emission of the constant pool may be blocked in some code sequences. 1172 int const_pool_blocked_nesting_; // Block emission if this is not zero. 1173 int no_const_pool_before_; // Block emission before this pc offset. 1174 1175 // Keep track of the last emitted pool to guarantee a maximal distance 1176 int last_const_pool_end_; // pc offset following the last constant pool 1177 1178 // Relocation info generation 1179 // Each relocation is encoded as a variable size value 1180 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 1181 RelocInfoWriter reloc_info_writer; 1182 // Relocation info records are also used during code generation as temporary 1183 // containers for constants and code target addresses until they are emitted 1184 // to the constant pool. These pending relocation info records are temporarily 1185 // stored in a separate buffer until a constant pool is emitted. 1186 // If every instruction in a long sequence is accessing the pool, we need one 1187 // pending relocation entry per instruction. 1188 static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize; 1189 RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info 1190 int num_prinfo_; // number of pending reloc info entries in the buffer 1191 1192 // The bound position, before this we cannot do instruction elimination. 1193 int last_bound_pos_; 1194 1195 // source position information 1196 int current_position_; 1197 int current_statement_position_; 1198 int written_position_; 1199 int written_statement_position_; 1200 1201 // Code emission 1202 inline void CheckBuffer(); 1203 void GrowBuffer(); 1204 inline void emit(Instr x); 1205 1206 // Instruction generation 1207 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); 1208 void addrmod2(Instr instr, Register rd, const MemOperand& x); 1209 void addrmod3(Instr instr, Register rd, const MemOperand& x); 1210 void addrmod4(Instr instr, Register rn, RegList rl); 1211 void addrmod5(Instr instr, CRegister crd, const MemOperand& x); 1212 1213 // Labels 1214 void print(Label* L); 1215 void bind_to(Label* L, int pos); 1216 void link_to(Label* L, Label* appendix); 1217 void next(Label* L); 1218 1219 // Record reloc info for current pc_ 1220 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1221 1222 friend class RegExpMacroAssemblerARM; 1223 friend class RelocInfo; 1224 friend class CodePatcher; 1225 friend class BlockConstPoolScope; 1226}; 1227 1228} } // namespace v8::internal 1229 1230#endif // V8_ARM_ASSEMBLER_ARM_H_ 1231