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