OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 // | 4 // |
5 // Modified by the Subzero authors. | 5 // Modified by the Subzero authors. |
6 // | 6 // |
7 //===- subzero/src/assembler_ia32.h - Assembler for x86-32 ----------------===// | 7 //===- subzero/src/assembler_ia32.h - Assembler for x86-32 ----------------===// |
Jim Stichnoth
2014/10/16 18:19:53
Add the emacs c++-mode marker here?
*- C++ -*
jvoung (off chromium)
2014/10/16 19:02:37
Done. I think technically it should be on the firs
| |
8 // | 8 // |
9 // The Subzero Code Generator | 9 // The Subzero Code Generator |
10 // | 10 // |
11 // This file is distributed under the University of Illinois Open Source | 11 // This file is distributed under the University of Illinois Open Source |
12 // License. See LICENSE.TXT for details. | 12 // License. See LICENSE.TXT for details. |
13 // | 13 // |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 // | 15 // |
16 // This file implements the Assembler class for x86-32. | 16 // This file implements the Assembler class for x86-32. |
17 // | 17 // |
(...skipping 20 matching lines...) Expand all Loading... | |
38 using RegX8632::ByteRegister; | 38 using RegX8632::ByteRegister; |
39 using RegX8632::X87STRegister; | 39 using RegX8632::X87STRegister; |
40 | 40 |
41 namespace x86 { | 41 namespace x86 { |
42 | 42 |
43 const int MAX_NOP_SIZE = 8; | 43 const int MAX_NOP_SIZE = 8; |
44 | 44 |
45 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; | 45 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; |
46 | 46 |
47 class DisplacementRelocation : public AssemblerFixup { | 47 class DisplacementRelocation : public AssemblerFixup { |
48 DisplacementRelocation(const DisplacementRelocation &) = delete; | |
49 DisplacementRelocation &operator=(const DisplacementRelocation &) = delete; | |
50 | |
48 public: | 51 public: |
49 static DisplacementRelocation *create(Assembler *Asm, FixupKind Kind, | 52 static DisplacementRelocation *create(Assembler *Asm, FixupKind Kind, |
50 const ConstantRelocatable *Sym) { | 53 const ConstantRelocatable *Sym) { |
51 return new (Asm->Allocate<DisplacementRelocation>()) | 54 return new (Asm->Allocate<DisplacementRelocation>()) |
52 DisplacementRelocation(Kind, Sym); | 55 DisplacementRelocation(Kind, Sym); |
53 } | 56 } |
54 | 57 |
55 void Process(const MemoryRegion ®ion, intptr_t position) override { | 58 void Process(const MemoryRegion ®ion, intptr_t position) override { |
56 (void)region; | 59 (void)region; |
57 (void)position; | 60 (void)position; |
58 llvm_unreachable("We might not be using this Process() method later."); | 61 llvm_unreachable("We might not be using this Process() method later."); |
59 } | 62 } |
60 | 63 |
61 private: | 64 private: |
62 DisplacementRelocation(FixupKind Kind, const ConstantRelocatable *Sym) | 65 DisplacementRelocation(FixupKind Kind, const ConstantRelocatable *Sym) |
63 : AssemblerFixup(Kind, Sym) {} | 66 : AssemblerFixup(Kind, Sym) {} |
64 DisplacementRelocation(const DisplacementRelocation &) = delete; | |
65 DisplacementRelocation &operator=(const DisplacementRelocation &) = delete; | |
66 }; | 67 }; |
67 | 68 |
68 class Immediate { | 69 class Immediate { |
70 Immediate(const Immediate &) = delete; | |
71 Immediate &operator=(const Immediate &) = delete; | |
72 | |
69 public: | 73 public: |
70 explicit Immediate(int32_t value) : value_(value), fixup_(NULL) {} | 74 explicit Immediate(int32_t value) : value_(value), fixup_(NULL) {} |
71 | 75 |
72 explicit Immediate(const Immediate &other) | |
73 : value_(other.value_), fixup_(other.fixup_) {} | |
74 | |
75 explicit Immediate(AssemblerFixup *fixup) | 76 explicit Immediate(AssemblerFixup *fixup) |
76 : value_(fixup->value()->getOffset()), fixup_(fixup) { | 77 : value_(fixup->value()->getOffset()), fixup_(fixup) { |
77 // Use the Offset in the "value" for now. If the symbol is part of | 78 // Use the Offset in the "value" for now. If the symbol is part of |
78 // ".bss", then the relocation's symbol will be plain ".bss" and | 79 // ".bss", then the relocation's symbol will be plain ".bss" and |
79 // the value will need to be adjusted further to be sym's | 80 // the value will need to be adjusted further to be sym's |
80 // bss offset + Offset. | 81 // bss offset + Offset. |
81 } | 82 } |
82 | 83 |
83 int32_t value() const { return value_; } | 84 int32_t value() const { return value_; } |
84 AssemblerFixup *fixup() const { return fixup_; } | 85 AssemblerFixup *fixup() const { return fixup_; } |
85 | 86 |
86 bool is_int8() const { | 87 bool is_int8() const { |
87 // We currently only allow 32-bit fixups, and they usually have value = 0, | 88 // We currently only allow 32-bit fixups, and they usually have value = 0, |
88 // so if fixup_ != NULL, it shouldn't be classified as int8/16. | 89 // so if fixup_ != NULL, it shouldn't be classified as int8/16. |
89 return fixup_ == NULL && Utils::IsInt(8, value_); | 90 return fixup_ == NULL && Utils::IsInt(8, value_); |
90 } | 91 } |
91 bool is_uint8() const { return fixup_ == NULL && Utils::IsUint(8, value_); } | 92 bool is_uint8() const { return fixup_ == NULL && Utils::IsUint(8, value_); } |
92 bool is_uint16() const { return fixup_ == NULL && Utils::IsUint(16, value_); } | 93 bool is_uint16() const { return fixup_ == NULL && Utils::IsUint(16, value_); } |
93 | 94 |
94 private: | 95 private: |
95 const int32_t value_; | 96 const int32_t value_; |
96 AssemblerFixup *fixup_; | 97 AssemblerFixup *fixup_; |
97 }; | 98 }; |
98 | 99 |
99 class Operand { | 100 class Operand { |
100 public: | 101 public: |
102 Operand(const Operand &other) : length_(other.length_), fixup_(other.fixup_) { | |
Karl
2014/10/16 17:23:26
Jim suggested doing
// Operand(const Operand
Jim Stichnoth
2014/10/16 18:19:53
True, but here we're explicitly not using the defa
jvoung (off chromium)
2014/10/16 19:02:37
Right, it doesn't quite need to memmove everything
| |
103 memmove(&encoding_[0], &other.encoding_[0], other.length_); | |
104 } | |
105 | |
106 Operand &operator=(const Operand &other) { | |
107 length_ = other.length_; | |
108 fixup_ = other.fixup_; | |
109 memmove(&encoding_[0], &other.encoding_[0], other.length_); | |
110 return *this; | |
111 } | |
112 | |
101 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; } | 113 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; } |
102 | 114 |
103 GPRRegister rm() const { | 115 GPRRegister rm() const { |
104 return static_cast<GPRRegister>(encoding_at(0) & 7); | 116 return static_cast<GPRRegister>(encoding_at(0) & 7); |
105 } | 117 } |
106 | 118 |
107 ScaleFactor scale() const { | 119 ScaleFactor scale() const { |
108 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); | 120 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); |
109 } | 121 } |
110 | 122 |
(...skipping 10 matching lines...) Expand all Loading... | |
121 return static_cast<int8_t>(encoding_[length_ - 1]); | 133 return static_cast<int8_t>(encoding_[length_ - 1]); |
122 } | 134 } |
123 | 135 |
124 int32_t disp32() const { | 136 int32_t disp32() const { |
125 assert(length_ >= 5); | 137 assert(length_ >= 5); |
126 return bit_copy<int32_t>(encoding_[length_ - 4]); | 138 return bit_copy<int32_t>(encoding_[length_ - 4]); |
127 } | 139 } |
128 | 140 |
129 AssemblerFixup *fixup() const { return fixup_; } | 141 AssemblerFixup *fixup() const { return fixup_; } |
130 | 142 |
131 Operand(const Operand &other) : length_(other.length_), fixup_(other.fixup_) { | |
132 memmove(&encoding_[0], &other.encoding_[0], other.length_); | |
133 } | |
134 | |
135 Operand &operator=(const Operand &other) { | |
136 length_ = other.length_; | |
137 fixup_ = other.fixup_; | |
138 memmove(&encoding_[0], &other.encoding_[0], other.length_); | |
139 return *this; | |
140 } | |
141 | |
142 protected: | 143 protected: |
143 Operand() : length_(0), fixup_(NULL) {} // Needed by subclass Address. | 144 Operand() : length_(0), fixup_(NULL) {} // Needed by subclass Address. |
144 | 145 |
145 void SetModRM(int mod, GPRRegister rm) { | 146 void SetModRM(int mod, GPRRegister rm) { |
146 assert((mod & ~3) == 0); | 147 assert((mod & ~3) == 0); |
147 encoding_[0] = (mod << 6) | rm; | 148 encoding_[0] = (mod << 6) | rm; |
148 length_ = 1; | 149 length_ = 1; |
149 } | 150 } |
150 | 151 |
151 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { | 152 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
187 bool IsRegister(GPRRegister reg) const { | 188 bool IsRegister(GPRRegister reg) const { |
188 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. | 189 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. |
189 && ((encoding_[0] & 0x07) == reg); // Register codes match. | 190 && ((encoding_[0] & 0x07) == reg); // Register codes match. |
190 } | 191 } |
191 | 192 |
192 friend class AssemblerX86; | 193 friend class AssemblerX86; |
193 }; | 194 }; |
194 | 195 |
195 class Address : public Operand { | 196 class Address : public Operand { |
196 public: | 197 public: |
198 Address(const Address &other) : Operand(other) {} | |
199 | |
200 Address &operator=(const Address &other) { | |
201 Operand::operator=(other); | |
202 return *this; | |
203 } | |
204 | |
197 Address(GPRRegister base, int32_t disp) { | 205 Address(GPRRegister base, int32_t disp) { |
198 if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) { | 206 if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) { |
199 SetModRM(0, base); | 207 SetModRM(0, base); |
200 if (base == RegX8632::Encoded_Reg_esp) | 208 if (base == RegX8632::Encoded_Reg_esp) |
201 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); | 209 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); |
202 } else if (Utils::IsInt(8, disp)) { | 210 } else if (Utils::IsInt(8, disp)) { |
203 SetModRM(1, base); | 211 SetModRM(1, base); |
204 if (base == RegX8632::Encoded_Reg_esp) | 212 if (base == RegX8632::Encoded_Reg_esp) |
205 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); | 213 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); |
206 SetDisp8(disp); | 214 SetDisp8(disp); |
(...skipping 22 matching lines...) Expand all Loading... | |
229 SetModRM(1, RegX8632::Encoded_Reg_esp); | 237 SetModRM(1, RegX8632::Encoded_Reg_esp); |
230 SetSIB(scale, index, base); | 238 SetSIB(scale, index, base); |
231 SetDisp8(disp); | 239 SetDisp8(disp); |
232 } else { | 240 } else { |
233 SetModRM(2, RegX8632::Encoded_Reg_esp); | 241 SetModRM(2, RegX8632::Encoded_Reg_esp); |
234 SetSIB(scale, index, base); | 242 SetSIB(scale, index, base); |
235 SetDisp32(disp); | 243 SetDisp32(disp); |
236 } | 244 } |
237 } | 245 } |
238 | 246 |
239 Address(const Address &other) : Operand(other) {} | |
240 | |
241 Address &operator=(const Address &other) { | |
242 Operand::operator=(other); | |
243 return *this; | |
244 } | |
245 | |
246 static Address Absolute(const uintptr_t addr) { | 247 static Address Absolute(const uintptr_t addr) { |
247 Address result; | 248 Address result; |
248 result.SetModRM(0, RegX8632::Encoded_Reg_ebp); | 249 result.SetModRM(0, RegX8632::Encoded_Reg_ebp); |
249 result.SetDisp32(addr); | 250 result.SetDisp32(addr); |
250 return result; | 251 return result; |
251 } | 252 } |
252 | 253 |
253 static Address Absolute(AssemblerFixup *fixup) { | 254 static Address Absolute(AssemblerFixup *fixup) { |
254 Address result; | 255 Address result; |
255 result.SetModRM(0, RegX8632::Encoded_Reg_ebp); | 256 result.SetModRM(0, RegX8632::Encoded_Reg_ebp); |
256 // Use the Offset in the displacement for now. If the symbol is part of | 257 // Use the Offset in the displacement for now. If the symbol is part of |
257 // ".bss", then the relocation's symbol will be plain .bss and the | 258 // ".bss", then the relocation's symbol will be plain .bss and the |
258 // displacement will need to be adjusted further to be sym's | 259 // displacement will need to be adjusted further to be sym's |
259 // bss offset + Offset. | 260 // bss offset + Offset. |
260 result.SetDisp32(fixup->value()->getOffset()); | 261 result.SetDisp32(fixup->value()->getOffset()); |
261 result.SetFixup(fixup); | 262 result.SetFixup(fixup); |
262 return result; | 263 return result; |
263 } | 264 } |
264 | 265 |
265 static Address ofConstPool(GlobalContext *Ctx, Assembler *Asm, | 266 static Address ofConstPool(GlobalContext *Ctx, Assembler *Asm, |
266 const Constant *Imm); | 267 const Constant *Imm); |
267 | 268 |
268 private: | 269 private: |
269 Address() {} // Needed by Address::Absolute. | 270 Address() {} // Needed by Address::Absolute. |
270 }; | 271 }; |
271 | 272 |
272 class Label { | 273 class Label { |
274 Label(const Label &) = delete; | |
275 Label &operator=(const Label &) = delete; | |
276 | |
273 public: | 277 public: |
274 Label() : position_(0), num_unresolved_(0) { | 278 Label() : position_(0), num_unresolved_(0) { |
275 #ifdef DEBUG | 279 #ifdef DEBUG |
276 for (int i = 0; i < kMaxUnresolvedBranches; i++) { | 280 for (int i = 0; i < kMaxUnresolvedBranches; i++) { |
277 unresolved_near_positions_[i] = -1; | 281 unresolved_near_positions_[i] = -1; |
278 } | 282 } |
279 #endif // DEBUG | 283 #endif // DEBUG |
280 } | 284 } |
281 | 285 |
282 ~Label() { | 286 ~Label() { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 unresolved_near_positions_[num_unresolved_++] = position; | 343 unresolved_near_positions_[num_unresolved_++] = position; |
340 } | 344 } |
341 | 345 |
342 static const int kMaxUnresolvedBranches = 20; | 346 static const int kMaxUnresolvedBranches = 20; |
343 | 347 |
344 intptr_t position_; | 348 intptr_t position_; |
345 intptr_t num_unresolved_; | 349 intptr_t num_unresolved_; |
346 intptr_t unresolved_near_positions_[kMaxUnresolvedBranches]; | 350 intptr_t unresolved_near_positions_[kMaxUnresolvedBranches]; |
347 | 351 |
348 friend class AssemblerX86; | 352 friend class AssemblerX86; |
349 Label(const Label &) = delete; | |
350 Label &operator=(const Label &) = delete; | |
351 }; | 353 }; |
352 | 354 |
353 class AssemblerX86 : public Assembler { | 355 class AssemblerX86 : public Assembler { |
356 AssemblerX86(const AssemblerX86 &) = delete; | |
357 AssemblerX86 &operator=(const AssemblerX86 &) = delete; | |
358 | |
354 public: | 359 public: |
355 explicit AssemblerX86(bool use_far_branches = false) : buffer_(*this) { | 360 explicit AssemblerX86(bool use_far_branches = false) : buffer_(*this) { |
356 // This mode is only needed and implemented for MIPS and ARM. | 361 // This mode is only needed and implemented for MIPS and ARM. |
357 assert(!use_far_branches); | 362 assert(!use_far_branches); |
358 (void)use_far_branches; | 363 (void)use_far_branches; |
359 } | 364 } |
360 ~AssemblerX86() {} | 365 ~AssemblerX86() {} |
361 | 366 |
362 static const bool kNearJump = true; | 367 static const bool kNearJump = true; |
363 static const bool kFarJump = false; | 368 static const bool kFarJump = false; |
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
836 const Immediate &immediate); | 841 const Immediate &immediate); |
837 void EmitLabel(Label *label, intptr_t instruction_size); | 842 void EmitLabel(Label *label, intptr_t instruction_size); |
838 void EmitLabelLink(Label *label); | 843 void EmitLabelLink(Label *label); |
839 void EmitNearLabelLink(Label *label); | 844 void EmitNearLabelLink(Label *label); |
840 | 845 |
841 void EmitGenericShift(int rm, Type Ty, GPRRegister reg, const Immediate &imm); | 846 void EmitGenericShift(int rm, Type Ty, GPRRegister reg, const Immediate &imm); |
842 void EmitGenericShift(int rm, Type Ty, const Operand &operand, | 847 void EmitGenericShift(int rm, Type Ty, const Operand &operand, |
843 GPRRegister shifter); | 848 GPRRegister shifter); |
844 | 849 |
845 AssemblerBuffer buffer_; | 850 AssemblerBuffer buffer_; |
846 | |
847 AssemblerX86(const AssemblerX86 &) = delete; | |
848 AssemblerX86 &operator=(const AssemblerX86 &) = delete; | |
849 }; | 851 }; |
850 | 852 |
851 inline void AssemblerX86::EmitUint8(uint8_t value) { | 853 inline void AssemblerX86::EmitUint8(uint8_t value) { |
852 buffer_.Emit<uint8_t>(value); | 854 buffer_.Emit<uint8_t>(value); |
853 } | 855 } |
854 | 856 |
855 inline void AssemblerX86::EmitInt16(int16_t value) { | 857 inline void AssemblerX86::EmitInt16(int16_t value) { |
856 buffer_.Emit<int16_t>(value); | 858 buffer_.Emit<int16_t>(value); |
857 } | 859 } |
858 | 860 |
(...skipping 13 matching lines...) Expand all Loading... | |
872 inline void AssemblerX86::EmitFixup(AssemblerFixup *fixup) { | 874 inline void AssemblerX86::EmitFixup(AssemblerFixup *fixup) { |
873 buffer_.EmitFixup(fixup); | 875 buffer_.EmitFixup(fixup); |
874 } | 876 } |
875 | 877 |
876 inline void AssemblerX86::EmitOperandSizeOverride() { EmitUint8(0x66); } | 878 inline void AssemblerX86::EmitOperandSizeOverride() { EmitUint8(0x66); } |
877 | 879 |
878 } // end of namespace x86 | 880 } // end of namespace x86 |
879 } // end of namespace Ice | 881 } // end of namespace Ice |
880 | 882 |
881 #endif // SUBZERO_SRC_ASSEMBLER_IA32_H_ | 883 #endif // SUBZERO_SRC_ASSEMBLER_IA32_H_ |
OLD | NEW |