| 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> void AssemblerX86Base<Machine>::alignCfgNode() { |
| 53 const SizeT Align = 1 << getBundleAlignLog2Bytes(); |
| 54 padWithNop(Utils::OffsetToAlignment(Buffer.getPosition(), Align)); |
| 55 } |
| 56 |
| 52 template <class Machine> | 57 template <class Machine> |
| 53 Label *AssemblerX86Base<Machine>::GetOrCreateLabel(SizeT Number, | 58 Label *AssemblerX86Base<Machine>::getOrCreateLabel(SizeT Number, |
| 54 LabelVector &Labels) { | 59 LabelVector &Labels) { |
| 55 Label *L = nullptr; | 60 Label *L = nullptr; |
| 56 if (Number == Labels.size()) { | 61 if (Number == Labels.size()) { |
| 57 L = new (this->allocate<Label>()) Label(); | 62 L = new (this->allocate<Label>()) Label(); |
| 58 Labels.push_back(L); | 63 Labels.push_back(L); |
| 59 return L; | 64 return L; |
| 60 } | 65 } |
| 61 if (Number > Labels.size()) { | 66 if (Number > Labels.size()) { |
| 62 Labels.resize(Number + 1); | 67 Labels.resize(Number + 1); |
| 63 } | 68 } |
| 64 L = Labels[Number]; | 69 L = Labels[Number]; |
| 65 if (!L) { | 70 if (!L) { |
| 66 L = new (this->allocate<Label>()) Label(); | 71 L = new (this->allocate<Label>()) Label(); |
| 67 Labels[Number] = L; | 72 Labels[Number] = L; |
| 68 } | 73 } |
| 69 return L; | 74 return L; |
| 70 } | 75 } |
| 71 | 76 |
| 72 template <class Machine> | 77 template <class Machine> |
| 73 Label *AssemblerX86Base<Machine>::GetOrCreateCfgNodeLabel(SizeT NodeNumber) { | 78 Label *AssemblerX86Base<Machine>::getOrCreateCfgNodeLabel(SizeT NodeNumber) { |
| 74 return GetOrCreateLabel(NodeNumber, CfgNodeLabels); | 79 return getOrCreateLabel(NodeNumber, CfgNodeLabels); |
| 75 } | 80 } |
| 76 | 81 |
| 77 template <class Machine> | 82 template <class Machine> |
| 78 Label *AssemblerX86Base<Machine>::GetOrCreateLocalLabel(SizeT Number) { | 83 Label *AssemblerX86Base<Machine>::getOrCreateLocalLabel(SizeT Number) { |
| 79 return GetOrCreateLabel(Number, LocalLabels); | 84 return getOrCreateLabel(Number, LocalLabels); |
| 80 } | 85 } |
| 81 | 86 |
| 82 template <class Machine> | 87 template <class Machine> |
| 83 void AssemblerX86Base<Machine>::bindCfgNodeLabel(SizeT NodeNumber) { | 88 void AssemblerX86Base<Machine>::bindCfgNodeLabel(SizeT NodeNumber) { |
| 84 assert(!getPreliminary()); | 89 assert(!getPreliminary()); |
| 85 Label *L = GetOrCreateCfgNodeLabel(NodeNumber); | 90 Label *L = getOrCreateCfgNodeLabel(NodeNumber); |
| 86 this->bind(L); | 91 this->bind(L); |
| 87 } | 92 } |
| 88 | 93 |
| 89 template <class Machine> | 94 template <class Machine> |
| 90 void AssemblerX86Base<Machine>::BindLocalLabel(SizeT Number) { | 95 void AssemblerX86Base<Machine>::BindLocalLabel(SizeT Number) { |
| 91 Label *L = GetOrCreateLocalLabel(Number); | 96 Label *L = getOrCreateLocalLabel(Number); |
| 92 if (!getPreliminary()) | 97 if (!getPreliminary()) |
| 93 this->bind(L); | 98 this->bind(L); |
| 94 } | 99 } |
| 95 | 100 |
| 96 template <class Machine> | 101 template <class Machine> |
| 97 void AssemblerX86Base<Machine>::call(typename Traits::GPRRegister reg) { | 102 void AssemblerX86Base<Machine>::call(typename Traits::GPRRegister reg) { |
| 98 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 103 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 99 emitUint8(0xFF); | 104 emitUint8(0xFF); |
| 100 emitRegisterOperand(2, reg); | 105 emitRegisterOperand(2, reg); |
| 101 } | 106 } |
| (...skipping 2671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2773 template <class Machine> void AssemblerX86Base<Machine>::ud2() { | 2778 template <class Machine> void AssemblerX86Base<Machine>::ud2() { |
| 2774 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2779 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2775 emitUint8(0x0F); | 2780 emitUint8(0x0F); |
| 2776 emitUint8(0x0B); | 2781 emitUint8(0x0B); |
| 2777 } | 2782 } |
| 2778 | 2783 |
| 2779 template <class Machine> | 2784 template <class Machine> |
| 2780 void AssemblerX86Base<Machine>::j(typename Traits::Cond::BrCond condition, | 2785 void AssemblerX86Base<Machine>::j(typename Traits::Cond::BrCond condition, |
| 2781 Label *label, bool near) { | 2786 Label *label, bool near) { |
| 2782 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2787 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2783 if (label->IsBound()) { | 2788 if (label->isBound()) { |
| 2784 static const int kShortSize = 2; | 2789 static const int kShortSize = 2; |
| 2785 static const int kLongSize = 6; | 2790 static const int kLongSize = 6; |
| 2786 intptr_t offset = label->Position() - Buffer.size(); | 2791 intptr_t offset = label->getPosition() - Buffer.size(); |
| 2787 assert(offset <= 0); | 2792 assert(offset <= 0); |
| 2788 if (Utils::IsInt(8, offset - kShortSize)) { | 2793 if (Utils::IsInt(8, offset - kShortSize)) { |
| 2789 // TODO(stichnot): Here and in jmp(), we may need to be more | 2794 // TODO(stichnot): Here and in jmp(), we may need to be more |
| 2790 // conservative about the backward branch distance if the branch | 2795 // conservative about the backward branch distance if the branch |
| 2791 // instruction is within a bundle_lock sequence, because the | 2796 // instruction is within a bundle_lock sequence, because the |
| 2792 // distance may increase when padding is added. This isn't an | 2797 // distance may increase when padding is added. This isn't an |
| 2793 // issue for branches outside a bundle_lock, because if padding | 2798 // issue for branches outside a bundle_lock, because if padding |
| 2794 // is added, the retry may change it to a long backward branch | 2799 // is added, the retry may change it to a long backward branch |
| 2795 // without affecting any of the bookkeeping. | 2800 // without affecting any of the bookkeeping. |
| 2796 emitUint8(0x70 + condition); | 2801 emitUint8(0x70 + condition); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2823 template <class Machine> | 2828 template <class Machine> |
| 2824 void AssemblerX86Base<Machine>::jmp(typename Traits::GPRRegister reg) { | 2829 void AssemblerX86Base<Machine>::jmp(typename Traits::GPRRegister reg) { |
| 2825 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2830 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2826 emitUint8(0xFF); | 2831 emitUint8(0xFF); |
| 2827 emitRegisterOperand(4, reg); | 2832 emitRegisterOperand(4, reg); |
| 2828 } | 2833 } |
| 2829 | 2834 |
| 2830 template <class Machine> | 2835 template <class Machine> |
| 2831 void AssemblerX86Base<Machine>::jmp(Label *label, bool near) { | 2836 void AssemblerX86Base<Machine>::jmp(Label *label, bool near) { |
| 2832 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2837 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2833 if (label->IsBound()) { | 2838 if (label->isBound()) { |
| 2834 static const int kShortSize = 2; | 2839 static const int kShortSize = 2; |
| 2835 static const int kLongSize = 5; | 2840 static const int kLongSize = 5; |
| 2836 intptr_t offset = label->Position() - Buffer.size(); | 2841 intptr_t offset = label->getPosition() - Buffer.size(); |
| 2837 assert(offset <= 0); | 2842 assert(offset <= 0); |
| 2838 if (Utils::IsInt(8, offset - kShortSize)) { | 2843 if (Utils::IsInt(8, offset - kShortSize)) { |
| 2839 emitUint8(0xEB); | 2844 emitUint8(0xEB); |
| 2840 emitUint8((offset - kShortSize) & 0xFF); | 2845 emitUint8((offset - kShortSize) & 0xFF); |
| 2841 } else { | 2846 } else { |
| 2842 emitUint8(0xE9); | 2847 emitUint8(0xE9); |
| 2843 emitInt32(offset - kLongSize); | 2848 emitInt32(offset - kLongSize); |
| 2844 } | 2849 } |
| 2845 } else if (near) { | 2850 } else if (near) { |
| 2846 emitUint8(0xEB); | 2851 emitUint8(0xEB); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2952 bytes_needed -= MAX_NOP_SIZE; | 2957 bytes_needed -= MAX_NOP_SIZE; |
| 2953 } | 2958 } |
| 2954 if (bytes_needed) { | 2959 if (bytes_needed) { |
| 2955 nop(bytes_needed); | 2960 nop(bytes_needed); |
| 2956 } | 2961 } |
| 2957 assert(((offset + Buffer.getPosition()) & (alignment - 1)) == 0); | 2962 assert(((offset + Buffer.getPosition()) & (alignment - 1)) == 0); |
| 2958 } | 2963 } |
| 2959 | 2964 |
| 2960 template <class Machine> void AssemblerX86Base<Machine>::bind(Label *label) { | 2965 template <class Machine> void AssemblerX86Base<Machine>::bind(Label *label) { |
| 2961 intptr_t bound = Buffer.size(); | 2966 intptr_t bound = Buffer.size(); |
| 2962 assert(!label->IsBound()); // Labels can only be bound once. | 2967 assert(!label->isBound()); // Labels can only be bound once. |
| 2963 while (label->IsLinked()) { | 2968 while (label->isLinked()) { |
| 2964 intptr_t position = label->LinkPosition(); | 2969 intptr_t position = label->getLinkPosition(); |
| 2965 intptr_t next = Buffer.load<int32_t>(position); | 2970 intptr_t next = Buffer.load<int32_t>(position); |
| 2966 Buffer.store<int32_t>(position, bound - (position + 4)); | 2971 Buffer.store<int32_t>(position, bound - (position + 4)); |
| 2967 label->position_ = next; | 2972 label->Position = next; |
| 2968 } | 2973 } |
| 2969 while (label->HasNear()) { | 2974 while (label->hasNear()) { |
| 2970 intptr_t position = label->NearPosition(); | 2975 intptr_t position = label->getNearPosition(); |
| 2971 intptr_t offset = bound - (position + 1); | 2976 intptr_t offset = bound - (position + 1); |
| 2972 assert(Utils::IsInt(8, offset)); | 2977 assert(Utils::IsInt(8, offset)); |
| 2973 Buffer.store<int8_t>(position, offset); | 2978 Buffer.store<int8_t>(position, offset); |
| 2974 } | 2979 } |
| 2975 label->BindTo(bound); | 2980 label->bindTo(bound); |
| 2976 } | 2981 } |
| 2977 | 2982 |
| 2978 template <class Machine> | 2983 template <class Machine> |
| 2979 void AssemblerX86Base<Machine>::emitOperand( | 2984 void AssemblerX86Base<Machine>::emitOperand( |
| 2980 int rm, const typename Traits::Operand &operand) { | 2985 int rm, const typename Traits::Operand &operand) { |
| 2981 assert(rm >= 0 && rm < 8); | 2986 assert(rm >= 0 && rm < 8); |
| 2982 const intptr_t length = operand.length_; | 2987 const intptr_t length = operand.length_; |
| 2983 assert(length > 0); | 2988 assert(length > 0); |
| 2984 // Emit the ModRM byte updated with the given RM value. | 2989 // Emit the ModRM byte updated with the given RM value. |
| 2985 assert((operand.encoding_[0] & 0x38) == 0); | 2990 assert((operand.encoding_[0] & 0x38) == 0); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3041 } else { | 3046 } else { |
| 3042 emitUint8(0x81); | 3047 emitUint8(0x81); |
| 3043 emitOperand(rm, operand); | 3048 emitOperand(rm, operand); |
| 3044 emitImmediate(Ty, immediate); | 3049 emitImmediate(Ty, immediate); |
| 3045 } | 3050 } |
| 3046 } | 3051 } |
| 3047 | 3052 |
| 3048 template <class Machine> | 3053 template <class Machine> |
| 3049 void AssemblerX86Base<Machine>::emitLabel(Label *label, | 3054 void AssemblerX86Base<Machine>::emitLabel(Label *label, |
| 3050 intptr_t instruction_size) { | 3055 intptr_t instruction_size) { |
| 3051 if (label->IsBound()) { | 3056 if (label->isBound()) { |
| 3052 intptr_t offset = label->Position() - Buffer.size(); | 3057 intptr_t offset = label->getPosition() - Buffer.size(); |
| 3053 assert(offset <= 0); | 3058 assert(offset <= 0); |
| 3054 emitInt32(offset - instruction_size); | 3059 emitInt32(offset - instruction_size); |
| 3055 } else { | 3060 } else { |
| 3056 emitLabelLink(label); | 3061 emitLabelLink(label); |
| 3057 } | 3062 } |
| 3058 } | 3063 } |
| 3059 | 3064 |
| 3060 template <class Machine> | 3065 template <class Machine> |
| 3061 void AssemblerX86Base<Machine>::emitLabelLink(Label *Label) { | 3066 void AssemblerX86Base<Machine>::emitLabelLink(Label *Label) { |
| 3062 assert(!Label->IsBound()); | 3067 assert(!Label->isBound()); |
| 3063 intptr_t Position = Buffer.size(); | 3068 intptr_t Position = Buffer.size(); |
| 3064 emitInt32(Label->position_); | 3069 emitInt32(Label->Position); |
| 3065 if (!getPreliminary()) | 3070 if (!getPreliminary()) |
| 3066 Label->LinkTo(Position); | 3071 Label->linkTo(Position); |
| 3067 } | 3072 } |
| 3068 | 3073 |
| 3069 template <class Machine> | 3074 template <class Machine> |
| 3070 void AssemblerX86Base<Machine>::emitNearLabelLink(Label *label) { | 3075 void AssemblerX86Base<Machine>::emitNearLabelLink(Label *label) { |
| 3071 assert(!label->IsBound()); | 3076 assert(!label->isBound()); |
| 3072 intptr_t position = Buffer.size(); | 3077 intptr_t position = Buffer.size(); |
| 3073 emitUint8(0); | 3078 emitUint8(0); |
| 3074 if (!getPreliminary()) | 3079 if (!getPreliminary()) |
| 3075 label->NearLinkTo(position); | 3080 label->nearLinkTo(position); |
| 3076 } | 3081 } |
| 3077 | 3082 |
| 3078 template <class Machine> | 3083 template <class Machine> |
| 3079 void AssemblerX86Base<Machine>::emitGenericShift( | 3084 void AssemblerX86Base<Machine>::emitGenericShift( |
| 3080 int rm, Type Ty, typename Traits::GPRRegister reg, const Immediate &imm) { | 3085 int rm, Type Ty, typename Traits::GPRRegister reg, const Immediate &imm) { |
| 3081 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 3086 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 3082 assert(imm.is_int8()); | 3087 assert(imm.is_int8()); |
| 3083 if (Ty == IceType_i16) | 3088 if (Ty == IceType_i16) |
| 3084 emitOperandSizeOverride(); | 3089 emitOperandSizeOverride(); |
| 3085 if (imm.value() == 1) { | 3090 if (imm.value() == 1) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3100 assert(shifter == Traits::Encoded_Reg_Counter); | 3105 assert(shifter == Traits::Encoded_Reg_Counter); |
| 3101 (void)shifter; | 3106 (void)shifter; |
| 3102 if (Ty == IceType_i16) | 3107 if (Ty == IceType_i16) |
| 3103 emitOperandSizeOverride(); | 3108 emitOperandSizeOverride(); |
| 3104 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); | 3109 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); |
| 3105 emitOperand(rm, operand); | 3110 emitOperand(rm, operand); |
| 3106 } | 3111 } |
| 3107 | 3112 |
| 3108 } // end of namespace X86Internal | 3113 } // end of namespace X86Internal |
| 3109 } // end of namespace Ice | 3114 } // end of namespace Ice |
| OLD | NEW |