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_THUMB2_H_ 41#define V8_ARM_ASSEMBLER_THUMB2_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 // Unfortunately we can't make this private in a struct. 84 int code_; 85}; 86 87 88extern Register no_reg; 89extern Register r0; 90extern Register r1; 91extern Register r2; 92extern Register r3; 93extern Register r4; 94extern Register r5; 95extern Register r6; 96extern Register r7; 97extern Register r8; 98extern Register r9; 99extern Register r10; 100extern Register fp; 101extern Register ip; 102extern Register sp; 103extern Register lr; 104extern Register pc; 105 106 107// Single word VFP register. 108struct SwVfpRegister { 109 bool is_valid() const { return 0 <= code_ && code_ < 32; } 110 bool is(SwVfpRegister reg) const { return code_ == reg.code_; } 111 int code() const { 112 ASSERT(is_valid()); 113 return code_; 114 } 115 int bit() const { 116 ASSERT(is_valid()); 117 return 1 << code_; 118 } 119 120 int code_; 121}; 122 123 124// Double word VFP register. 125struct DwVfpRegister { 126 // Supporting d0 to d15, can be later extended to d31. 127 bool is_valid() const { return 0 <= code_ && code_ < 16; } 128 bool is(DwVfpRegister reg) const { return code_ == reg.code_; } 129 int code() const { 130 ASSERT(is_valid()); 131 return code_; 132 } 133 int bit() const { 134 ASSERT(is_valid()); 135 return 1 << code_; 136 } 137 138 int code_; 139}; 140 141 142// Support for VFP registers s0 to s31 (d0 to d15). 143// Note that "s(N):s(N+1)" is the same as "d(N/2)". 144extern SwVfpRegister s0; 145extern SwVfpRegister s1; 146extern SwVfpRegister s2; 147extern SwVfpRegister s3; 148extern SwVfpRegister s4; 149extern SwVfpRegister s5; 150extern SwVfpRegister s6; 151extern SwVfpRegister s7; 152extern SwVfpRegister s8; 153extern SwVfpRegister s9; 154extern SwVfpRegister s10; 155extern SwVfpRegister s11; 156extern SwVfpRegister s12; 157extern SwVfpRegister s13; 158extern SwVfpRegister s14; 159extern SwVfpRegister s15; 160extern SwVfpRegister s16; 161extern SwVfpRegister s17; 162extern SwVfpRegister s18; 163extern SwVfpRegister s19; 164extern SwVfpRegister s20; 165extern SwVfpRegister s21; 166extern SwVfpRegister s22; 167extern SwVfpRegister s23; 168extern SwVfpRegister s24; 169extern SwVfpRegister s25; 170extern SwVfpRegister s26; 171extern SwVfpRegister s27; 172extern SwVfpRegister s28; 173extern SwVfpRegister s29; 174extern SwVfpRegister s30; 175extern SwVfpRegister s31; 176 177extern DwVfpRegister d0; 178extern DwVfpRegister d1; 179extern DwVfpRegister d2; 180extern DwVfpRegister d3; 181extern DwVfpRegister d4; 182extern DwVfpRegister d5; 183extern DwVfpRegister d6; 184extern DwVfpRegister d7; 185extern DwVfpRegister d8; 186extern DwVfpRegister d9; 187extern DwVfpRegister d10; 188extern DwVfpRegister d11; 189extern DwVfpRegister d12; 190extern DwVfpRegister d13; 191extern DwVfpRegister d14; 192extern DwVfpRegister d15; 193 194 195// Coprocessor register 196struct CRegister { 197 bool is_valid() const { return 0 <= code_ && code_ < 16; } 198 bool is(CRegister creg) const { return code_ == creg.code_; } 199 int code() const { 200 ASSERT(is_valid()); 201 return code_; 202 } 203 int bit() const { 204 ASSERT(is_valid()); 205 return 1 << code_; 206 } 207 208 // Unfortunately we can't make this private in a struct. 209 int code_; 210}; 211 212 213extern CRegister no_creg; 214extern CRegister cr0; 215extern CRegister cr1; 216extern CRegister cr2; 217extern CRegister cr3; 218extern CRegister cr4; 219extern CRegister cr5; 220extern CRegister cr6; 221extern CRegister cr7; 222extern CRegister cr8; 223extern CRegister cr9; 224extern CRegister cr10; 225extern CRegister cr11; 226extern CRegister cr12; 227extern CRegister cr13; 228extern CRegister cr14; 229extern CRegister cr15; 230 231 232// Coprocessor number 233enum Coprocessor { 234 p0 = 0, 235 p1 = 1, 236 p2 = 2, 237 p3 = 3, 238 p4 = 4, 239 p5 = 5, 240 p6 = 6, 241 p7 = 7, 242 p8 = 8, 243 p9 = 9, 244 p10 = 10, 245 p11 = 11, 246 p12 = 12, 247 p13 = 13, 248 p14 = 14, 249 p15 = 15 250}; 251 252 253// Condition field in instructions. 254enum Condition { 255 eq = 0 << 28, // Z set equal. 256 ne = 1 << 28, // Z clear not equal. 257 nz = 1 << 28, // Z clear not zero. 258 cs = 2 << 28, // C set carry set. 259 hs = 2 << 28, // C set unsigned higher or same. 260 cc = 3 << 28, // C clear carry clear. 261 lo = 3 << 28, // C clear unsigned lower. 262 mi = 4 << 28, // N set negative. 263 pl = 5 << 28, // N clear positive or zero. 264 vs = 6 << 28, // V set overflow. 265 vc = 7 << 28, // V clear no overflow. 266 hi = 8 << 28, // C set, Z clear unsigned higher. 267 ls = 9 << 28, // C clear or Z set unsigned lower or same. 268 ge = 10 << 28, // N == V greater or equal. 269 lt = 11 << 28, // N != V less than. 270 gt = 12 << 28, // Z clear, N == V greater than. 271 le = 13 << 28, // Z set or N != V less then or equal 272 al = 14 << 28 // always. 273}; 274 275 276// Returns the equivalent of !cc. 277INLINE(Condition NegateCondition(Condition cc)); 278 279 280// Corresponds to transposing the operands of a comparison. 281inline Condition ReverseCondition(Condition cc) { 282 switch (cc) { 283 case lo: 284 return hi; 285 case hi: 286 return lo; 287 case hs: 288 return ls; 289 case ls: 290 return hs; 291 case lt: 292 return gt; 293 case gt: 294 return lt; 295 case ge: 296 return le; 297 case le: 298 return ge; 299 default: 300 return cc; 301 }; 302} 303 304 305// Branch hints are not used on the ARM. They are defined so that they can 306// appear in shared function signatures, but will be ignored in ARM 307// implementations. 308enum Hint { no_hint }; 309 310// Hints are not used on the arm. Negating is trivial. 311inline Hint NegateHint(Hint ignored) { return no_hint; } 312 313 314// ----------------------------------------------------------------------------- 315// Addressing modes and instruction variants 316 317// Shifter operand shift operation 318enum ShiftOp { 319 LSL = 0 << 5, 320 LSR = 1 << 5, 321 ASR = 2 << 5, 322 ROR = 3 << 5, 323 RRX = -1 324}; 325 326 327// Condition code updating mode 328enum SBit { 329 SetCC = 1 << 20, // set condition code 330 LeaveCC = 0 << 20 // leave condition code unchanged 331}; 332 333 334// Status register selection 335enum SRegister { 336 CPSR = 0 << 22, 337 SPSR = 1 << 22 338}; 339 340 341// Status register fields 342enum SRegisterField { 343 CPSR_c = CPSR | 1 << 16, 344 CPSR_x = CPSR | 1 << 17, 345 CPSR_s = CPSR | 1 << 18, 346 CPSR_f = CPSR | 1 << 19, 347 SPSR_c = SPSR | 1 << 16, 348 SPSR_x = SPSR | 1 << 17, 349 SPSR_s = SPSR | 1 << 18, 350 SPSR_f = SPSR | 1 << 19 351}; 352 353// Status register field mask (or'ed SRegisterField enum values) 354typedef uint32_t SRegisterFieldMask; 355 356 357// Memory operand addressing mode 358enum AddrMode { 359 // bit encoding P U W 360 Offset = (8|4|0) << 21, // offset (without writeback to base) 361 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback 362 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback 363 NegOffset = (8|0|0) << 21, // negative offset (without writeback to base) 364 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback 365 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback 366}; 367 368 369// Load/store multiple addressing mode 370enum BlockAddrMode { 371 // bit encoding P U W 372 da = (0|0|0) << 21, // decrement after 373 ia = (0|4|0) << 21, // increment after 374 db = (8|0|0) << 21, // decrement before 375 ib = (8|4|0) << 21, // increment before 376 da_w = (0|0|1) << 21, // decrement after with writeback to base 377 ia_w = (0|4|1) << 21, // increment after with writeback to base 378 db_w = (8|0|1) << 21, // decrement before with writeback to base 379 ib_w = (8|4|1) << 21 // increment before with writeback to base 380}; 381 382 383// Coprocessor load/store operand size 384enum LFlag { 385 Long = 1 << 22, // long load/store coprocessor 386 Short = 0 << 22 // short load/store coprocessor 387}; 388 389 390// ----------------------------------------------------------------------------- 391// Machine instruction Operands 392 393// Class Operand represents a shifter operand in data processing instructions 394class Operand BASE_EMBEDDED { 395 public: 396 // immediate 397 INLINE(explicit Operand(int32_t immediate, 398 RelocInfo::Mode rmode = RelocInfo::NONE)); 399 INLINE(explicit Operand(const ExternalReference& f)); 400 INLINE(explicit Operand(const char* s)); 401 explicit Operand(Handle<Object> handle); 402 INLINE(explicit Operand(Smi* value)); 403 404 // rm 405 INLINE(explicit Operand(Register rm)); 406 407 // rm <shift_op> shift_imm 408 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm); 409 410 // rm <shift_op> rs 411 explicit Operand(Register rm, ShiftOp shift_op, Register rs); 412 413 // Return true if this is a register operand. 414 INLINE(bool is_reg() const); 415 416 Register rm() const { return rm_; } 417 418 private: 419 Register rm_; 420 Register rs_; 421 ShiftOp shift_op_; 422 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 423 int32_t imm32_; // valid if rm_ == no_reg 424 RelocInfo::Mode rmode_; 425 426 friend class Assembler; 427}; 428 429 430// Class MemOperand represents a memory operand in load and store instructions 431class MemOperand BASE_EMBEDDED { 432 public: 433 // [rn +/- offset] Offset/NegOffset 434 // [rn +/- offset]! PreIndex/NegPreIndex 435 // [rn], +/- offset PostIndex/NegPostIndex 436 // offset is any signed 32-bit value; offset is first loaded to register ip if 437 // it does not fit the addressing mode (12-bit unsigned and sign bit) 438 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset); 439 440 // [rn +/- rm] Offset/NegOffset 441 // [rn +/- rm]! PreIndex/NegPreIndex 442 // [rn], +/- rm PostIndex/NegPostIndex 443 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset); 444 445 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset 446 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex 447 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex 448 explicit MemOperand(Register rn, Register rm, 449 ShiftOp shift_op, int shift_imm, AddrMode am = Offset); 450 451 private: 452 Register rn_; // base 453 Register rm_; // register offset 454 int32_t offset_; // valid if rm_ == no_reg 455 ShiftOp shift_op_; 456 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 457 AddrMode am_; // bits P, U, and W 458 459 friend class Assembler; 460}; 461 462// CpuFeatures keeps track of which features are supported by the target CPU. 463// Supported features must be enabled by a Scope before use. 464class CpuFeatures : public AllStatic { 465 public: 466 // Detect features of the target CPU. Set safe defaults if the serializer 467 // is enabled (snapshots must be portable). 468 static void Probe(); 469 470 // Check whether a feature is supported by the target CPU. 471 static bool IsSupported(CpuFeature f) { 472 if (f == VFP3 && !FLAG_enable_vfp3) return false; 473 return (supported_ & (1u << f)) != 0; 474 } 475 476 // Check whether a feature is currently enabled. 477 static bool IsEnabled(CpuFeature f) { 478 return (enabled_ & (1u << f)) != 0; 479 } 480 481 // Enable a specified feature within a scope. 482 class Scope BASE_EMBEDDED { 483#ifdef DEBUG 484 public: 485 explicit Scope(CpuFeature f) { 486 ASSERT(CpuFeatures::IsSupported(f)); 487 ASSERT(!Serializer::enabled() || 488 (found_by_runtime_probing_ & (1u << f)) == 0); 489 old_enabled_ = CpuFeatures::enabled_; 490 CpuFeatures::enabled_ |= 1u << f; 491 } 492 ~Scope() { CpuFeatures::enabled_ = old_enabled_; } 493 private: 494 unsigned old_enabled_; 495#else 496 public: 497 explicit Scope(CpuFeature f) {} 498#endif 499 }; 500 501 private: 502 static unsigned supported_; 503 static unsigned enabled_; 504 static unsigned found_by_runtime_probing_; 505}; 506 507 508typedef int32_t Instr; 509 510 511extern const Instr kMovLrPc; 512extern const Instr kLdrPCPattern; 513 514 515class Assembler : public Malloced { 516 public: 517 // Create an assembler. Instructions and relocation information are emitted 518 // into a buffer, with the instructions starting from the beginning and the 519 // relocation information starting from the end of the buffer. See CodeDesc 520 // for a detailed comment on the layout (globals.h). 521 // 522 // If the provided buffer is NULL, the assembler allocates and grows its own 523 // buffer, and buffer_size determines the initial buffer size. The buffer is 524 // owned by the assembler and deallocated upon destruction of the assembler. 525 // 526 // If the provided buffer is not NULL, the assembler uses the provided buffer 527 // for code generation and assumes its size to be buffer_size. If the buffer 528 // is too small, a fatal error occurs. No deallocation of the buffer is done 529 // upon destruction of the assembler. 530 Assembler(void* buffer, int buffer_size); 531 ~Assembler(); 532 533 // GetCode emits any pending (non-emitted) code and fills the descriptor 534 // desc. GetCode() is idempotent; it returns the same result if no other 535 // Assembler functions are invoked in between GetCode() calls. 536 void GetCode(CodeDesc* desc); 537 538 // Label operations & relative jumps (PPUM Appendix D) 539 // 540 // Takes a branch opcode (cc) and a label (L) and generates 541 // either a backward branch or a forward branch and links it 542 // to the label fixup chain. Usage: 543 // 544 // Label L; // unbound label 545 // j(cc, &L); // forward branch to unbound label 546 // bind(&L); // bind label to the current pc 547 // j(cc, &L); // backward branch to bound label 548 // bind(&L); // illegal: a label may be bound only once 549 // 550 // Note: The same Label can be used for forward and backward branches 551 // but it may be bound only once. 552 553 void bind(Label* L); // binds an unbound label L to the current code position 554 555 // Returns the branch offset to the given label from the current code position 556 // Links the label to the current position if it is still unbound 557 // Manages the jump elimination optimization if the second parameter is true. 558 int branch_offset(Label* L, bool jump_elimination_allowed); 559 560 // Puts a labels target address at the given position. 561 // The high 8 bits are set to zero. 562 void label_at_put(Label* L, int at_offset); 563 564 // Return the address in the constant pool of the code target address used by 565 // the branch/call instruction at pc. 566 INLINE(static Address target_address_address_at(Address pc)); 567 568 // Read/Modify the code target address in the branch/call instruction at pc. 569 INLINE(static Address target_address_at(Address pc)); 570 INLINE(static void set_target_address_at(Address pc, Address target)); 571 572 // This sets the branch destination (which is in the constant pool on ARM). 573 // This is for calls and branches within generated code. 574 inline static void set_target_at(Address constant_pool_entry, Address target); 575 576 // This sets the branch destination (which is in the constant pool on ARM). 577 // This is for calls and branches to runtime code. 578 inline static void set_external_target_at(Address constant_pool_entry, 579 Address target) { 580 set_target_at(constant_pool_entry, target); 581 } 582 583 // Here we are patching the address in the constant pool, not the actual call 584 // instruction. The address in the constant pool is the same size as a 585 // pointer. 586 static const int kCallTargetSize = kPointerSize; 587 static const int kExternalTargetSize = kPointerSize; 588 589 // Size of an instruction. 590 static const int kInstrSize = sizeof(Instr); 591 592 // Distance between the instruction referring to the address of the call 593 // target (ldr pc, [target addr in const pool]) and the return address 594 static const int kCallTargetAddressOffset = kInstrSize; 595 596 // Distance between start of patched return sequence and the emitted address 597 // to jump to. 598 static const int kPatchReturnSequenceAddressOffset = kInstrSize; 599 600 // Difference between address of current opcode and value read from pc 601 // register. 602 static const int kPcLoadDelta = 8; 603 604 static const int kJSReturnSequenceLength = 4; 605 606 // --------------------------------------------------------------------------- 607 // Code generation 608 609 // Insert the smallest number of nop instructions 610 // possible to align the pc offset to a multiple 611 // of m. m must be a power of 2 (>= 4). 612 void Align(int m); 613 614 // Branch instructions 615 void b(int branch_offset, Condition cond = al); 616 void bl(int branch_offset, Condition cond = al); 617 void blx(int branch_offset); // v5 and above 618 void blx(Register target, Condition cond = al); // v5 and above 619 void bx(Register target, Condition cond = al); // v5 and above, plus v4t 620 621 // Convenience branch instructions using labels 622 void b(Label* L, Condition cond = al) { 623 b(branch_offset(L, cond == al), cond); 624 } 625 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); } 626 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); } 627 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); } 628 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above 629 630 // Data-processing instructions 631 void ubfx(Register dst, Register src1, const Operand& src2, 632 const Operand& src3, Condition cond = al); 633 634 void and_(Register dst, Register src1, const Operand& src2, 635 SBit s = LeaveCC, Condition cond = al); 636 637 void eor(Register dst, Register src1, const Operand& src2, 638 SBit s = LeaveCC, Condition cond = al); 639 640 void sub(Register dst, Register src1, const Operand& src2, 641 SBit s = LeaveCC, Condition cond = al); 642 void sub(Register dst, Register src1, Register src2, 643 SBit s = LeaveCC, Condition cond = al) { 644 sub(dst, src1, Operand(src2), s, cond); 645 } 646 647 void rsb(Register dst, Register src1, const Operand& src2, 648 SBit s = LeaveCC, Condition cond = al); 649 650 void add(Register dst, Register src1, const Operand& src2, 651 SBit s = LeaveCC, Condition cond = al); 652 653 void adc(Register dst, Register src1, const Operand& src2, 654 SBit s = LeaveCC, Condition cond = al); 655 656 void sbc(Register dst, Register src1, const Operand& src2, 657 SBit s = LeaveCC, Condition cond = al); 658 659 void rsc(Register dst, Register src1, const Operand& src2, 660 SBit s = LeaveCC, Condition cond = al); 661 662 void tst(Register src1, const Operand& src2, Condition cond = al); 663 void tst(Register src1, Register src2, Condition cond = al) { 664 tst(src1, Operand(src2), cond); 665 } 666 667 void teq(Register src1, const Operand& src2, Condition cond = al); 668 669 void cmp(Register src1, const Operand& src2, Condition cond = al); 670 void cmp(Register src1, Register src2, Condition cond = al) { 671 cmp(src1, Operand(src2), cond); 672 } 673 674 void cmn(Register src1, const Operand& src2, Condition cond = al); 675 676 void orr(Register dst, Register src1, const Operand& src2, 677 SBit s = LeaveCC, Condition cond = al); 678 void orr(Register dst, Register src1, Register src2, 679 SBit s = LeaveCC, Condition cond = al) { 680 orr(dst, src1, Operand(src2), s, cond); 681 } 682 683 void mov(Register dst, const Operand& src, 684 SBit s = LeaveCC, Condition cond = al); 685 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) { 686 mov(dst, Operand(src), s, cond); 687 } 688 689 void bic(Register dst, Register src1, const Operand& src2, 690 SBit s = LeaveCC, Condition cond = al); 691 692 void mvn(Register dst, const Operand& src, 693 SBit s = LeaveCC, Condition cond = al); 694 695 // Multiply instructions 696 697 void mla(Register dst, Register src1, Register src2, Register srcA, 698 SBit s = LeaveCC, Condition cond = al); 699 700 void mul(Register dst, Register src1, Register src2, 701 SBit s = LeaveCC, Condition cond = al); 702 703 void smlal(Register dstL, Register dstH, Register src1, Register src2, 704 SBit s = LeaveCC, Condition cond = al); 705 706 void smull(Register dstL, Register dstH, Register src1, Register src2, 707 SBit s = LeaveCC, Condition cond = al); 708 709 void umlal(Register dstL, Register dstH, Register src1, Register src2, 710 SBit s = LeaveCC, Condition cond = al); 711 712 void umull(Register dstL, Register dstH, Register src1, Register src2, 713 SBit s = LeaveCC, Condition cond = al); 714 715 // Miscellaneous arithmetic instructions 716 717 void clz(Register dst, Register src, Condition cond = al); // v5 and above 718 719 // Status register access instructions 720 721 void mrs(Register dst, SRegister s, Condition cond = al); 722 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al); 723 724 // Load/Store instructions 725 void ldr(Register dst, const MemOperand& src, Condition cond = al); 726 void str(Register src, const MemOperand& dst, Condition cond = al); 727 void ldrb(Register dst, const MemOperand& src, Condition cond = al); 728 void strb(Register src, const MemOperand& dst, Condition cond = al); 729 void ldrh(Register dst, const MemOperand& src, Condition cond = al); 730 void strh(Register src, const MemOperand& dst, Condition cond = al); 731 void ldrsb(Register dst, const MemOperand& src, Condition cond = al); 732 void ldrsh(Register dst, const MemOperand& src, Condition cond = al); 733 734 // Load/Store multiple instructions 735 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al); 736 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al); 737 738 // Semaphore instructions 739 void swp(Register dst, Register src, Register base, Condition cond = al); 740 void swpb(Register dst, Register src, Register base, Condition cond = al); 741 742 // Exception-generating instructions and debugging support 743 void stop(const char* msg); 744 745 void bkpt(uint32_t imm16); // v5 and above 746 void swi(uint32_t imm24, Condition cond = al); 747 748 // Coprocessor instructions 749 750 void cdp(Coprocessor coproc, int opcode_1, 751 CRegister crd, CRegister crn, CRegister crm, 752 int opcode_2, Condition cond = al); 753 754 void cdp2(Coprocessor coproc, int opcode_1, 755 CRegister crd, CRegister crn, CRegister crm, 756 int opcode_2); // v5 and above 757 758 void mcr(Coprocessor coproc, int opcode_1, 759 Register rd, CRegister crn, CRegister crm, 760 int opcode_2 = 0, Condition cond = al); 761 762 void mcr2(Coprocessor coproc, int opcode_1, 763 Register rd, CRegister crn, CRegister crm, 764 int opcode_2 = 0); // v5 and above 765 766 void mrc(Coprocessor coproc, int opcode_1, 767 Register rd, CRegister crn, CRegister crm, 768 int opcode_2 = 0, Condition cond = al); 769 770 void mrc2(Coprocessor coproc, int opcode_1, 771 Register rd, CRegister crn, CRegister crm, 772 int opcode_2 = 0); // v5 and above 773 774 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src, 775 LFlag l = Short, Condition cond = al); 776 void ldc(Coprocessor coproc, CRegister crd, Register base, int option, 777 LFlag l = Short, Condition cond = al); 778 779 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src, 780 LFlag l = Short); // v5 and above 781 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option, 782 LFlag l = Short); // v5 and above 783 784 void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst, 785 LFlag l = Short, Condition cond = al); 786 void stc(Coprocessor coproc, CRegister crd, Register base, int option, 787 LFlag l = Short, Condition cond = al); 788 789 void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst, 790 LFlag l = Short); // v5 and above 791 void stc2(Coprocessor coproc, CRegister crd, Register base, int option, 792 LFlag l = Short); // v5 and above 793 794 // Support for VFP. 795 // All these APIs support S0 to S31 and D0 to D15. 796 // Currently these APIs do not support extended D registers, i.e, D16 to D31. 797 // However, some simple modifications can allow 798 // these APIs to support D16 to D31. 799 800 void vldr(const DwVfpRegister dst, 801 const Register base, 802 int offset, // Offset must be a multiple of 4. 803 const Condition cond = al); 804 void vstr(const DwVfpRegister src, 805 const Register base, 806 int offset, // Offset must be a multiple of 4. 807 const Condition cond = al); 808 void vmov(const DwVfpRegister dst, 809 const Register src1, 810 const Register src2, 811 const Condition cond = al); 812 void vmov(const Register dst1, 813 const Register dst2, 814 const DwVfpRegister src, 815 const Condition cond = al); 816 void vmov(const SwVfpRegister dst, 817 const Register src, 818 const Condition cond = al); 819 void vmov(const Register dst, 820 const SwVfpRegister src, 821 const Condition cond = al); 822 void vcvt(const DwVfpRegister dst, 823 const SwVfpRegister src, 824 const Condition cond = al); 825 void vcvt(const SwVfpRegister dst, 826 const DwVfpRegister src, 827 const Condition cond = al); 828 829 void vadd(const DwVfpRegister dst, 830 const DwVfpRegister src1, 831 const DwVfpRegister src2, 832 const Condition cond = al); 833 void vsub(const DwVfpRegister dst, 834 const DwVfpRegister src1, 835 const DwVfpRegister src2, 836 const Condition cond = al); 837 void vmul(const DwVfpRegister dst, 838 const DwVfpRegister src1, 839 const DwVfpRegister src2, 840 const Condition cond = al); 841 void vdiv(const DwVfpRegister dst, 842 const DwVfpRegister src1, 843 const DwVfpRegister src2, 844 const Condition cond = al); 845 void vcmp(const DwVfpRegister src1, 846 const DwVfpRegister src2, 847 const SBit s = LeaveCC, 848 const Condition cond = al); 849 void vmrs(const Register dst, 850 const Condition cond = al); 851 852 // Pseudo instructions 853 void nop() { mov(r0, Operand(r0)); } 854 855 void push(Register src, Condition cond = al) { 856 str(src, MemOperand(sp, 4, NegPreIndex), cond); 857 } 858 859 void pop(Register dst, Condition cond = al) { 860 ldr(dst, MemOperand(sp, 4, PostIndex), cond); 861 } 862 863 void pop() { 864 add(sp, sp, Operand(kPointerSize)); 865 } 866 867 // Load effective address of memory operand x into register dst 868 void lea(Register dst, const MemOperand& x, 869 SBit s = LeaveCC, Condition cond = al); 870 871 // Jump unconditionally to given label. 872 void jmp(Label* L) { b(L, al); } 873 874 // Check the code size generated from label to here. 875 int InstructionsGeneratedSince(Label* l) { 876 return (pc_offset() - l->pos()) / kInstrSize; 877 } 878 879 // Check whether an immediate fits an addressing mode 1 instruction. 880 bool ImmediateFitsAddrMode1Instruction(int32_t imm32); 881 882 // Postpone the generation of the constant pool for the specified number of 883 // instructions. 884 void BlockConstPoolFor(int instructions); 885 886 // Debugging 887 888 // Mark address of the ExitJSFrame code. 889 void RecordJSReturn(); 890 891 // Record a comment relocation entry that can be used by a disassembler. 892 // Use --debug_code to enable. 893 void RecordComment(const char* msg); 894 895 void RecordPosition(int pos); 896 void RecordStatementPosition(int pos); 897 void WriteRecordedPositions(); 898 899 int pc_offset() const { return pc_ - buffer_; } 900 int current_position() const { return current_position_; } 901 int current_statement_position() const { return current_position_; } 902 903 protected: 904 int buffer_space() const { return reloc_info_writer.pos() - pc_; } 905 906 // Read/patch instructions 907 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } 908 void instr_at_put(byte* pc, Instr instr) { 909 *reinterpret_cast<Instr*>(pc) = instr; 910 } 911 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } 912 void instr_at_put(int pos, Instr instr) { 913 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 914 } 915 916 // Decode branch instruction at pos and return branch target pos 917 int target_at(int pos); 918 919 // Patch branch instruction at pos to branch to given branch target pos 920 void target_at_put(int pos, int target_pos); 921 922 // Check if is time to emit a constant pool for pending reloc info entries 923 void CheckConstPool(bool force_emit, bool require_jump); 924 925 // Block the emission of the constant pool before pc_offset 926 void BlockConstPoolBefore(int pc_offset) { 927 if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset; 928 } 929 930 private: 931 // Code buffer: 932 // The buffer into which code and relocation info are generated. 933 byte* buffer_; 934 int buffer_size_; 935 // True if the assembler owns the buffer, false if buffer is external. 936 bool own_buffer_; 937 938 // Buffer size and constant pool distance are checked together at regular 939 // intervals of kBufferCheckInterval emitted bytes 940 static const int kBufferCheckInterval = 1*KB/2; 941 int next_buffer_check_; // pc offset of next buffer check 942 943 // Code generation 944 // The relocation writer's position is at least kGap bytes below the end of 945 // the generated instructions. This is so that multi-instruction sequences do 946 // not have to check for overflow. The same is true for writes of large 947 // relocation info entries. 948 static const int kGap = 32; 949 byte* pc_; // the program counter; moves forward 950 951 // Constant pool generation 952 // Pools are emitted in the instruction stream, preferably after unconditional 953 // jumps or after returns from functions (in dead code locations). 954 // If a long code sequence does not contain unconditional jumps, it is 955 // necessary to emit the constant pool before the pool gets too far from the 956 // location it is accessed from. In this case, we emit a jump over the emitted 957 // constant pool. 958 // Constants in the pool may be addresses of functions that gets relocated; 959 // if so, a relocation info entry is associated to the constant pool entry. 960 961 // Repeated checking whether the constant pool should be emitted is rather 962 // expensive. By default we only check again once a number of instructions 963 // has been generated. That also means that the sizing of the buffers is not 964 // an exact science, and that we rely on some slop to not overrun buffers. 965 static const int kCheckConstIntervalInst = 32; 966 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; 967 968 969 // Pools are emitted after function return and in dead code at (more or less) 970 // regular intervals of kDistBetweenPools bytes 971 static const int kDistBetweenPools = 1*KB; 972 973 // Constants in pools are accessed via pc relative addressing, which can 974 // reach +/-4KB thereby defining a maximum distance between the instruction 975 // and the accessed constant. We satisfy this constraint by limiting the 976 // distance between pools. 977 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval; 978 979 // Emission of the constant pool may be blocked in some code sequences 980 int no_const_pool_before_; // block emission before this pc offset 981 982 // Keep track of the last emitted pool to guarantee a maximal distance 983 int last_const_pool_end_; // pc offset following the last constant pool 984 985 // Relocation info generation 986 // Each relocation is encoded as a variable size value 987 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 988 RelocInfoWriter reloc_info_writer; 989 // Relocation info records are also used during code generation as temporary 990 // containers for constants and code target addresses until they are emitted 991 // to the constant pool. These pending relocation info records are temporarily 992 // stored in a separate buffer until a constant pool is emitted. 993 // If every instruction in a long sequence is accessing the pool, we need one 994 // pending relocation entry per instruction. 995 static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize; 996 RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info 997 int num_prinfo_; // number of pending reloc info entries in the buffer 998 999 // The bound position, before this we cannot do instruction elimination. 1000 int last_bound_pos_; 1001 1002 // source position information 1003 int current_position_; 1004 int current_statement_position_; 1005 int written_position_; 1006 int written_statement_position_; 1007 1008 // Code emission 1009 inline void CheckBuffer(); 1010 void GrowBuffer(); 1011 inline void emit(Instr x); 1012 1013 // Instruction generation 1014 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); 1015 void addrmod2(Instr instr, Register rd, const MemOperand& x); 1016 void addrmod3(Instr instr, Register rd, const MemOperand& x); 1017 void addrmod4(Instr instr, Register rn, RegList rl); 1018 void addrmod5(Instr instr, CRegister crd, const MemOperand& x); 1019 1020 // Labels 1021 void print(Label* L); 1022 void bind_to(Label* L, int pos); 1023 void link_to(Label* L, Label* appendix); 1024 void next(Label* L); 1025 1026 // Record reloc info for current pc_ 1027 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1028 1029 friend class RegExpMacroAssemblerARM; 1030 friend class RelocInfo; 1031 friend class CodePatcher; 1032}; 1033 1034} } // namespace v8::internal 1035 1036#endif // V8_ARM_ASSEMBLER_THUMB2_H_ 1037