| OLD | NEW |
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| 24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | 24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| 29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
| 31 // OF THE POSSIBILITY OF SUCH DAMAGE. | 31 // OF THE POSSIBILITY OF SUCH DAMAGE. |
| 32 | 32 |
| 33 // The original source code covered by the above license above has been modified | 33 // The original source code covered by the above license has been modified |
| 34 // significantly by Google Inc. | 34 // significantly by Google Inc. |
| 35 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 35 // Copyright 2010 the V8 project authors. All rights reserved. |
| 36 | 36 |
| 37 // A light-weight ARM Assembler | 37 // A light-weight ARM Assembler |
| 38 // Generates user mode instructions for the ARM architecture up to version 5 | 38 // Generates user mode instructions for the ARM architecture up to version 5 |
| 39 | 39 |
| 40 #ifndef V8_ARM_ASSEMBLER_THUMB2_H_ | 40 #ifndef V8_ARM_ASSEMBLER_THUMB2_H_ |
| 41 #define V8_ARM_ASSEMBLER_THUMB2_H_ | 41 #define V8_ARM_ASSEMBLER_THUMB2_H_ |
| 42 #include <stdio.h> | 42 #include <stdio.h> |
| 43 #include "assembler.h" | 43 #include "assembler.h" |
| 44 #include "serialize.h" | 44 #include "serialize.h" |
| 45 | 45 |
| 46 namespace v8 { | 46 namespace v8 { |
| 47 namespace internal { | 47 namespace internal { |
| 48 | 48 |
| 49 // The beginning of this file contains some enum declarations that are |
| 50 // redundant with declarations in constants-arm.h, but in a different namespace |
| 51 // Please keep the order and values consistent, so we can merge the files |
| 52 // later easily. |
| 53 |
| 54 // Opcodes for Data-processing instructions (instructions with a type 0 and 1) |
| 55 // as defined in section A3.4 |
| 56 enum Opcode { |
| 57 no_operand = -1, |
| 58 AND = 0, // Logical AND |
| 59 EOR = 1, // Logical Exclusive OR |
| 60 SUB = 2, // Subtract |
| 61 RSB = 3, // Reverse Subtract |
| 62 ADD = 4, // Add |
| 63 ADC = 5, // Add with Carry |
| 64 SBC = 6, // Subtract with Carry |
| 65 RSC = 7, // Reverse Subtract with Carry |
| 66 TST = 8, // Test |
| 67 TEQ = 9, // Test Equivalence |
| 68 CMP = 10, // Compare |
| 69 CMN = 11, // Compare Negated |
| 70 ORR = 12, // Logical (inclusive) OR |
| 71 MOV = 13, // Move |
| 72 BIC = 14, // Bit Clear |
| 73 MVN = 15, // Move Not |
| 74 max_operand = 16 |
| 75 }; |
| 76 |
| 77 enum BitPositions { |
| 78 B0 = 1 << 0, |
| 79 B1 = 1 << 1, |
| 80 B2 = 1 << 2, |
| 81 B3 = 1 << 3, |
| 82 B4 = 1 << 4, |
| 83 B5 = 1 << 5, |
| 84 B6 = 1 << 6, |
| 85 B7 = 1 << 7, |
| 86 B8 = 1 << 8, |
| 87 B9 = 1 << 9, |
| 88 B10 = 1 << 10, |
| 89 B11 = 1 << 11, |
| 90 B12 = 1 << 12, |
| 91 B16 = 1 << 16, |
| 92 B18 = 1 << 18, |
| 93 B19 = 1 << 19, |
| 94 B20 = 1 << 20, |
| 95 B21 = 1 << 21, |
| 96 B22 = 1 << 22, |
| 97 B23 = 1 << 23, |
| 98 B24 = 1 << 24, |
| 99 B25 = 1 << 25, |
| 100 B26 = 1 << 26, |
| 101 B27 = 1 << 27 |
| 102 }; |
| 103 |
| 104 enum Bits1 { |
| 105 b0 = 0x0, |
| 106 b1 = 0x1 |
| 107 }; |
| 108 |
| 109 enum Bits2 { |
| 110 b00 = 0x0, |
| 111 b01 = 0x1, |
| 112 b10 = 0x2, |
| 113 b11 = 0x3 |
| 114 }; |
| 115 |
| 116 enum Bits3 { |
| 117 b000 = 0x0, |
| 118 b001 = 0x1, |
| 119 b010 = 0x2, |
| 120 b011 = 0x3, |
| 121 b100 = 0x4, |
| 122 b101 = 0x5, |
| 123 b110 = 0x6, |
| 124 b111 = 0x7 |
| 125 }; |
| 126 |
| 127 enum Bits4 { |
| 128 b0000 = 0x0, |
| 129 b0001 = 0x1, |
| 130 b0010 = 0x2, |
| 131 b0011 = 0x3, |
| 132 b0100 = 0x4, |
| 133 b0101 = 0x5, |
| 134 b0110 = 0x6, |
| 135 b0111 = 0x7, |
| 136 b1000 = 0x8, |
| 137 b1001 = 0x9, |
| 138 b1010 = 0xa, |
| 139 b1011 = 0xb, |
| 140 b1100 = 0xc, |
| 141 b1101 = 0xd, |
| 142 b1110 = 0xe, |
| 143 b1111 = 0xf |
| 144 }; |
| 145 |
| 146 enum Bits5 { |
| 147 b00000 = 0x00, |
| 148 b00001 = 0x01, |
| 149 b00010 = 0x02, |
| 150 b00011 = 0x03, |
| 151 b00100 = 0x04, |
| 152 b00101 = 0x05, |
| 153 b00110 = 0x06, |
| 154 b00111 = 0x07, |
| 155 b01000 = 0x08, |
| 156 b01001 = 0x09, |
| 157 b01010 = 0x0a, |
| 158 b01011 = 0x0b, |
| 159 b01100 = 0x0c, |
| 160 b01101 = 0x0d, |
| 161 b01110 = 0x0e, |
| 162 b01111 = 0x0f, |
| 163 b10000 = 0x10, |
| 164 b10001 = 0x11, |
| 165 b10010 = 0x12, |
| 166 b10011 = 0x13, |
| 167 b10100 = 0x14, |
| 168 b10101 = 0x15, |
| 169 b10110 = 0x16, |
| 170 b10111 = 0x17, |
| 171 b11000 = 0x18, |
| 172 b11001 = 0x19, |
| 173 b11010 = 0x1a, |
| 174 b11011 = 0x1b, |
| 175 b11100 = 0x1c, |
| 176 b11101 = 0x1d, |
| 177 b11110 = 0x1e, |
| 178 b11111 = 0x1f |
| 179 }; |
| 180 |
| 49 // CPU Registers. | 181 // CPU Registers. |
| 50 // | 182 // |
| 51 // 1) We would prefer to use an enum, but enum values are assignment- | 183 // 1) We would prefer to use an enum, but enum values are assignment- |
| 52 // compatible with int, which has caused code-generation bugs. | 184 // compatible with int, which has caused code-generation bugs. |
| 53 // | 185 // |
| 54 // 2) We would prefer to use a class instead of a struct but we don't like | 186 // 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 | 187 // the register initialization to depend on the particular initialization |
| 56 // order (which appears to be different on OS X, Linux, and Windows for the | 188 // 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 | 189 // installed versions of C++ we tried). Using a struct permits C-style |
| 58 // "initialization". Also, the Register objects cannot be const as this | 190 // "initialization". Also, the Register objects cannot be const as this |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 p9 = 9, | 375 p9 = 9, |
| 244 p10 = 10, | 376 p10 = 10, |
| 245 p11 = 11, | 377 p11 = 11, |
| 246 p12 = 12, | 378 p12 = 12, |
| 247 p13 = 13, | 379 p13 = 13, |
| 248 p14 = 14, | 380 p14 = 14, |
| 249 p15 = 15 | 381 p15 = 15 |
| 250 }; | 382 }; |
| 251 | 383 |
| 252 | 384 |
| 253 // Condition field in instructions | 385 // Condition field in instructions. |
| 254 enum Condition { | 386 enum Condition { |
| 255 eq = 0 << 28, // Z set equal. | 387 eq = 0 << 28, // Z set equal. |
| 256 ne = 1 << 28, // Z clear not equal. | 388 ne = 1 << 28, // Z clear not equal. |
| 257 nz = 1 << 28, // Z clear not zero. | 389 nz = 1 << 28, // Z clear not zero. |
| 258 cs = 2 << 28, // C set carry set. | 390 cs = 2 << 28, // C set carry set. |
| 259 hs = 2 << 28, // C set unsigned higher or same. | 391 hs = 2 << 28, // C set unsigned higher or same. |
| 260 cc = 3 << 28, // C clear carry clear. | 392 cc = 3 << 28, // C clear carry clear. |
| 261 lo = 3 << 28, // C clear unsigned lower. | 393 lo = 3 << 28, // C clear unsigned lower. |
| 262 mi = 4 << 28, // N set negative. | 394 mi = 4 << 28, // N set negative. |
| 263 pl = 5 << 28, // N clear positive or zero. | 395 pl = 5 << 28, // N clear positive or zero. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 | 441 |
| 310 // Hints are not used on the arm. Negating is trivial. | 442 // Hints are not used on the arm. Negating is trivial. |
| 311 inline Hint NegateHint(Hint ignored) { return no_hint; } | 443 inline Hint NegateHint(Hint ignored) { return no_hint; } |
| 312 | 444 |
| 313 | 445 |
| 314 // ----------------------------------------------------------------------------- | 446 // ----------------------------------------------------------------------------- |
| 315 // Addressing modes and instruction variants | 447 // Addressing modes and instruction variants |
| 316 | 448 |
| 317 // Shifter operand shift operation | 449 // Shifter operand shift operation |
| 318 enum ShiftOp { | 450 enum ShiftOp { |
| 319 LSL = 0 << 5, | 451 LSL = 0, |
| 320 LSR = 1 << 5, | 452 LSR = 1, |
| 321 ASR = 2 << 5, | 453 ASR = 2, |
| 322 ROR = 3 << 5, | 454 ROR = 3, |
| 323 RRX = -1 | 455 RRX = -1 |
| 324 }; | 456 }; |
| 325 | 457 |
| 326 | 458 |
| 327 // Condition code updating mode | 459 // Condition code updating mode |
| 328 enum SBit { | 460 enum SBit { |
| 329 SetCC = 1 << 20, // set condition code | 461 SetCC = 1 << 20, // set condition code |
| 330 LeaveCC = 0 << 20 // leave condition code unchanged | 462 LeaveCC = 0 << 20 // leave condition code unchanged |
| 331 }; | 463 }; |
| 332 | 464 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 explicit Scope(CpuFeature f) {} | 631 explicit Scope(CpuFeature f) {} |
| 500 #endif | 632 #endif |
| 501 }; | 633 }; |
| 502 | 634 |
| 503 private: | 635 private: |
| 504 static unsigned supported_; | 636 static unsigned supported_; |
| 505 static unsigned enabled_; | 637 static unsigned enabled_; |
| 506 static unsigned found_by_runtime_probing_; | 638 static unsigned found_by_runtime_probing_; |
| 507 }; | 639 }; |
| 508 | 640 |
| 641 typedef int32_t InstrArm; |
| 642 typedef int16_t InstrThumb; |
| 509 | 643 |
| 510 typedef int32_t Instr; | 644 // hack to keep the code patcher happy for now |
| 645 typedef InstrArm Instr; |
| 511 | 646 |
| 512 | 647 extern const InstrArm kMovLrPc; |
| 513 extern const Instr kMovLrPc; | 648 extern const InstrArm kLdrPCPattern; |
| 514 extern const Instr kLdrPCPattern; | |
| 515 | 649 |
| 516 | 650 |
| 517 class Assembler : public Malloced { | 651 class Assembler : public Malloced { |
| 518 public: | 652 public: |
| 519 // Create an assembler. Instructions and relocation information are emitted | 653 // Create an assembler. Instructions and relocation information are emitted |
| 520 // into a buffer, with the instructions starting from the beginning and the | 654 // into a buffer, with the instructions starting from the beginning and the |
| 521 // relocation information starting from the end of the buffer. See CodeDesc | 655 // relocation information starting from the end of the buffer. See CodeDesc |
| 522 // for a detailed comment on the layout (globals.h). | 656 // for a detailed comment on the layout (globals.h). |
| 523 // | 657 // |
| 524 // If the provided buffer is NULL, the assembler allocates and grows its own | 658 // If the provided buffer is NULL, the assembler allocates and grows its own |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 set_target_at(constant_pool_entry, target); | 716 set_target_at(constant_pool_entry, target); |
| 583 } | 717 } |
| 584 | 718 |
| 585 // Here we are patching the address in the constant pool, not the actual call | 719 // Here we are patching the address in the constant pool, not the actual call |
| 586 // instruction. The address in the constant pool is the same size as a | 720 // instruction. The address in the constant pool is the same size as a |
| 587 // pointer. | 721 // pointer. |
| 588 static const int kCallTargetSize = kPointerSize; | 722 static const int kCallTargetSize = kPointerSize; |
| 589 static const int kExternalTargetSize = kPointerSize; | 723 static const int kExternalTargetSize = kPointerSize; |
| 590 | 724 |
| 591 // Size of an instruction. | 725 // Size of an instruction. |
| 726 static const int kInstrArmSize = sizeof(InstrArm); |
| 727 static const int kInstrThumbSize = sizeof(InstrThumb); |
| 728 // Keep the code generator happy for now. |
| 592 static const int kInstrSize = sizeof(Instr); | 729 static const int kInstrSize = sizeof(Instr); |
| 593 | 730 |
| 731 |
| 594 // Distance between the instruction referring to the address of the call | 732 // Distance between the instruction referring to the address of the call |
| 595 // target (ldr pc, [target addr in const pool]) and the return address | 733 // target (ldr pc, [target addr in const pool]) and the return address |
| 596 static const int kCallTargetAddressOffset = kInstrSize; | 734 static const int kCallTargetAddressOffset = kInstrArmSize; |
| 597 | 735 |
| 598 // Distance between start of patched return sequence and the emitted address | 736 // Distance between start of patched return sequence and the emitted address |
| 599 // to jump to. | 737 // to jump to. |
| 600 static const int kPatchReturnSequenceAddressOffset = kInstrSize; | 738 static const int kPatchReturnSequenceAddressOffset = kInstrArmSize; |
| 601 | 739 |
| 602 // Difference between address of current opcode and value read from pc | 740 // Difference between address of current opcode and value read from pc |
| 603 // register. | 741 // register. |
| 604 static const int kPcLoadDelta = 8; | 742 static const int kPcLoadDelta = 8; |
| 605 | 743 |
| 606 static const int kJSReturnSequenceLength = 4; | 744 static const int kJSReturnSequenceLength = 4; |
| 607 | 745 |
| 608 // --------------------------------------------------------------------------- | 746 // --------------------------------------------------------------------------- |
| 609 // Code generation | 747 // Code generation |
| 610 | 748 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 623 // Convenience branch instructions using labels | 761 // Convenience branch instructions using labels |
| 624 void b(Label* L, Condition cond = al) { | 762 void b(Label* L, Condition cond = al) { |
| 625 b(branch_offset(L, cond == al), cond); | 763 b(branch_offset(L, cond == al), cond); |
| 626 } | 764 } |
| 627 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); } | 765 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); } |
| 628 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); } | 766 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); } |
| 629 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); } | 767 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); } |
| 630 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above | 768 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above |
| 631 | 769 |
| 632 // Data-processing instructions | 770 // Data-processing instructions |
| 771 void ubfx(Register dst, Register src1, const Operand& src2, |
| 772 const Operand& src3, Condition cond = al); |
| 773 |
| 633 void and_(Register dst, Register src1, const Operand& src2, | 774 void and_(Register dst, Register src1, const Operand& src2, |
| 634 SBit s = LeaveCC, Condition cond = al); | 775 SBit s = LeaveCC, Condition cond = al); |
| 635 | 776 |
| 636 void eor(Register dst, Register src1, const Operand& src2, | 777 void eor(Register dst, Register src1, const Operand& src2, |
| 637 SBit s = LeaveCC, Condition cond = al); | 778 SBit s = LeaveCC, Condition cond = al); |
| 638 | 779 |
| 639 void sub(Register dst, Register src1, const Operand& src2, | 780 void sub(Register dst, Register src1, const Operand& src2, |
| 640 SBit s = LeaveCC, Condition cond = al); | 781 SBit s = LeaveCC, Condition cond = al); |
| 641 void sub(Register dst, Register src1, Register src2, | 782 void sub(Register dst, Register src1, Register src2, |
| 642 SBit s = LeaveCC, Condition cond = al) { | 783 SBit s = LeaveCC, Condition cond = al) { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 789 LFlag l = Short); // v5 and above | 930 LFlag l = Short); // v5 and above |
| 790 void stc2(Coprocessor coproc, CRegister crd, Register base, int option, | 931 void stc2(Coprocessor coproc, CRegister crd, Register base, int option, |
| 791 LFlag l = Short); // v5 and above | 932 LFlag l = Short); // v5 and above |
| 792 | 933 |
| 793 // Support for VFP. | 934 // Support for VFP. |
| 794 // All these APIs support S0 to S31 and D0 to D15. | 935 // All these APIs support S0 to S31 and D0 to D15. |
| 795 // Currently these APIs do not support extended D registers, i.e, D16 to D31. | 936 // Currently these APIs do not support extended D registers, i.e, D16 to D31. |
| 796 // However, some simple modifications can allow | 937 // However, some simple modifications can allow |
| 797 // these APIs to support D16 to D31. | 938 // these APIs to support D16 to D31. |
| 798 | 939 |
| 940 void vldr(const DwVfpRegister dst, |
| 941 const Register base, |
| 942 int offset, // Offset must be a multiple of 4. |
| 943 const Condition cond = al); |
| 944 void vstr(const DwVfpRegister src, |
| 945 const Register base, |
| 946 int offset, // Offset must be a multiple of 4. |
| 947 const Condition cond = al); |
| 799 void vmov(const DwVfpRegister dst, | 948 void vmov(const DwVfpRegister dst, |
| 800 const Register src1, | 949 const Register src1, |
| 801 const Register src2, | 950 const Register src2, |
| 802 const Condition cond = al); | 951 const Condition cond = al); |
| 803 void vmov(const Register dst1, | 952 void vmov(const Register dst1, |
| 804 const Register dst2, | 953 const Register dst2, |
| 805 const DwVfpRegister src, | 954 const DwVfpRegister src, |
| 806 const Condition cond = al); | 955 const Condition cond = al); |
| 807 void vmov(const SwVfpRegister dst, | 956 void vmov(const SwVfpRegister dst, |
| 808 const Register src, | 957 const Register src, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 | 1006 |
| 858 // Load effective address of memory operand x into register dst | 1007 // Load effective address of memory operand x into register dst |
| 859 void lea(Register dst, const MemOperand& x, | 1008 void lea(Register dst, const MemOperand& x, |
| 860 SBit s = LeaveCC, Condition cond = al); | 1009 SBit s = LeaveCC, Condition cond = al); |
| 861 | 1010 |
| 862 // Jump unconditionally to given label. | 1011 // Jump unconditionally to given label. |
| 863 void jmp(Label* L) { b(L, al); } | 1012 void jmp(Label* L) { b(L, al); } |
| 864 | 1013 |
| 865 // Check the code size generated from label to here. | 1014 // Check the code size generated from label to here. |
| 866 int InstructionsGeneratedSince(Label* l) { | 1015 int InstructionsGeneratedSince(Label* l) { |
| 867 return (pc_offset() - l->pos()) / kInstrSize; | 1016 return (pc_offset() - l->pos()) / kInstrArmSize; |
| 868 } | 1017 } |
| 869 | 1018 |
| 870 // Check whether an immediate fits an addressing mode 1 instruction. | 1019 // Check whether an immediate fits an addressing mode 1 instruction. |
| 871 bool ImmediateFitsAddrMode1Instruction(int32_t imm32); | 1020 bool ImmediateFitsAddrMode1Instruction(int32_t imm32); |
| 872 | 1021 |
| 873 // Postpone the generation of the constant pool for the specified number of | 1022 // Postpone the generation of the constant pool for the specified number of |
| 874 // instructions. | 1023 // instructions. |
| 875 void BlockConstPoolFor(int instructions); | 1024 void BlockConstPoolFor(int instructions); |
| 876 | 1025 |
| 877 // Debugging | 1026 // Debugging |
| (...skipping 10 matching lines...) Expand all Loading... |
| 888 void WriteRecordedPositions(); | 1037 void WriteRecordedPositions(); |
| 889 | 1038 |
| 890 int pc_offset() const { return pc_ - buffer_; } | 1039 int pc_offset() const { return pc_ - buffer_; } |
| 891 int current_position() const { return current_position_; } | 1040 int current_position() const { return current_position_; } |
| 892 int current_statement_position() const { return current_position_; } | 1041 int current_statement_position() const { return current_position_; } |
| 893 | 1042 |
| 894 protected: | 1043 protected: |
| 895 int buffer_space() const { return reloc_info_writer.pos() - pc_; } | 1044 int buffer_space() const { return reloc_info_writer.pos() - pc_; } |
| 896 | 1045 |
| 897 // Read/patch instructions | 1046 // Read/patch instructions |
| 898 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } | 1047 static InstrArm instr_arm_at(byte* pc) { |
| 899 void instr_at_put(byte* pc, Instr instr) { | 1048 return *reinterpret_cast<InstrArm*>(pc); |
| 900 *reinterpret_cast<Instr*>(pc) = instr; | |
| 901 } | 1049 } |
| 902 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } | 1050 |
| 903 void instr_at_put(int pos, Instr instr) { | 1051 void instr_arm_at_put(byte* pc, InstrArm instr) { |
| 904 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; | 1052 *reinterpret_cast<InstrArm*>(pc) = instr; |
| 1053 } |
| 1054 |
| 1055 InstrArm instr_arm_at(int pos) { |
| 1056 return *reinterpret_cast<InstrArm*>(buffer_ + pos); |
| 1057 } |
| 1058 |
| 1059 void instr_arm_at_put(int pos, InstrArm instr) { |
| 1060 *reinterpret_cast<InstrArm*>(buffer_ + pos) = instr; |
| 905 } | 1061 } |
| 906 | 1062 |
| 907 // Decode branch instruction at pos and return branch target pos | 1063 // Decode branch instruction at pos and return branch target pos |
| 908 int target_at(int pos); | 1064 int target_at(int pos); |
| 909 | 1065 |
| 910 // Patch branch instruction at pos to branch to given branch target pos | 1066 // Patch branch instruction at pos to branch to given branch target pos |
| 911 void target_at_put(int pos, int target_pos); | 1067 void target_at_put(int pos, int target_pos); |
| 912 | 1068 |
| 913 // Check if is time to emit a constant pool for pending reloc info entries | 1069 // Check if is time to emit a constant pool for pending reloc info entries |
| 914 void CheckConstPool(bool force_emit, bool require_jump); | 1070 void CheckConstPool(bool force_emit, bool require_jump); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 // location it is accessed from. In this case, we emit a jump over the emitted | 1103 // location it is accessed from. In this case, we emit a jump over the emitted |
| 948 // constant pool. | 1104 // constant pool. |
| 949 // Constants in the pool may be addresses of functions that gets relocated; | 1105 // Constants in the pool may be addresses of functions that gets relocated; |
| 950 // if so, a relocation info entry is associated to the constant pool entry. | 1106 // if so, a relocation info entry is associated to the constant pool entry. |
| 951 | 1107 |
| 952 // Repeated checking whether the constant pool should be emitted is rather | 1108 // Repeated checking whether the constant pool should be emitted is rather |
| 953 // expensive. By default we only check again once a number of instructions | 1109 // expensive. By default we only check again once a number of instructions |
| 954 // has been generated. That also means that the sizing of the buffers is not | 1110 // has been generated. That also means that the sizing of the buffers is not |
| 955 // an exact science, and that we rely on some slop to not overrun buffers. | 1111 // an exact science, and that we rely on some slop to not overrun buffers. |
| 956 static const int kCheckConstIntervalInst = 32; | 1112 static const int kCheckConstIntervalInst = 32; |
| 957 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; | 1113 static const int kCheckConstInterval = |
| 1114 kCheckConstIntervalInst * kInstrArmSize; |
| 958 | 1115 |
| 959 | 1116 |
| 960 // Pools are emitted after function return and in dead code at (more or less) | 1117 // Pools are emitted after function return and in dead code at (more or less) |
| 961 // regular intervals of kDistBetweenPools bytes | 1118 // regular intervals of kDistBetweenPools bytes |
| 962 static const int kDistBetweenPools = 1*KB; | 1119 static const int kDistBetweenPools = 1*KB; |
| 963 | 1120 |
| 964 // Constants in pools are accessed via pc relative addressing, which can | 1121 // Constants in pools are accessed via pc relative addressing, which can |
| 965 // reach +/-4KB thereby defining a maximum distance between the instruction | 1122 // reach +/-4KB thereby defining a maximum distance between the instruction |
| 966 // and the accessed constant. We satisfy this constraint by limiting the | 1123 // and the accessed constant. We satisfy this constraint by limiting the |
| 967 // distance between pools. | 1124 // distance between pools. |
| 968 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval; | 1125 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval; |
| 969 | 1126 |
| 970 // Emission of the constant pool may be blocked in some code sequences | 1127 // Emission of the constant pool may be blocked in some code sequences |
| 971 int no_const_pool_before_; // block emission before this pc offset | 1128 int no_const_pool_before_; // block emission before this pc offset |
| 972 | 1129 |
| 973 // Keep track of the last emitted pool to guarantee a maximal distance | 1130 // Keep track of the last emitted pool to guarantee a maximal distance |
| 974 int last_const_pool_end_; // pc offset following the last constant pool | 1131 int last_const_pool_end_; // pc offset following the last constant pool |
| 975 | 1132 |
| 976 // Relocation info generation | 1133 // Relocation info generation |
| 977 // Each relocation is encoded as a variable size value | 1134 // Each relocation is encoded as a variable size value |
| 978 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; | 1135 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; |
| 979 RelocInfoWriter reloc_info_writer; | 1136 RelocInfoWriter reloc_info_writer; |
| 980 // Relocation info records are also used during code generation as temporary | 1137 // Relocation info records are also used during code generation as temporary |
| 981 // containers for constants and code target addresses until they are emitted | 1138 // containers for constants and code target addresses until they are emitted |
| 982 // to the constant pool. These pending relocation info records are temporarily | 1139 // to the constant pool. These pending relocation info records are temporarily |
| 983 // stored in a separate buffer until a constant pool is emitted. | 1140 // stored in a separate buffer until a constant pool is emitted. |
| 984 // If every instruction in a long sequence is accessing the pool, we need one | 1141 // If every instruction in a long sequence is accessing the pool, we need one |
| 985 // pending relocation entry per instruction. | 1142 // pending relocation entry per instruction. |
| 986 static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize; | 1143 static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrArmSize; |
| 987 RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info | 1144 RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info |
| 988 int num_prinfo_; // number of pending reloc info entries in the buffer | 1145 int num_prinfo_; // number of pending reloc info entries in the buffer |
| 989 | 1146 |
| 990 // The bound position, before this we cannot do instruction elimination. | 1147 // The bound position, before this we cannot do instruction elimination. |
| 991 int last_bound_pos_; | 1148 int last_bound_pos_; |
| 992 | 1149 |
| 993 // source position information | 1150 // source position information |
| 994 int current_position_; | 1151 int current_position_; |
| 995 int current_statement_position_; | 1152 int current_statement_position_; |
| 996 int written_position_; | 1153 int written_position_; |
| 997 int written_statement_position_; | 1154 int written_statement_position_; |
| 1155 bool thumb_mode_; |
| 1156 |
| 998 | 1157 |
| 999 // Code emission | 1158 // Code emission |
| 1000 inline void CheckBuffer(); | 1159 inline void CheckBuffer(); |
| 1160 inline void EnsureThumbMode(); |
| 1161 inline void EnsureArmMode(); |
| 1001 void GrowBuffer(); | 1162 void GrowBuffer(); |
| 1002 inline void emit(Instr x); | 1163 inline void emit_thumb(InstrThumb x); |
| 1164 inline void emit_arm(InstrArm x); |
| 1165 inline void emit_int32(int32_t x); |
| 1003 | 1166 |
| 1004 // Instruction generation | 1167 // ARM Instruction generation |
| 1005 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); | 1168 void addrmod1(InstrArm instr, Register rn, Register rd, const Operand& x); |
| 1006 void addrmod2(Instr instr, Register rd, const MemOperand& x); | 1169 void addrmod2(InstrArm instr, Register rd, const MemOperand& x); |
| 1007 void addrmod3(Instr instr, Register rd, const MemOperand& x); | 1170 void addrmod3(InstrArm instr, Register rd, const MemOperand& x); |
| 1008 void addrmod4(Instr instr, Register rn, RegList rl); | 1171 void addrmod4(InstrArm instr, Register rn, RegList rl); |
| 1009 void addrmod5(Instr instr, CRegister crd, const MemOperand& x); | 1172 void addrmod5(InstrArm instr, CRegister crd, const MemOperand& x); |
| 1173 |
| 1174 // Thumb2 Instruction generation |
| 1175 void DataProcessing(Condition cond, Opcode op, SBit s, |
| 1176 Register rn, Register rd, const Operand& x); |
| 1177 void DataProcessingReg(Opcode op, SBit s, Register rn, Register rd, |
| 1178 Register rm, ShiftOp shiftOp, int shiftBy); |
| 1179 void DataProcessingImm(Opcode op, SBit s, Register rn, Register rd, int imm); |
| 1010 | 1180 |
| 1011 // Labels | 1181 // Labels |
| 1012 void print(Label* L); | 1182 void print(Label* L); |
| 1013 void bind_to(Label* L, int pos); | 1183 void bind_to(Label* L, int pos); |
| 1014 void link_to(Label* L, Label* appendix); | 1184 void link_to(Label* L, Label* appendix); |
| 1015 void next(Label* L); | 1185 void next(Label* L); |
| 1016 | 1186 |
| 1017 // Record reloc info for current pc_ | 1187 // Record reloc info for current pc_ |
| 1018 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 1188 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); |
| 1019 | 1189 |
| 1020 friend class RegExpMacroAssemblerARM; | 1190 friend class RegExpMacroAssemblerARM; |
| 1021 friend class RelocInfo; | 1191 friend class RelocInfo; |
| 1022 friend class CodePatcher; | 1192 friend class CodePatcher; |
| 1023 }; | 1193 }; |
| 1024 | 1194 |
| 1025 } } // namespace v8::internal | 1195 } } // namespace v8::internal |
| 1026 | 1196 |
| 1027 #endif // V8_ARM_ASSEMBLER_THUMB2_H_ | 1197 #endif // V8_ARM_ASSEMBLER_THUMB2_H_ |
| OLD | NEW |