Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: src/IceTargetLoweringX8632Traits.h

Issue 1216033004: Move X8632-specific Assembler stuff to Machine Traits. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceTargetLoweringX8632.cpp ('k') | src/IceTargetLoweringX86Base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- C++ -*-=//
2 //
3 // The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the X8632 Target Lowering Traits.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
15 #define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
16
17 #include "IceAssembler.h"
18 #include "IceConditionCodesX8632.h"
19 #include "IceDefs.h"
20 #include "IceInst.h"
21 #include "IceInstX8632.def"
22 #include "IceRegistersX8632.h"
23 #include "IceTargetLoweringX8632.def"
24
25 namespace Ice {
26
27 class TargetX8632;
28
29 namespace X86Internal {
30
31 template <class Machine> struct MachineTraits;
32
33 template <> struct MachineTraits<TargetX8632> {
34 //----------------------------------------------------------------------------
35 // ______ ______ __ __
36 // /\ __ \/\ ___\/\ "-./ \
37 // \ \ __ \ \___ \ \ \-./\ \
38 // \ \_\ \_\/\_____\ \_\ \ \_\
39 // \/_/\/_/\/_____/\/_/ \/_/
40 //
41 //----------------------------------------------------------------------------
42 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
43
44 using GPRRegister = ::Ice::RegX8632::GPRRegister;
45 using XmmRegister = ::Ice::RegX8632::XmmRegister;
46 using ByteRegister = ::Ice::RegX8632::ByteRegister;
47 using X87STRegister = ::Ice::RegX8632::X87STRegister;
48
49 using Cond = ::Ice::CondX86;
50
51 using RegisterSet = ::Ice::RegX8632;
52 static const GPRRegister Encoded_Reg_Accumulator = RegX8632::Encoded_Reg_eax;
53 static const GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx;
54 static const FixupKind PcRelFixup = llvm::ELF::R_386_PC32;
55
56 class Operand {
57 public:
58 Operand(const Operand &other)
59 : length_(other.length_), fixup_(other.fixup_) {
60 memmove(&encoding_[0], &other.encoding_[0], other.length_);
61 }
62
63 Operand &operator=(const Operand &other) {
64 length_ = other.length_;
65 fixup_ = other.fixup_;
66 memmove(&encoding_[0], &other.encoding_[0], other.length_);
67 return *this;
68 }
69
70 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
71
72 GPRRegister rm() const {
73 return static_cast<GPRRegister>(encoding_at(0) & 7);
74 }
75
76 ScaleFactor scale() const {
77 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
78 }
79
80 GPRRegister index() const {
81 return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
82 }
83
84 GPRRegister base() const {
85 return static_cast<GPRRegister>(encoding_at(1) & 7);
86 }
87
88 int8_t disp8() const {
89 assert(length_ >= 2);
90 return static_cast<int8_t>(encoding_[length_ - 1]);
91 }
92
93 int32_t disp32() const {
94 assert(length_ >= 5);
95 return bit_copy<int32_t>(encoding_[length_ - 4]);
96 }
97
98 AssemblerFixup *fixup() const { return fixup_; }
99
100 protected:
101 Operand() : length_(0), fixup_(nullptr) {} // Needed by subclass Address.
102
103 void SetModRM(int mod, GPRRegister rm) {
104 assert((mod & ~3) == 0);
105 encoding_[0] = (mod << 6) | rm;
106 length_ = 1;
107 }
108
109 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
110 assert(length_ == 1);
111 assert((scale & ~3) == 0);
112 encoding_[1] = (scale << 6) | (index << 3) | base;
113 length_ = 2;
114 }
115
116 void SetDisp8(int8_t disp) {
117 assert(length_ == 1 || length_ == 2);
118 encoding_[length_++] = static_cast<uint8_t>(disp);
119 }
120
121 void SetDisp32(int32_t disp) {
122 assert(length_ == 1 || length_ == 2);
123 intptr_t disp_size = sizeof(disp);
124 memmove(&encoding_[length_], &disp, disp_size);
125 length_ += disp_size;
126 }
127
128 void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
129
130 private:
131 uint8_t length_;
132 uint8_t encoding_[6];
133 AssemblerFixup *fixup_;
134
135 explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
136
137 // Get the operand encoding byte at the given index.
138 uint8_t encoding_at(intptr_t index) const {
139 assert(index >= 0 && index < length_);
140 return encoding_[index];
141 }
142
143 // Returns whether or not this operand is really the given register in
144 // disguise. Used from the assembler to generate better encodings.
145 bool IsRegister(GPRRegister reg) const {
146 return ((encoding_[0] & 0xF8) ==
147 0xC0) // Addressing mode is register only.
148 &&
149 ((encoding_[0] & 0x07) == reg); // Register codes match.
150 }
151
152 template <class> friend class AssemblerX86Base;
153 };
154
155 class Address : public Operand {
156 Address() = delete;
157
158 public:
159 Address(const Address &other) : Operand(other) {}
160
161 Address &operator=(const Address &other) {
162 Operand::operator=(other);
163 return *this;
164 }
165
166 Address(GPRRegister base, int32_t disp) {
167 if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) {
168 SetModRM(0, base);
169 if (base == RegX8632::Encoded_Reg_esp)
170 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
171 } else if (Utils::IsInt(8, disp)) {
172 SetModRM(1, base);
173 if (base == RegX8632::Encoded_Reg_esp)
174 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
175 SetDisp8(disp);
176 } else {
177 SetModRM(2, base);
178 if (base == RegX8632::Encoded_Reg_esp)
179 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
180 SetDisp32(disp);
181 }
182 }
183
184 Address(GPRRegister index, ScaleFactor scale, int32_t disp) {
185 assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
186 SetModRM(0, RegX8632::Encoded_Reg_esp);
187 SetSIB(scale, index, RegX8632::Encoded_Reg_ebp);
188 SetDisp32(disp);
189 }
190
191 Address(GPRRegister base, GPRRegister index, ScaleFactor scale,
192 int32_t disp) {
193 assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
194 if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) {
195 SetModRM(0, RegX8632::Encoded_Reg_esp);
196 SetSIB(scale, index, base);
197 } else if (Utils::IsInt(8, disp)) {
198 SetModRM(1, RegX8632::Encoded_Reg_esp);
199 SetSIB(scale, index, base);
200 SetDisp8(disp);
201 } else {
202 SetModRM(2, RegX8632::Encoded_Reg_esp);
203 SetSIB(scale, index, base);
204 SetDisp32(disp);
205 }
206 }
207
208 // AbsoluteTag is a special tag used by clients to create an absolute
209 // Address.
210 enum AbsoluteTag { ABSOLUTE };
211
212 Address(AbsoluteTag, const uintptr_t Addr) {
213 SetModRM(0, RegX8632::Encoded_Reg_ebp);
214 SetDisp32(Addr);
215 }
216
217 // TODO(jpp): remove this.
218 static Address Absolute(const uintptr_t Addr) {
219 return Address(ABSOLUTE, Addr);
220 }
221
222 Address(AbsoluteTag, RelocOffsetT Offset, AssemblerFixup *Fixup) {
223 SetModRM(0, RegX8632::Encoded_Reg_ebp);
224 // Use the Offset in the displacement for now. If we decide to process
225 // fixups later, we'll need to patch up the emitted displacement.
226 SetDisp32(Offset);
227 SetFixup(Fixup);
228 }
229
230 // TODO(jpp): remove this.
231 static Address Absolute(RelocOffsetT Offset, AssemblerFixup *Fixup) {
232 return Address(ABSOLUTE, Offset, Fixup);
233 }
234
235 static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
236 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
237 const RelocOffsetT Offset = 0;
238 return Address(ABSOLUTE, Offset, Fixup);
239 }
240 };
241
242 //----------------------------------------------------------------------------
243 // __ ______ __ __ ______ ______ __ __ __ ______
244 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\
245 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \
246 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
247 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
248 //
249 //----------------------------------------------------------------------------
250 enum InstructionSet {
251 Begin,
252 // SSE2 is the PNaCl baseline instruction set.
253 SSE2 = Begin,
254 SSE4_1,
255 End
256 };
257
258 // The maximum number of arguments to pass in XMM registers
259 static const uint32_t X86_MAX_XMM_ARGS = 4;
260 // The number of bits in a byte
261 static const uint32_t X86_CHAR_BIT = 8;
262 // Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it
263 // is used as an argument to std::max(), and the default std::less<T> has an
264 // operator(T const&, T const&) which requires this member to have an address.
265 static const uint32_t X86_STACK_ALIGNMENT_BYTES;
266 // Size of the return address on the stack
267 static const uint32_t X86_RET_IP_SIZE_BYTES = 4;
268 // The number of different NOP instructions
269 static const uint32_t X86_NUM_NOP_VARIANTS = 5;
270
271 // Value is in bytes. Return Value adjusted to the next highest multiple
272 // of the stack alignment.
273 static uint32_t applyStackAlignment(uint32_t Value) {
274 return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
275 }
276
277 // Return the type which the elements of the vector have in the X86
278 // representation of the vector.
279 static Type getInVectorElementType(Type Ty) {
280 assert(isVectorType(Ty));
281 size_t Index = static_cast<size_t>(Ty);
282 (void)Index;
283 assert(Index < TableTypeX8632AttributesSize);
284 return TableTypeX8632Attributes[Ty].InVectorElementType;
285 }
286
287 // Note: The following data structures are defined in
288 // IceTargetLoweringX8632.cpp.
289
290 // The following table summarizes the logic for lowering the fcmp
291 // instruction. There is one table entry for each of the 16 conditions.
292 //
293 // The first four columns describe the case when the operands are
294 // floating point scalar values. A comment in lowerFcmp() describes the
295 // lowering template. In the most general case, there is a compare
296 // followed by two conditional branches, because some fcmp conditions
297 // don't map to a single x86 conditional branch. However, in many cases
298 // it is possible to swap the operands in the comparison and have a
299 // single conditional branch. Since it's quite tedious to validate the
300 // table by hand, good execution tests are helpful.
301 //
302 // The last two columns describe the case when the operands are vectors
303 // of floating point values. For most fcmp conditions, there is a clear
304 // mapping to a single x86 cmpps instruction variant. Some fcmp
305 // conditions require special code to handle and these are marked in the
306 // table with a Cmpps_Invalid predicate.
307 static const struct TableFcmpType {
308 uint32_t Default;
309 bool SwapScalarOperands;
310 CondX86::BrCond C1, C2;
311 bool SwapVectorOperands;
312 CondX86::CmppsCond Predicate;
313 } TableFcmp[];
314 static const size_t TableFcmpSize;
315
316 // The following table summarizes the logic for lowering the icmp instruction
317 // for i32 and narrower types. Each icmp condition has a clear mapping to an
318 // x86 conditional branch instruction.
319
320 static const struct TableIcmp32Type {
321 CondX86::BrCond Mapping;
322 } TableIcmp32[];
323 static const size_t TableIcmp32Size;
324
325 // The following table summarizes the logic for lowering the icmp instruction
326 // for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
327 // conditional branches are needed. For the other conditions, three separate
328 // conditional branches are needed.
329 static const struct TableIcmp64Type {
330 CondX86::BrCond C1, C2, C3;
331 } TableIcmp64[];
332 static const size_t TableIcmp64Size;
333
334 static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
335 size_t Index = static_cast<size_t>(Cond);
336 assert(Index < TableIcmp32Size);
337 return TableIcmp32[Index].Mapping;
338 }
339
340 static const struct TableTypeX8632AttributesType {
341 Type InVectorElementType;
342 } TableTypeX8632Attributes[];
343 static const size_t TableTypeX8632AttributesSize;
344 };
345
346 } // end of namespace X86Internal
347
348 namespace X8632 {
349 using Traits = ::Ice::X86Internal::MachineTraits<TargetX8632>;
350 } // end of namespace X8632
351
352 } // end of namespace Ice
353
354 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
OLDNEW
« no previous file with comments | « src/IceTargetLoweringX8632.cpp ('k') | src/IceTargetLoweringX86Base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698