| OLD | NEW |
| 1 //===- subzero/src/IceAssemblerX86BaseImpl.h - base x86 assembler -*- C++ -*-=// | 1 //===- subzero/src/IceAssemblerX86BaseImpl.h - base x86 assembler -*- C++ -*-=// |
| 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
| 4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
| 5 // | 5 // |
| 6 // Modified by the Subzero authors. | 6 // Modified by the Subzero authors. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // The Subzero Code Generator | 10 // The Subzero Code Generator |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 #include "IceCfg.h" | 24 #include "IceCfg.h" |
| 25 #include "IceOperand.h" | 25 #include "IceOperand.h" |
| 26 | 26 |
| 27 namespace Ice { | 27 namespace Ice { |
| 28 namespace X86Internal { | 28 namespace X86Internal { |
| 29 | 29 |
| 30 template <class Machine> | 30 template <class Machine> |
| 31 AssemblerX86Base<Machine>::~AssemblerX86Base<Machine>() { | 31 AssemblerX86Base<Machine>::~AssemblerX86Base<Machine>() { |
| 32 if (BuildDefs::asserts()) { | 32 if (BuildDefs::asserts()) { |
| 33 for (const Label *Label : CfgNodeLabels) { | 33 for (const Label *Label : CfgNodeLabels) { |
| 34 Label->FinalCheck(); | 34 Label->finalCheck(); |
| 35 } | 35 } |
| 36 for (const Label *Label : LocalLabels) { | 36 for (const Label *Label : LocalLabels) { |
| 37 Label->FinalCheck(); | 37 Label->finalCheck(); |
| 38 } | 38 } |
| 39 } | 39 } |
| 40 } | 40 } |
| 41 | 41 |
| 42 template <class Machine> void AssemblerX86Base<Machine>::alignFunction() { | 42 template <class Machine> void AssemblerX86Base<Machine>::alignFunction() { |
| 43 SizeT Align = 1 << getBundleAlignLog2Bytes(); | 43 const SizeT Align = 1 << getBundleAlignLog2Bytes(); |
| 44 SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align); | 44 SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align); |
| 45 const SizeT HltSize = 1; | 45 constexpr SizeT HltSize = 1; |
| 46 while (BytesNeeded > 0) { | 46 while (BytesNeeded > 0) { |
| 47 hlt(); | 47 hlt(); |
| 48 BytesNeeded -= HltSize; | 48 BytesNeeded -= HltSize; |
| 49 } | 49 } |
| 50 } | 50 } |
| 51 | 51 |
| 52 template <class Machine> | 52 template <class Machine> |
| 53 Label *AssemblerX86Base<Machine>::GetOrCreateLabel(SizeT Number, | 53 Label *AssemblerX86Base<Machine>::getOrCreateLabel(SizeT Number, |
| 54 LabelVector &Labels) { | 54 LabelVector &Labels) { |
| 55 Label *L = nullptr; | 55 Label *L = nullptr; |
| 56 if (Number == Labels.size()) { | 56 if (Number == Labels.size()) { |
| 57 L = new (this->allocate<Label>()) Label(); | 57 L = new (this->allocate<Label>()) Label(); |
| 58 Labels.push_back(L); | 58 Labels.push_back(L); |
| 59 return L; | 59 return L; |
| 60 } | 60 } |
| 61 if (Number > Labels.size()) { | 61 if (Number > Labels.size()) { |
| 62 Labels.resize(Number + 1); | 62 Labels.resize(Number + 1); |
| 63 } | 63 } |
| 64 L = Labels[Number]; | 64 L = Labels[Number]; |
| 65 if (!L) { | 65 if (!L) { |
| 66 L = new (this->allocate<Label>()) Label(); | 66 L = new (this->allocate<Label>()) Label(); |
| 67 Labels[Number] = L; | 67 Labels[Number] = L; |
| 68 } | 68 } |
| 69 return L; | 69 return L; |
| 70 } | 70 } |
| 71 | 71 |
| 72 template <class Machine> | 72 template <class Machine> |
| 73 Label *AssemblerX86Base<Machine>::GetOrCreateCfgNodeLabel(SizeT NodeNumber) { | 73 Label *AssemblerX86Base<Machine>::getOrCreateCfgNodeLabel(SizeT NodeNumber) { |
| 74 return GetOrCreateLabel(NodeNumber, CfgNodeLabels); | 74 return getOrCreateLabel(NodeNumber, CfgNodeLabels); |
| 75 } | 75 } |
| 76 | 76 |
| 77 template <class Machine> | 77 template <class Machine> |
| 78 Label *AssemblerX86Base<Machine>::GetOrCreateLocalLabel(SizeT Number) { | 78 Label *AssemblerX86Base<Machine>::getOrCreateLocalLabel(SizeT Number) { |
| 79 return GetOrCreateLabel(Number, LocalLabels); | 79 return getOrCreateLabel(Number, LocalLabels); |
| 80 } | 80 } |
| 81 | 81 |
| 82 template <class Machine> | 82 template <class Machine> |
| 83 void AssemblerX86Base<Machine>::bindCfgNodeLabel(SizeT NodeNumber) { | 83 void AssemblerX86Base<Machine>::bindCfgNodeLabel(SizeT NodeNumber) { |
| 84 assert(!getPreliminary()); | 84 assert(!getPreliminary()); |
| 85 Label *L = GetOrCreateCfgNodeLabel(NodeNumber); | 85 Label *L = getOrCreateCfgNodeLabel(NodeNumber); |
| 86 this->bind(L); | 86 this->bind(L); |
| 87 } | 87 } |
| 88 | 88 |
| 89 template <class Machine> | 89 template <class Machine> |
| 90 void AssemblerX86Base<Machine>::BindLocalLabel(SizeT Number) { | 90 void AssemblerX86Base<Machine>::BindLocalLabel(SizeT Number) { |
| 91 Label *L = GetOrCreateLocalLabel(Number); | 91 Label *L = getOrCreateLocalLabel(Number); |
| 92 if (!getPreliminary()) | 92 if (!getPreliminary()) |
| 93 this->bind(L); | 93 this->bind(L); |
| 94 } | 94 } |
| 95 | 95 |
| 96 template <class Machine> | 96 template <class Machine> |
| 97 void AssemblerX86Base<Machine>::call(typename Traits::GPRRegister reg) { | 97 void AssemblerX86Base<Machine>::call(typename Traits::GPRRegister reg) { |
| 98 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 98 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 99 emitUint8(0xFF); | 99 emitUint8(0xFF); |
| 100 emitRegisterOperand(2, reg); | 100 emitRegisterOperand(2, reg); |
| 101 } | 101 } |
| (...skipping 2671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2773 template <class Machine> void AssemblerX86Base<Machine>::ud2() { | 2773 template <class Machine> void AssemblerX86Base<Machine>::ud2() { |
| 2774 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2774 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2775 emitUint8(0x0F); | 2775 emitUint8(0x0F); |
| 2776 emitUint8(0x0B); | 2776 emitUint8(0x0B); |
| 2777 } | 2777 } |
| 2778 | 2778 |
| 2779 template <class Machine> | 2779 template <class Machine> |
| 2780 void AssemblerX86Base<Machine>::j(typename Traits::Cond::BrCond condition, | 2780 void AssemblerX86Base<Machine>::j(typename Traits::Cond::BrCond condition, |
| 2781 Label *label, bool near) { | 2781 Label *label, bool near) { |
| 2782 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2782 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2783 if (label->IsBound()) { | 2783 if (label->isBound()) { |
| 2784 static const int kShortSize = 2; | 2784 static const int kShortSize = 2; |
| 2785 static const int kLongSize = 6; | 2785 static const int kLongSize = 6; |
| 2786 intptr_t offset = label->Position() - Buffer.size(); | 2786 intptr_t offset = label->getPosition() - Buffer.size(); |
| 2787 assert(offset <= 0); | 2787 assert(offset <= 0); |
| 2788 if (Utils::IsInt(8, offset - kShortSize)) { | 2788 if (Utils::IsInt(8, offset - kShortSize)) { |
| 2789 // TODO(stichnot): Here and in jmp(), we may need to be more | 2789 // TODO(stichnot): Here and in jmp(), we may need to be more |
| 2790 // conservative about the backward branch distance if the branch | 2790 // conservative about the backward branch distance if the branch |
| 2791 // instruction is within a bundle_lock sequence, because the | 2791 // instruction is within a bundle_lock sequence, because the |
| 2792 // distance may increase when padding is added. This isn't an | 2792 // distance may increase when padding is added. This isn't an |
| 2793 // issue for branches outside a bundle_lock, because if padding | 2793 // issue for branches outside a bundle_lock, because if padding |
| 2794 // is added, the retry may change it to a long backward branch | 2794 // is added, the retry may change it to a long backward branch |
| 2795 // without affecting any of the bookkeeping. | 2795 // without affecting any of the bookkeeping. |
| 2796 emitUint8(0x70 + condition); | 2796 emitUint8(0x70 + condition); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2823 template <class Machine> | 2823 template <class Machine> |
| 2824 void AssemblerX86Base<Machine>::jmp(typename Traits::GPRRegister reg) { | 2824 void AssemblerX86Base<Machine>::jmp(typename Traits::GPRRegister reg) { |
| 2825 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2825 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2826 emitUint8(0xFF); | 2826 emitUint8(0xFF); |
| 2827 emitRegisterOperand(4, reg); | 2827 emitRegisterOperand(4, reg); |
| 2828 } | 2828 } |
| 2829 | 2829 |
| 2830 template <class Machine> | 2830 template <class Machine> |
| 2831 void AssemblerX86Base<Machine>::jmp(Label *label, bool near) { | 2831 void AssemblerX86Base<Machine>::jmp(Label *label, bool near) { |
| 2832 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2832 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2833 if (label->IsBound()) { | 2833 if (label->isBound()) { |
| 2834 static const int kShortSize = 2; | 2834 static const int kShortSize = 2; |
| 2835 static const int kLongSize = 5; | 2835 static const int kLongSize = 5; |
| 2836 intptr_t offset = label->Position() - Buffer.size(); | 2836 intptr_t offset = label->getPosition() - Buffer.size(); |
| 2837 assert(offset <= 0); | 2837 assert(offset <= 0); |
| 2838 if (Utils::IsInt(8, offset - kShortSize)) { | 2838 if (Utils::IsInt(8, offset - kShortSize)) { |
| 2839 emitUint8(0xEB); | 2839 emitUint8(0xEB); |
| 2840 emitUint8((offset - kShortSize) & 0xFF); | 2840 emitUint8((offset - kShortSize) & 0xFF); |
| 2841 } else { | 2841 } else { |
| 2842 emitUint8(0xE9); | 2842 emitUint8(0xE9); |
| 2843 emitInt32(offset - kLongSize); | 2843 emitInt32(offset - kLongSize); |
| 2844 } | 2844 } |
| 2845 } else if (near) { | 2845 } else if (near) { |
| 2846 emitUint8(0xEB); | 2846 emitUint8(0xEB); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2952 bytes_needed -= MAX_NOP_SIZE; | 2952 bytes_needed -= MAX_NOP_SIZE; |
| 2953 } | 2953 } |
| 2954 if (bytes_needed) { | 2954 if (bytes_needed) { |
| 2955 nop(bytes_needed); | 2955 nop(bytes_needed); |
| 2956 } | 2956 } |
| 2957 assert(((offset + Buffer.getPosition()) & (alignment - 1)) == 0); | 2957 assert(((offset + Buffer.getPosition()) & (alignment - 1)) == 0); |
| 2958 } | 2958 } |
| 2959 | 2959 |
| 2960 template <class Machine> void AssemblerX86Base<Machine>::bind(Label *label) { | 2960 template <class Machine> void AssemblerX86Base<Machine>::bind(Label *label) { |
| 2961 intptr_t bound = Buffer.size(); | 2961 intptr_t bound = Buffer.size(); |
| 2962 assert(!label->IsBound()); // Labels can only be bound once. | 2962 assert(!label->isBound()); // Labels can only be bound once. |
| 2963 while (label->IsLinked()) { | 2963 while (label->isLinked()) { |
| 2964 intptr_t position = label->LinkPosition(); | 2964 intptr_t position = label->getLinkPosition(); |
| 2965 intptr_t next = Buffer.load<int32_t>(position); | 2965 intptr_t next = Buffer.load<int32_t>(position); |
| 2966 Buffer.store<int32_t>(position, bound - (position + 4)); | 2966 Buffer.store<int32_t>(position, bound - (position + 4)); |
| 2967 label->position_ = next; | 2967 label->Position = next; |
| 2968 } | 2968 } |
| 2969 while (label->HasNear()) { | 2969 while (label->hasNear()) { |
| 2970 intptr_t position = label->NearPosition(); | 2970 intptr_t position = label->getNearPosition(); |
| 2971 intptr_t offset = bound - (position + 1); | 2971 intptr_t offset = bound - (position + 1); |
| 2972 assert(Utils::IsInt(8, offset)); | 2972 assert(Utils::IsInt(8, offset)); |
| 2973 Buffer.store<int8_t>(position, offset); | 2973 Buffer.store<int8_t>(position, offset); |
| 2974 } | 2974 } |
| 2975 label->BindTo(bound); | 2975 label->bindTo(bound); |
| 2976 } | 2976 } |
| 2977 | 2977 |
| 2978 template <class Machine> | 2978 template <class Machine> |
| 2979 void AssemblerX86Base<Machine>::emitOperand( | 2979 void AssemblerX86Base<Machine>::emitOperand( |
| 2980 int rm, const typename Traits::Operand &operand) { | 2980 int rm, const typename Traits::Operand &operand) { |
| 2981 assert(rm >= 0 && rm < 8); | 2981 assert(rm >= 0 && rm < 8); |
| 2982 const intptr_t length = operand.length_; | 2982 const intptr_t length = operand.length_; |
| 2983 assert(length > 0); | 2983 assert(length > 0); |
| 2984 // Emit the ModRM byte updated with the given RM value. | 2984 // Emit the ModRM byte updated with the given RM value. |
| 2985 assert((operand.encoding_[0] & 0x38) == 0); | 2985 assert((operand.encoding_[0] & 0x38) == 0); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3041 } else { | 3041 } else { |
| 3042 emitUint8(0x81); | 3042 emitUint8(0x81); |
| 3043 emitOperand(rm, operand); | 3043 emitOperand(rm, operand); |
| 3044 emitImmediate(Ty, immediate); | 3044 emitImmediate(Ty, immediate); |
| 3045 } | 3045 } |
| 3046 } | 3046 } |
| 3047 | 3047 |
| 3048 template <class Machine> | 3048 template <class Machine> |
| 3049 void AssemblerX86Base<Machine>::emitLabel(Label *label, | 3049 void AssemblerX86Base<Machine>::emitLabel(Label *label, |
| 3050 intptr_t instruction_size) { | 3050 intptr_t instruction_size) { |
| 3051 if (label->IsBound()) { | 3051 if (label->isBound()) { |
| 3052 intptr_t offset = label->Position() - Buffer.size(); | 3052 intptr_t offset = label->getPosition() - Buffer.size(); |
| 3053 assert(offset <= 0); | 3053 assert(offset <= 0); |
| 3054 emitInt32(offset - instruction_size); | 3054 emitInt32(offset - instruction_size); |
| 3055 } else { | 3055 } else { |
| 3056 emitLabelLink(label); | 3056 emitLabelLink(label); |
| 3057 } | 3057 } |
| 3058 } | 3058 } |
| 3059 | 3059 |
| 3060 template <class Machine> | 3060 template <class Machine> |
| 3061 void AssemblerX86Base<Machine>::emitLabelLink(Label *Label) { | 3061 void AssemblerX86Base<Machine>::emitLabelLink(Label *Label) { |
| 3062 assert(!Label->IsBound()); | 3062 assert(!Label->isBound()); |
| 3063 intptr_t Position = Buffer.size(); | 3063 intptr_t Position = Buffer.size(); |
| 3064 emitInt32(Label->position_); | 3064 emitInt32(Label->Position); |
| 3065 if (!getPreliminary()) | 3065 if (!getPreliminary()) |
| 3066 Label->LinkTo(Position); | 3066 Label->linkTo(Position); |
| 3067 } | 3067 } |
| 3068 | 3068 |
| 3069 template <class Machine> | 3069 template <class Machine> |
| 3070 void AssemblerX86Base<Machine>::emitNearLabelLink(Label *label) { | 3070 void AssemblerX86Base<Machine>::emitNearLabelLink(Label *label) { |
| 3071 assert(!label->IsBound()); | 3071 assert(!label->isBound()); |
| 3072 intptr_t position = Buffer.size(); | 3072 intptr_t position = Buffer.size(); |
| 3073 emitUint8(0); | 3073 emitUint8(0); |
| 3074 if (!getPreliminary()) | 3074 if (!getPreliminary()) |
| 3075 label->NearLinkTo(position); | 3075 label->nearLinkTo(position); |
| 3076 } | 3076 } |
| 3077 | 3077 |
| 3078 template <class Machine> | 3078 template <class Machine> |
| 3079 void AssemblerX86Base<Machine>::emitGenericShift( | 3079 void AssemblerX86Base<Machine>::emitGenericShift( |
| 3080 int rm, Type Ty, typename Traits::GPRRegister reg, const Immediate &imm) { | 3080 int rm, Type Ty, typename Traits::GPRRegister reg, const Immediate &imm) { |
| 3081 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 3081 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 3082 assert(imm.is_int8()); | 3082 assert(imm.is_int8()); |
| 3083 if (Ty == IceType_i16) | 3083 if (Ty == IceType_i16) |
| 3084 emitOperandSizeOverride(); | 3084 emitOperandSizeOverride(); |
| 3085 if (imm.value() == 1) { | 3085 if (imm.value() == 1) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3100 assert(shifter == Traits::Encoded_Reg_Counter); | 3100 assert(shifter == Traits::Encoded_Reg_Counter); |
| 3101 (void)shifter; | 3101 (void)shifter; |
| 3102 if (Ty == IceType_i16) | 3102 if (Ty == IceType_i16) |
| 3103 emitOperandSizeOverride(); | 3103 emitOperandSizeOverride(); |
| 3104 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); | 3104 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); |
| 3105 emitOperand(rm, operand); | 3105 emitOperand(rm, operand); |
| 3106 } | 3106 } |
| 3107 | 3107 |
| 3108 } // end of namespace X86Internal | 3108 } // end of namespace X86Internal |
| 3109 } // end of namespace Ice | 3109 } // end of namespace Ice |
| OLD | NEW |