| 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 28 matching lines...) Expand all Loading... |
| 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 B13 = 1 << 13, |
| 92 B14 = 1 << 14, |
| 93 B15 = 1 << 15, |
| 94 B16 = 1 << 16, |
| 95 B18 = 1 << 18, |
| 96 B19 = 1 << 19, |
| 97 B20 = 1 << 20, |
| 98 B21 = 1 << 21, |
| 99 B22 = 1 << 22, |
| 100 B23 = 1 << 23, |
| 101 B24 = 1 << 24, |
| 102 B25 = 1 << 25, |
| 103 B26 = 1 << 26, |
| 104 B27 = 1 << 27 |
| 105 }; |
| 106 |
| 49 // CPU Registers. | 107 // CPU Registers. |
| 50 // | 108 // |
| 51 // 1) We would prefer to use an enum, but enum values are assignment- | 109 // 1) We would prefer to use an enum, but enum values are assignment- |
| 52 // compatible with int, which has caused code-generation bugs. | 110 // compatible with int, which has caused code-generation bugs. |
| 53 // | 111 // |
| 54 // 2) We would prefer to use a class instead of a struct but we don't like | 112 // 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 | 113 // the register initialization to depend on the particular initialization |
| 56 // order (which appears to be different on OS X, Linux, and Windows for the | 114 // 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 | 115 // installed versions of C++ we tried). Using a struct permits C-style |
| 58 // "initialization". Also, the Register objects cannot be const as this | 116 // "initialization". Also, the Register objects cannot be const as this |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 | 367 |
| 310 // Hints are not used on the arm. Negating is trivial. | 368 // Hints are not used on the arm. Negating is trivial. |
| 311 inline Hint NegateHint(Hint ignored) { return no_hint; } | 369 inline Hint NegateHint(Hint ignored) { return no_hint; } |
| 312 | 370 |
| 313 | 371 |
| 314 // ----------------------------------------------------------------------------- | 372 // ----------------------------------------------------------------------------- |
| 315 // Addressing modes and instruction variants | 373 // Addressing modes and instruction variants |
| 316 | 374 |
| 317 // Shifter operand shift operation | 375 // Shifter operand shift operation |
| 318 enum ShiftOp { | 376 enum ShiftOp { |
| 319 LSL = 0 << 5, | 377 LSL = 0, |
| 320 LSR = 1 << 5, | 378 LSR = 1, |
| 321 ASR = 2 << 5, | 379 ASR = 2, |
| 322 ROR = 3 << 5, | 380 ROR = 3, |
| 323 RRX = -1 | 381 RRX = -1 |
| 324 }; | 382 }; |
| 325 | 383 |
| 326 | 384 |
| 327 // Condition code updating mode | 385 // Condition code updating mode |
| 328 enum SBit { | 386 enum SBit { |
| 329 SetCC = 1 << 20, // set condition code | 387 SetCC = 1 << 20, // set condition code |
| 330 LeaveCC = 0 << 20 // leave condition code unchanged | 388 LeaveCC = 0 << 20 // leave condition code unchanged |
| 331 }; | 389 }; |
| 332 | 390 |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 explicit Scope(CpuFeature f) {} | 555 explicit Scope(CpuFeature f) {} |
| 498 #endif | 556 #endif |
| 499 }; | 557 }; |
| 500 | 558 |
| 501 private: | 559 private: |
| 502 static unsigned supported_; | 560 static unsigned supported_; |
| 503 static unsigned enabled_; | 561 static unsigned enabled_; |
| 504 static unsigned found_by_runtime_probing_; | 562 static unsigned found_by_runtime_probing_; |
| 505 }; | 563 }; |
| 506 | 564 |
| 565 typedef int32_t InstrArm; |
| 566 typedef int16_t InstrThumb; |
| 507 | 567 |
| 508 typedef int32_t Instr; | 568 // Hack to keep the code patcher happy for now. |
| 569 typedef InstrArm Instr; |
| 509 | 570 |
| 510 | 571 |
| 511 extern const Instr kMovLrPc; | 572 extern const InstrArm kMovLrPc; |
| 512 extern const Instr kLdrPCPattern; | 573 extern const InstrArm kLdrPCPattern; |
| 513 | 574 |
| 514 | 575 |
| 515 class Assembler : public Malloced { | 576 class Assembler : public Malloced { |
| 516 public: | 577 public: |
| 517 // Create an assembler. Instructions and relocation information are emitted | 578 // Create an assembler. Instructions and relocation information are emitted |
| 518 // into a buffer, with the instructions starting from the beginning and the | 579 // into a buffer, with the instructions starting from the beginning and the |
| 519 // relocation information starting from the end of the buffer. See CodeDesc | 580 // relocation information starting from the end of the buffer. See CodeDesc |
| 520 // for a detailed comment on the layout (globals.h). | 581 // for a detailed comment on the layout (globals.h). |
| 521 // | 582 // |
| 522 // If the provided buffer is NULL, the assembler allocates and grows its own | 583 // 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... |
| 580 set_target_at(constant_pool_entry, target); | 641 set_target_at(constant_pool_entry, target); |
| 581 } | 642 } |
| 582 | 643 |
| 583 // Here we are patching the address in the constant pool, not the actual call | 644 // 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 | 645 // instruction. The address in the constant pool is the same size as a |
| 585 // pointer. | 646 // pointer. |
| 586 static const int kCallTargetSize = kPointerSize; | 647 static const int kCallTargetSize = kPointerSize; |
| 587 static const int kExternalTargetSize = kPointerSize; | 648 static const int kExternalTargetSize = kPointerSize; |
| 588 | 649 |
| 589 // Size of an instruction. | 650 // Size of an instruction. |
| 651 static const int kInstrArmSize = sizeof(InstrArm); |
| 652 static const int kInstrThumbSize = sizeof(InstrThumb); |
| 653 // Keep the code generator happy for now. |
| 590 static const int kInstrSize = sizeof(Instr); | 654 static const int kInstrSize = sizeof(Instr); |
| 591 | 655 |
| 592 // Distance between the instruction referring to the address of the call | 656 // Distance between the instruction referring to the address of the call |
| 593 // target (ldr pc, [target addr in const pool]) and the return address | 657 // target (ldr pc, [target addr in const pool]) and the return address |
| 594 static const int kCallTargetAddressOffset = kInstrSize; | 658 static const int kCallTargetAddressOffset = kInstrArmSize; |
| 595 | 659 |
| 596 // Distance between start of patched return sequence and the emitted address | 660 // Distance between start of patched return sequence and the emitted address |
| 597 // to jump to. | 661 // to jump to. |
| 598 static const int kPatchReturnSequenceAddressOffset = kInstrSize; | 662 static const int kPatchReturnSequenceAddressOffset = kInstrArmSize; |
| 599 | 663 |
| 600 // Difference between address of current opcode and value read from pc | 664 // Difference between address of current opcode and value read from pc |
| 601 // register. | 665 // register. |
| 602 static const int kPcLoadDelta = 8; | 666 static const int kPcLoadDelta = 8; |
| 603 | 667 |
| 604 static const int kJSReturnSequenceLength = 4; | 668 static const int kJSReturnSequenceLength = 4; |
| 605 | 669 |
| 606 // --------------------------------------------------------------------------- | 670 // --------------------------------------------------------------------------- |
| 607 // Code generation | 671 // Code generation |
| 608 | 672 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 | 930 |
| 867 // Load effective address of memory operand x into register dst | 931 // Load effective address of memory operand x into register dst |
| 868 void lea(Register dst, const MemOperand& x, | 932 void lea(Register dst, const MemOperand& x, |
| 869 SBit s = LeaveCC, Condition cond = al); | 933 SBit s = LeaveCC, Condition cond = al); |
| 870 | 934 |
| 871 // Jump unconditionally to given label. | 935 // Jump unconditionally to given label. |
| 872 void jmp(Label* L) { b(L, al); } | 936 void jmp(Label* L) { b(L, al); } |
| 873 | 937 |
| 874 // Check the code size generated from label to here. | 938 // Check the code size generated from label to here. |
| 875 int InstructionsGeneratedSince(Label* l) { | 939 int InstructionsGeneratedSince(Label* l) { |
| 876 return (pc_offset() - l->pos()) / kInstrSize; | 940 return (pc_offset() - l->pos()) / kInstrArmSize; |
| 877 } | 941 } |
| 878 | 942 |
| 879 // Check whether an immediate fits an addressing mode 1 instruction. | 943 // Check whether an immediate fits an addressing mode 1 instruction. |
| 880 bool ImmediateFitsAddrMode1Instruction(int32_t imm32); | 944 bool ImmediateFitsAddrMode1Instruction(int32_t imm32); |
| 881 | 945 |
| 882 // Postpone the generation of the constant pool for the specified number of | 946 // Postpone the generation of the constant pool for the specified number of |
| 883 // instructions. | 947 // instructions. |
| 884 void BlockConstPoolFor(int instructions); | 948 void BlockConstPoolFor(int instructions); |
| 885 | 949 |
| 886 // Debugging | 950 // Debugging |
| (...skipping 10 matching lines...) Expand all Loading... |
| 897 void WriteRecordedPositions(); | 961 void WriteRecordedPositions(); |
| 898 | 962 |
| 899 int pc_offset() const { return pc_ - buffer_; } | 963 int pc_offset() const { return pc_ - buffer_; } |
| 900 int current_position() const { return current_position_; } | 964 int current_position() const { return current_position_; } |
| 901 int current_statement_position() const { return current_position_; } | 965 int current_statement_position() const { return current_position_; } |
| 902 | 966 |
| 903 protected: | 967 protected: |
| 904 int buffer_space() const { return reloc_info_writer.pos() - pc_; } | 968 int buffer_space() const { return reloc_info_writer.pos() - pc_; } |
| 905 | 969 |
| 906 // Read/patch instructions | 970 // Read/patch instructions |
| 907 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } | 971 static InstrArm instr_arm_at(byte* pc) { |
| 908 void instr_at_put(byte* pc, Instr instr) { | 972 return *reinterpret_cast<InstrArm*>(pc); |
| 909 *reinterpret_cast<Instr*>(pc) = instr; | |
| 910 } | 973 } |
| 911 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } | 974 |
| 912 void instr_at_put(int pos, Instr instr) { | 975 void instr_arm_at_put(byte* pc, InstrArm instr) { |
| 913 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; | 976 *reinterpret_cast<InstrArm*>(pc) = instr; |
| 977 } |
| 978 |
| 979 InstrArm instr_arm_at(int pos) { |
| 980 return *reinterpret_cast<InstrArm*>(buffer_ + pos); |
| 981 } |
| 982 |
| 983 void instr_arm_at_put(int pos, InstrArm instr) { |
| 984 *reinterpret_cast<InstrArm*>(buffer_ + pos) = instr; |
| 914 } | 985 } |
| 915 | 986 |
| 916 // Decode branch instruction at pos and return branch target pos | 987 // Decode branch instruction at pos and return branch target pos |
| 917 int target_at(int pos); | 988 int target_at(int pos); |
| 918 | 989 |
| 919 // Patch branch instruction at pos to branch to given branch target pos | 990 // Patch branch instruction at pos to branch to given branch target pos |
| 920 void target_at_put(int pos, int target_pos); | 991 void target_at_put(int pos, int target_pos); |
| 921 | 992 |
| 922 // Check if is time to emit a constant pool for pending reloc info entries | 993 // Check if is time to emit a constant pool for pending reloc info entries |
| 923 void CheckConstPool(bool force_emit, bool require_jump); | 994 void CheckConstPool(bool force_emit, bool require_jump); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 956 // location it is accessed from. In this case, we emit a jump over the emitted | 1027 // location it is accessed from. In this case, we emit a jump over the emitted |
| 957 // constant pool. | 1028 // constant pool. |
| 958 // Constants in the pool may be addresses of functions that gets relocated; | 1029 // 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. | 1030 // if so, a relocation info entry is associated to the constant pool entry. |
| 960 | 1031 |
| 961 // Repeated checking whether the constant pool should be emitted is rather | 1032 // Repeated checking whether the constant pool should be emitted is rather |
| 962 // expensive. By default we only check again once a number of instructions | 1033 // 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 | 1034 // 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. | 1035 // an exact science, and that we rely on some slop to not overrun buffers. |
| 965 static const int kCheckConstIntervalInst = 32; | 1036 static const int kCheckConstIntervalInst = 32; |
| 966 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; | 1037 static const int kCheckConstInterval = |
| 1038 kCheckConstIntervalInst * kInstrArmSize; |
| 967 | 1039 |
| 968 | 1040 |
| 969 // Pools are emitted after function return and in dead code at (more or less) | 1041 // Pools are emitted after function return and in dead code at (more or less) |
| 970 // regular intervals of kDistBetweenPools bytes | 1042 // regular intervals of kDistBetweenPools bytes |
| 971 static const int kDistBetweenPools = 1*KB; | 1043 static const int kDistBetweenPools = 1*KB; |
| 972 | 1044 |
| 973 // Constants in pools are accessed via pc relative addressing, which can | 1045 // Constants in pools are accessed via pc relative addressing, which can |
| 974 // reach +/-4KB thereby defining a maximum distance between the instruction | 1046 // reach +/-4KB thereby defining a maximum distance between the instruction |
| 975 // and the accessed constant. We satisfy this constraint by limiting the | 1047 // and the accessed constant. We satisfy this constraint by limiting the |
| 976 // distance between pools. | 1048 // distance between pools. |
| 977 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval; | 1049 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval; |
| 978 | 1050 |
| 979 // Emission of the constant pool may be blocked in some code sequences | 1051 // Emission of the constant pool may be blocked in some code sequences |
| 980 int no_const_pool_before_; // block emission before this pc offset | 1052 int no_const_pool_before_; // block emission before this pc offset |
| 981 | 1053 |
| 982 // Keep track of the last emitted pool to guarantee a maximal distance | 1054 // 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 | 1055 int last_const_pool_end_; // pc offset following the last constant pool |
| 984 | 1056 |
| 985 // Relocation info generation | 1057 // Relocation info generation |
| 986 // Each relocation is encoded as a variable size value | 1058 // Each relocation is encoded as a variable size value |
| 987 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; | 1059 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; |
| 988 RelocInfoWriter reloc_info_writer; | 1060 RelocInfoWriter reloc_info_writer; |
| 989 // Relocation info records are also used during code generation as temporary | 1061 // Relocation info records are also used during code generation as temporary |
| 990 // containers for constants and code target addresses until they are emitted | 1062 // containers for constants and code target addresses until they are emitted |
| 991 // to the constant pool. These pending relocation info records are temporarily | 1063 // to the constant pool. These pending relocation info records are temporarily |
| 992 // stored in a separate buffer until a constant pool is emitted. | 1064 // 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 | 1065 // If every instruction in a long sequence is accessing the pool, we need one |
| 994 // pending relocation entry per instruction. | 1066 // pending relocation entry per instruction. |
| 995 static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize; | 1067 static const int kMaxNumPRInfo = kMaxDistBetweenPools / kInstrArmSize; |
| 996 RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info | 1068 RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info |
| 997 int num_prinfo_; // number of pending reloc info entries in the buffer | 1069 int num_prinfo_; // number of pending reloc info entries in the buffer |
| 998 | 1070 |
| 999 // The bound position, before this we cannot do instruction elimination. | 1071 // The bound position, before this we cannot do instruction elimination. |
| 1000 int last_bound_pos_; | 1072 int last_bound_pos_; |
| 1001 | 1073 |
| 1002 // source position information | 1074 // source position information |
| 1003 int current_position_; | 1075 int current_position_; |
| 1004 int current_statement_position_; | 1076 int current_statement_position_; |
| 1005 int written_position_; | 1077 int written_position_; |
| 1006 int written_statement_position_; | 1078 int written_statement_position_; |
| 1079 bool thumb_mode_; |
| 1080 |
| 1007 | 1081 |
| 1008 // Code emission | 1082 // Code emission |
| 1009 inline void CheckBuffer(); | 1083 inline void CheckBuffer(); |
| 1084 inline void EnsureThumbMode(); |
| 1085 inline void EnsureArmMode(); |
| 1010 void GrowBuffer(); | 1086 void GrowBuffer(); |
| 1011 inline void emit(Instr x); | 1087 inline void emit_thumb(InstrThumb x); |
| 1088 inline void emit_arm(InstrArm x); |
| 1089 inline void emit_int32(int32_t x); |
| 1012 | 1090 |
| 1013 // Instruction generation | 1091 // ARM Instruction generation |
| 1014 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); | 1092 void addrmod1(InstrArm instr, Register rn, Register rd, const Operand& x); |
| 1015 void addrmod2(Instr instr, Register rd, const MemOperand& x); | 1093 void addrmod2(InstrArm instr, Register rd, const MemOperand& x); |
| 1016 void addrmod3(Instr instr, Register rd, const MemOperand& x); | 1094 void addrmod3(InstrArm instr, Register rd, const MemOperand& x); |
| 1017 void addrmod4(Instr instr, Register rn, RegList rl); | 1095 void addrmod4(InstrArm instr, Register rn, RegList rl); |
| 1018 void addrmod5(Instr instr, CRegister crd, const MemOperand& x); | 1096 void addrmod5(InstrArm instr, CRegister crd, const MemOperand& x); |
| 1097 |
| 1098 // Thumb2 Instruction generation |
| 1099 void DataProcessing(Condition cond, Opcode op, SBit s, |
| 1100 Register rn, Register rd, const Operand& x); |
| 1101 void DataProcessingReg(Opcode op, SBit s, Register rn, Register rd, |
| 1102 Register rm, ShiftOp shiftOp, int shiftBy); |
| 1103 void DataProcessingImm(Opcode op, SBit s, Register rn, Register rd, int imm); |
| 1019 | 1104 |
| 1020 // Labels | 1105 // Labels |
| 1021 void print(Label* L); | 1106 void print(Label* L); |
| 1022 void bind_to(Label* L, int pos); | 1107 void bind_to(Label* L, int pos); |
| 1023 void link_to(Label* L, Label* appendix); | 1108 void link_to(Label* L, Label* appendix); |
| 1024 void next(Label* L); | 1109 void next(Label* L); |
| 1025 | 1110 |
| 1026 // Record reloc info for current pc_ | 1111 // Record reloc info for current pc_ |
| 1027 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 1112 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); |
| 1028 | 1113 |
| 1029 friend class RegExpMacroAssemblerARM; | 1114 friend class RegExpMacroAssemblerARM; |
| 1030 friend class RelocInfo; | 1115 friend class RelocInfo; |
| 1031 friend class CodePatcher; | 1116 friend class CodePatcher; |
| 1032 }; | 1117 }; |
| 1033 | 1118 |
| 1034 } } // namespace v8::internal | 1119 } } // namespace v8::internal |
| 1035 | 1120 |
| 1036 #endif // V8_ARM_ASSEMBLER_THUMB2_H_ | 1121 #endif // V8_ARM_ASSEMBLER_THUMB2_H_ |
| OLD | NEW |