| OLD | NEW |
| (Empty) | |
| 1 //===- subzero/src/IceTargetLoweringX8664Traits.h - x86-64 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 /// \file |
| 11 /// This file declares the X8664 Target Lowering Traits. |
| 12 /// |
| 13 //===----------------------------------------------------------------------===// |
| 14 |
| 15 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H |
| 16 #define SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H |
| 17 |
| 18 #include "IceAssembler.h" |
| 19 #include "IceConditionCodesX8664.h" |
| 20 #include "IceDefs.h" |
| 21 #include "IceInst.h" |
| 22 #include "IceInstX8664.def" |
| 23 #include "IceOperand.h" |
| 24 #include "IceRegistersX8664.h" |
| 25 #include "IceTargetLowering.h" |
| 26 |
| 27 namespace Ice { |
| 28 |
| 29 class TargetX8664; |
| 30 |
| 31 namespace X8664 { |
| 32 class AssemblerX8664; |
| 33 } // end of namespace X8664 |
| 34 |
| 35 namespace X86Internal { |
| 36 |
| 37 template <class Machine> struct Insts; |
| 38 template <class Machine> struct MachineTraits; |
| 39 |
| 40 template <> struct MachineTraits<TargetX8664> { |
| 41 //---------------------------------------------------------------------------- |
| 42 // ______ ______ __ __ |
| 43 // /\ __ \/\ ___\/\ "-./ \ |
| 44 // \ \ __ \ \___ \ \ \-./\ \ |
| 45 // \ \_\ \_\/\_____\ \_\ \ \_\ |
| 46 // \/_/\/_/\/_____/\/_/ \/_/ |
| 47 // |
| 48 //---------------------------------------------------------------------------- |
| 49 static constexpr bool Is64Bit = true; |
| 50 static constexpr bool HasPopa = false; |
| 51 static constexpr bool HasPusha = false; |
| 52 static constexpr bool UsesX87 = false; |
| 53 static constexpr ::Ice::RegX8664::GPRRegister Last8BitGPR = |
| 54 ::Ice::RegX8664::GPRRegister::Encoded_Reg_r15d; |
| 55 |
| 56 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; |
| 57 |
| 58 using GPRRegister = ::Ice::RegX8664::GPRRegister; |
| 59 using XmmRegister = ::Ice::RegX8664::XmmRegister; |
| 60 using ByteRegister = ::Ice::RegX8664::ByteRegister; |
| 61 |
| 62 using Cond = ::Ice::CondX8664; |
| 63 |
| 64 using RegisterSet = ::Ice::RegX8664; |
| 65 static const GPRRegister Encoded_Reg_Accumulator = RegX8664::Encoded_Reg_eax; |
| 66 static const GPRRegister Encoded_Reg_Counter = RegX8664::Encoded_Reg_ecx; |
| 67 static const FixupKind PcRelFixup = llvm::ELF::R_386_PC32; // TODO(jpp): ??? |
| 68 |
| 69 class Operand { |
| 70 public: |
| 71 enum RexBits { |
| 72 RexNone = 0x00, |
| 73 RexBase = 0x40, |
| 74 RexW = RexBase | (1 << 3), |
| 75 RexR = RexBase | (1 << 2), |
| 76 RexX = RexBase | (1 << 1), |
| 77 RexB = RexBase | (1 << 0), |
| 78 }; |
| 79 |
| 80 Operand(const Operand &other) |
| 81 : fixup_(other.fixup_), rex_(other.rex_), length_(other.length_) { |
| 82 memmove(&encoding_[0], &other.encoding_[0], other.length_); |
| 83 } |
| 84 |
| 85 Operand &operator=(const Operand &other) { |
| 86 length_ = other.length_; |
| 87 fixup_ = other.fixup_; |
| 88 rex_ = other.rex_; |
| 89 memmove(&encoding_[0], &other.encoding_[0], other.length_); |
| 90 return *this; |
| 91 } |
| 92 |
| 93 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; } |
| 94 |
| 95 uint8_t rexX() const { return (rex_ & RexX) != RexX ? RexNone : RexX; } |
| 96 uint8_t rexB() const { return (rex_ & RexB) != RexB ? RexNone : RexB; } |
| 97 |
| 98 GPRRegister rm() const { |
| 99 return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) | |
| 100 (encoding_at(0) & 7)); |
| 101 } |
| 102 |
| 103 ScaleFactor scale() const { |
| 104 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); |
| 105 } |
| 106 |
| 107 GPRRegister index() const { |
| 108 return static_cast<GPRRegister>((rexX() != 0 ? 0x08 : 0) | |
| 109 ((encoding_at(1) >> 3) & 7)); |
| 110 } |
| 111 |
| 112 GPRRegister base() const { |
| 113 return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) | |
| 114 (encoding_at(1) & 7)); |
| 115 } |
| 116 |
| 117 int8_t disp8() const { |
| 118 assert(length_ >= 2); |
| 119 return static_cast<int8_t>(encoding_[length_ - 1]); |
| 120 } |
| 121 |
| 122 int32_t disp32() const { |
| 123 assert(length_ >= 5); |
| 124 return bit_copy<int32_t>(encoding_[length_ - 4]); |
| 125 } |
| 126 |
| 127 AssemblerFixup *fixup() const { return fixup_; } |
| 128 |
| 129 protected: |
| 130 Operand() : fixup_(nullptr), length_(0) {} // Needed by subclass Address. |
| 131 |
| 132 void SetModRM(int mod, GPRRegister rm) { |
| 133 assert((mod & ~3) == 0); |
| 134 encoding_[0] = (mod << 6) | (rm & 0x07); |
| 135 rex_ = (rm & 0x08) ? RexB : RexNone; |
| 136 length_ = 1; |
| 137 } |
| 138 |
| 139 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { |
| 140 assert(length_ == 1); |
| 141 assert((scale & ~3) == 0); |
| 142 encoding_[1] = (scale << 6) | ((index & 0x07) << 3) | (base & 0x07); |
| 143 rex_ = |
| 144 ((base & 0x08) ? RexB : RexNone) | ((index & 0x08) ? RexX : RexNone); |
| 145 length_ = 2; |
| 146 } |
| 147 |
| 148 void SetDisp8(int8_t disp) { |
| 149 assert(length_ == 1 || length_ == 2); |
| 150 encoding_[length_++] = static_cast<uint8_t>(disp); |
| 151 } |
| 152 |
| 153 void SetDisp32(int32_t disp) { |
| 154 assert(length_ == 1 || length_ == 2); |
| 155 intptr_t disp_size = sizeof(disp); |
| 156 memmove(&encoding_[length_], &disp, disp_size); |
| 157 length_ += disp_size; |
| 158 } |
| 159 |
| 160 void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; } |
| 161 |
| 162 private: |
| 163 AssemblerFixup *fixup_; |
| 164 uint8_t rex_ = 0; |
| 165 uint8_t encoding_[6]; |
| 166 uint8_t length_; |
| 167 |
| 168 explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); } |
| 169 |
| 170 /// Get the operand encoding byte at the given index. |
| 171 uint8_t encoding_at(intptr_t index) const { |
| 172 assert(index >= 0 && index < length_); |
| 173 return encoding_[index]; |
| 174 } |
| 175 |
| 176 /// Returns whether or not this operand is really the given register in |
| 177 /// disguise. Used from the assembler to generate better encodings. |
| 178 bool IsRegister(GPRRegister reg) const { |
| 179 return ((encoding_[0] & 0xF8) == |
| 180 0xC0) // Addressing mode is register only. |
| 181 && |
| 182 (rm() == reg); // Register codes match. |
| 183 } |
| 184 |
| 185 template <class> friend class AssemblerX86Base; |
| 186 }; |
| 187 |
| 188 class Address : public Operand { |
| 189 Address() = delete; |
| 190 |
| 191 public: |
| 192 Address(const Address &other) : Operand(other) {} |
| 193 |
| 194 Address &operator=(const Address &other) { |
| 195 Operand::operator=(other); |
| 196 return *this; |
| 197 } |
| 198 |
| 199 Address(GPRRegister base, int32_t disp) { |
| 200 if (disp == 0 && (base & 7) != RegX8664::Encoded_Reg_ebp) { |
| 201 SetModRM(0, base); |
| 202 if ((base & 7) == RegX8664::Encoded_Reg_esp) |
| 203 SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, base); |
| 204 } else if (Utils::IsInt(8, disp)) { |
| 205 SetModRM(1, base); |
| 206 if ((base & 7) == RegX8664::Encoded_Reg_esp) |
| 207 SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, base); |
| 208 SetDisp8(disp); |
| 209 } else { |
| 210 SetModRM(2, base); |
| 211 if ((base & 7) == RegX8664::Encoded_Reg_esp) |
| 212 SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, base); |
| 213 SetDisp32(disp); |
| 214 } |
| 215 } |
| 216 |
| 217 Address(GPRRegister index, ScaleFactor scale, int32_t disp) { |
| 218 assert(index != RegX8664::Encoded_Reg_esp); // Illegal addressing mode. |
| 219 SetModRM(0, RegX8664::Encoded_Reg_esp); |
| 220 SetSIB(scale, index, RegX8664::Encoded_Reg_ebp); |
| 221 SetDisp32(disp); |
| 222 } |
| 223 |
| 224 Address(GPRRegister base, GPRRegister index, ScaleFactor scale, |
| 225 int32_t disp) { |
| 226 assert(index != RegX8664::Encoded_Reg_esp); // Illegal addressing mode. |
| 227 if (disp == 0 && (base & 7) != RegX8664::Encoded_Reg_ebp) { |
| 228 SetModRM(0, RegX8664::Encoded_Reg_esp); |
| 229 SetSIB(scale, index, base); |
| 230 } else if (Utils::IsInt(8, disp)) { |
| 231 SetModRM(1, RegX8664::Encoded_Reg_esp); |
| 232 SetSIB(scale, index, base); |
| 233 SetDisp8(disp); |
| 234 } else { |
| 235 SetModRM(2, RegX8664::Encoded_Reg_esp); |
| 236 SetSIB(scale, index, base); |
| 237 SetDisp32(disp); |
| 238 } |
| 239 } |
| 240 |
| 241 // PcRelTag is a special tag for requesting rip-relative addressing in |
| 242 // X86-64. |
| 243 // TODO(jpp): this is bogus. remove. |
| 244 enum AbsoluteTag { ABSOLUTE }; |
| 245 |
| 246 Address(AbsoluteTag, const uintptr_t Addr) { |
| 247 SetModRM(0, RegX8664::Encoded_Reg_ebp); |
| 248 SetDisp32(Addr); |
| 249 } |
| 250 |
| 251 // TODO(jpp): remove this. |
| 252 static Address Absolute(const uintptr_t Addr) { |
| 253 return Address(ABSOLUTE, Addr); |
| 254 } |
| 255 |
| 256 Address(AbsoluteTag, RelocOffsetT Offset, AssemblerFixup *Fixup) { |
| 257 SetModRM(0, RegX8664::Encoded_Reg_ebp); |
| 258 // Use the Offset in the displacement for now. If we decide to process |
| 259 // fixups later, we'll need to patch up the emitted displacement. |
| 260 SetDisp32(Offset); |
| 261 SetFixup(Fixup); |
| 262 } |
| 263 |
| 264 // TODO(jpp): remove this. |
| 265 static Address Absolute(RelocOffsetT Offset, AssemblerFixup *Fixup) { |
| 266 return Address(ABSOLUTE, Offset, Fixup); |
| 267 } |
| 268 |
| 269 static Address ofConstPool(Assembler *Asm, const Constant *Imm) { |
| 270 // TODO(jpp): ??? |
| 271 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm); |
| 272 const RelocOffsetT Offset = 0; |
| 273 return Address(ABSOLUTE, Offset, Fixup); |
| 274 } |
| 275 }; |
| 276 |
| 277 //---------------------------------------------------------------------------- |
| 278 // __ ______ __ __ ______ ______ __ __ __ ______ |
| 279 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ |
| 280 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ |
| 281 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ |
| 282 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ |
| 283 // |
| 284 //---------------------------------------------------------------------------- |
| 285 using Assembler = X8664::AssemblerX8664; |
| 286 }; |
| 287 |
| 288 } // end of namespace X86Internal |
| 289 |
| 290 namespace X8664 { |
| 291 using Traits = ::Ice::X86Internal::MachineTraits<TargetX8664>; |
| 292 } // end of namespace X8664 |
| 293 |
| 294 } // end of namespace Ice |
| 295 |
| 296 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H |
| OLD | NEW |