| 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 emitRexB(RexTypeIrrelevant, reg); | 99 emitRexB(RexTypeIrrelevant, reg); |
| 100 emitUint8(0xFF); | 100 emitUint8(0xFF); |
| 101 emitRegisterOperand(2, gprEncoding(reg)); | 101 emitRegisterOperand(2, gprEncoding(reg)); |
| (...skipping 2840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2942 template <class Machine> void AssemblerX86Base<Machine>::ud2() { | 2942 template <class Machine> void AssemblerX86Base<Machine>::ud2() { |
| 2943 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2943 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2944 emitUint8(0x0F); | 2944 emitUint8(0x0F); |
| 2945 emitUint8(0x0B); | 2945 emitUint8(0x0B); |
| 2946 } | 2946 } |
| 2947 | 2947 |
| 2948 template <class Machine> | 2948 template <class Machine> |
| 2949 void AssemblerX86Base<Machine>::j(typename Traits::Cond::BrCond condition, | 2949 void AssemblerX86Base<Machine>::j(typename Traits::Cond::BrCond condition, |
| 2950 Label *label, bool near) { | 2950 Label *label, bool near) { |
| 2951 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2951 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2952 if (label->IsBound()) { | 2952 if (label->isBound()) { |
| 2953 static const int kShortSize = 2; | 2953 static const int kShortSize = 2; |
| 2954 static const int kLongSize = 6; | 2954 static const int kLongSize = 6; |
| 2955 intptr_t offset = label->Position() - Buffer.size(); | 2955 intptr_t offset = label->getPosition() - Buffer.size(); |
| 2956 assert(offset <= 0); | 2956 assert(offset <= 0); |
| 2957 if (Utils::IsInt(8, offset - kShortSize)) { | 2957 if (Utils::IsInt(8, offset - kShortSize)) { |
| 2958 // TODO(stichnot): Here and in jmp(), we may need to be more | 2958 // TODO(stichnot): Here and in jmp(), we may need to be more |
| 2959 // conservative about the backward branch distance if the branch | 2959 // conservative about the backward branch distance if the branch |
| 2960 // instruction is within a bundle_lock sequence, because the | 2960 // instruction is within a bundle_lock sequence, because the |
| 2961 // distance may increase when padding is added. This isn't an | 2961 // distance may increase when padding is added. This isn't an |
| 2962 // issue for branches outside a bundle_lock, because if padding | 2962 // issue for branches outside a bundle_lock, because if padding |
| 2963 // is added, the retry may change it to a long backward branch | 2963 // is added, the retry may change it to a long backward branch |
| 2964 // without affecting any of the bookkeeping. | 2964 // without affecting any of the bookkeeping. |
| 2965 emitUint8(0x70 + condition); | 2965 emitUint8(0x70 + condition); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2993 void AssemblerX86Base<Machine>::jmp(typename Traits::GPRRegister reg) { | 2993 void AssemblerX86Base<Machine>::jmp(typename Traits::GPRRegister reg) { |
| 2994 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2994 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2995 emitRexB(RexTypeIrrelevant, reg); | 2995 emitRexB(RexTypeIrrelevant, reg); |
| 2996 emitUint8(0xFF); | 2996 emitUint8(0xFF); |
| 2997 emitRegisterOperand(4, gprEncoding(reg)); | 2997 emitRegisterOperand(4, gprEncoding(reg)); |
| 2998 } | 2998 } |
| 2999 | 2999 |
| 3000 template <class Machine> | 3000 template <class Machine> |
| 3001 void AssemblerX86Base<Machine>::jmp(Label *label, bool near) { | 3001 void AssemblerX86Base<Machine>::jmp(Label *label, bool near) { |
| 3002 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 3002 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 3003 if (label->IsBound()) { | 3003 if (label->isBound()) { |
| 3004 static const int kShortSize = 2; | 3004 static const int kShortSize = 2; |
| 3005 static const int kLongSize = 5; | 3005 static const int kLongSize = 5; |
| 3006 intptr_t offset = label->Position() - Buffer.size(); | 3006 intptr_t offset = label->getPosition() - Buffer.size(); |
| 3007 assert(offset <= 0); | 3007 assert(offset <= 0); |
| 3008 if (Utils::IsInt(8, offset - kShortSize)) { | 3008 if (Utils::IsInt(8, offset - kShortSize)) { |
| 3009 emitUint8(0xEB); | 3009 emitUint8(0xEB); |
| 3010 emitUint8((offset - kShortSize) & 0xFF); | 3010 emitUint8((offset - kShortSize) & 0xFF); |
| 3011 } else { | 3011 } else { |
| 3012 emitUint8(0xE9); | 3012 emitUint8(0xE9); |
| 3013 emitInt32(offset - kLongSize); | 3013 emitInt32(offset - kLongSize); |
| 3014 } | 3014 } |
| 3015 } else if (near) { | 3015 } else if (near) { |
| 3016 emitUint8(0xEB); | 3016 emitUint8(0xEB); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3126 bytes_needed -= MAX_NOP_SIZE; | 3126 bytes_needed -= MAX_NOP_SIZE; |
| 3127 } | 3127 } |
| 3128 if (bytes_needed) { | 3128 if (bytes_needed) { |
| 3129 nop(bytes_needed); | 3129 nop(bytes_needed); |
| 3130 } | 3130 } |
| 3131 assert(((offset + Buffer.getPosition()) & (alignment - 1)) == 0); | 3131 assert(((offset + Buffer.getPosition()) & (alignment - 1)) == 0); |
| 3132 } | 3132 } |
| 3133 | 3133 |
| 3134 template <class Machine> void AssemblerX86Base<Machine>::bind(Label *label) { | 3134 template <class Machine> void AssemblerX86Base<Machine>::bind(Label *label) { |
| 3135 intptr_t bound = Buffer.size(); | 3135 intptr_t bound = Buffer.size(); |
| 3136 assert(!label->IsBound()); // Labels can only be bound once. | 3136 assert(!label->isBound()); // Labels can only be bound once. |
| 3137 while (label->IsLinked()) { | 3137 while (label->isLinked()) { |
| 3138 intptr_t position = label->LinkPosition(); | 3138 intptr_t position = label->getLinkPosition(); |
| 3139 intptr_t next = Buffer.load<int32_t>(position); | 3139 intptr_t next = Buffer.load<int32_t>(position); |
| 3140 Buffer.store<int32_t>(position, bound - (position + 4)); | 3140 Buffer.store<int32_t>(position, bound - (position + 4)); |
| 3141 label->position_ = next; | 3141 label->Position = next; |
| 3142 } | 3142 } |
| 3143 while (label->HasNear()) { | 3143 while (label->hasNear()) { |
| 3144 intptr_t position = label->NearPosition(); | 3144 intptr_t position = label->getNearPosition(); |
| 3145 intptr_t offset = bound - (position + 1); | 3145 intptr_t offset = bound - (position + 1); |
| 3146 assert(Utils::IsInt(8, offset)); | 3146 assert(Utils::IsInt(8, offset)); |
| 3147 Buffer.store<int8_t>(position, offset); | 3147 Buffer.store<int8_t>(position, offset); |
| 3148 } | 3148 } |
| 3149 label->BindTo(bound); | 3149 label->bindTo(bound); |
| 3150 } | 3150 } |
| 3151 | 3151 |
| 3152 template <class Machine> | 3152 template <class Machine> |
| 3153 void AssemblerX86Base<Machine>::emitOperand( | 3153 void AssemblerX86Base<Machine>::emitOperand( |
| 3154 int rm, const typename Traits::Operand &operand) { | 3154 int rm, const typename Traits::Operand &operand) { |
| 3155 assert(rm >= 0 && rm < 8); | 3155 assert(rm >= 0 && rm < 8); |
| 3156 const intptr_t length = operand.length_; | 3156 const intptr_t length = operand.length_; |
| 3157 assert(length > 0); | 3157 assert(length > 0); |
| 3158 // Emit the ModRM byte updated with the given RM value. | 3158 // Emit the ModRM byte updated with the given RM value. |
| 3159 assert((operand.encoding_[0] & 0x38) == 0); | 3159 assert((operand.encoding_[0] & 0x38) == 0); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3215 } else { | 3215 } else { |
| 3216 emitUint8(0x81); | 3216 emitUint8(0x81); |
| 3217 emitOperand(rm, operand); | 3217 emitOperand(rm, operand); |
| 3218 emitImmediate(Ty, immediate); | 3218 emitImmediate(Ty, immediate); |
| 3219 } | 3219 } |
| 3220 } | 3220 } |
| 3221 | 3221 |
| 3222 template <class Machine> | 3222 template <class Machine> |
| 3223 void AssemblerX86Base<Machine>::emitLabel(Label *label, | 3223 void AssemblerX86Base<Machine>::emitLabel(Label *label, |
| 3224 intptr_t instruction_size) { | 3224 intptr_t instruction_size) { |
| 3225 if (label->IsBound()) { | 3225 if (label->isBound()) { |
| 3226 intptr_t offset = label->Position() - Buffer.size(); | 3226 intptr_t offset = label->getPosition() - Buffer.size(); |
| 3227 assert(offset <= 0); | 3227 assert(offset <= 0); |
| 3228 emitInt32(offset - instruction_size); | 3228 emitInt32(offset - instruction_size); |
| 3229 } else { | 3229 } else { |
| 3230 emitLabelLink(label); | 3230 emitLabelLink(label); |
| 3231 } | 3231 } |
| 3232 } | 3232 } |
| 3233 | 3233 |
| 3234 template <class Machine> | 3234 template <class Machine> |
| 3235 void AssemblerX86Base<Machine>::emitLabelLink(Label *Label) { | 3235 void AssemblerX86Base<Machine>::emitLabelLink(Label *Label) { |
| 3236 assert(!Label->IsBound()); | 3236 assert(!Label->isBound()); |
| 3237 intptr_t Position = Buffer.size(); | 3237 intptr_t Position = Buffer.size(); |
| 3238 emitInt32(Label->position_); | 3238 emitInt32(Label->Position); |
| 3239 if (!getPreliminary()) | 3239 if (!getPreliminary()) |
| 3240 Label->LinkTo(Position); | 3240 Label->linkTo(Position); |
| 3241 } | 3241 } |
| 3242 | 3242 |
| 3243 template <class Machine> | 3243 template <class Machine> |
| 3244 void AssemblerX86Base<Machine>::emitNearLabelLink(Label *label) { | 3244 void AssemblerX86Base<Machine>::emitNearLabelLink(Label *label) { |
| 3245 assert(!label->IsBound()); | 3245 assert(!label->isBound()); |
| 3246 intptr_t position = Buffer.size(); | 3246 intptr_t position = Buffer.size(); |
| 3247 emitUint8(0); | 3247 emitUint8(0); |
| 3248 if (!getPreliminary()) | 3248 if (!getPreliminary()) |
| 3249 label->NearLinkTo(position); | 3249 label->nearLinkTo(position); |
| 3250 } | 3250 } |
| 3251 | 3251 |
| 3252 template <class Machine> | 3252 template <class Machine> |
| 3253 void AssemblerX86Base<Machine>::emitGenericShift( | 3253 void AssemblerX86Base<Machine>::emitGenericShift( |
| 3254 int rm, Type Ty, typename Traits::GPRRegister reg, const Immediate &imm) { | 3254 int rm, Type Ty, typename Traits::GPRRegister reg, const Immediate &imm) { |
| 3255 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 3255 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 3256 assert(imm.is_int8()); | 3256 assert(imm.is_int8()); |
| 3257 if (Ty == IceType_i16) | 3257 if (Ty == IceType_i16) |
| 3258 emitOperandSizeOverride(); | 3258 emitOperandSizeOverride(); |
| 3259 emitRexB(Ty, reg); | 3259 emitRexB(Ty, reg); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3276 (void)shifter; | 3276 (void)shifter; |
| 3277 if (Ty == IceType_i16) | 3277 if (Ty == IceType_i16) |
| 3278 emitOperandSizeOverride(); | 3278 emitOperandSizeOverride(); |
| 3279 emitRexB(Ty, operand.rm()); | 3279 emitRexB(Ty, operand.rm()); |
| 3280 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); | 3280 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); |
| 3281 emitOperand(rm, operand); | 3281 emitOperand(rm, operand); |
| 3282 } | 3282 } |
| 3283 | 3283 |
| 3284 } // end of namespace X86Internal | 3284 } // end of namespace X86Internal |
| 3285 } // end of namespace Ice | 3285 } // end of namespace Ice |
| OLD | NEW |