15d0acff3a2fa421923392aadb4df2742064b6248John Porto//===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- C++ -*-=//
25d0acff3a2fa421923392aadb4df2742064b6248John Porto//
35d0acff3a2fa421923392aadb4df2742064b6248John Porto//                        The Subzero Code Generator
45d0acff3a2fa421923392aadb4df2742064b6248John Porto//
55d0acff3a2fa421923392aadb4df2742064b6248John Porto// This file is distributed under the University of Illinois Open Source
65d0acff3a2fa421923392aadb4df2742064b6248John Porto// License. See LICENSE.TXT for details.
75d0acff3a2fa421923392aadb4df2742064b6248John Porto//
85d0acff3a2fa421923392aadb4df2742064b6248John Porto//===----------------------------------------------------------------------===//
9921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto///
10921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto/// \file
1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Declares the X8632 Target Lowering Traits.
12921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto///
135d0acff3a2fa421923392aadb4df2742064b6248John Porto//===----------------------------------------------------------------------===//
145d0acff3a2fa421923392aadb4df2742064b6248John Porto
155d0acff3a2fa421923392aadb4df2742064b6248John Porto#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
165d0acff3a2fa421923392aadb4df2742064b6248John Porto#define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
175d0acff3a2fa421923392aadb4df2742064b6248John Porto
185d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceAssembler.h"
195d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceConditionCodesX8632.h"
205d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceDefs.h"
215d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceInst.h"
225d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceInstX8632.def"
23921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#include "IceOperand.h"
245d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceRegistersX8632.h"
25921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#include "IceTargetLowering.h"
26c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth#include "IceTargetLoweringX8632.def"
27c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth#include "IceTargetLoweringX86RegClass.h"
285d0acff3a2fa421923392aadb4df2742064b6248John Porto
29bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto#include <array>
30bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto
315d0acff3a2fa421923392aadb4df2742064b6248John Portonamespace Ice {
325d0acff3a2fa421923392aadb4df2742064b6248John Porto
33921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Portonamespace X8632 {
344a56686b5b56db6803f90ad53514bf2fa190d9f7John Portousing namespace ::Ice::X86;
355d0acff3a2fa421923392aadb4df2742064b6248John Porto
36921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Portotemplate <class Machine> struct Insts;
375aeed955e17bac8cc44cc6d2b6ff7513cc714c2fJohn Portotemplate <class Machine> class TargetX86Base;
384a56686b5b56db6803f90ad53514bf2fa190d9f7John Portotemplate <class Machine> class AssemblerX86Base;
395d0acff3a2fa421923392aadb4df2742064b6248John Porto
404a56686b5b56db6803f90ad53514bf2fa190d9f7John Portoclass TargetX8632;
414a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto
424a56686b5b56db6803f90ad53514bf2fa190d9f7John Portostruct TargetX8632Traits {
435d0acff3a2fa421923392aadb4df2742064b6248John Porto  //----------------------------------------------------------------------------
445d0acff3a2fa421923392aadb4df2742064b6248John Porto  //     ______  ______  __    __
455d0acff3a2fa421923392aadb4df2742064b6248John Porto  //    /\  __ \/\  ___\/\ "-./  \
465d0acff3a2fa421923392aadb4df2742064b6248John Porto  //    \ \  __ \ \___  \ \ \-./\ \
475d0acff3a2fa421923392aadb4df2742064b6248John Porto  //     \ \_\ \_\/\_____\ \_\ \ \_\
485d0acff3a2fa421923392aadb4df2742064b6248John Porto  //      \/_/\/_/\/_____/\/_/  \/_/
495d0acff3a2fa421923392aadb4df2742064b6248John Porto  //
505d0acff3a2fa421923392aadb4df2742064b6248John Porto  //----------------------------------------------------------------------------
514a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  static constexpr ::Ice::Assembler::AssemblerKind AsmKind =
524a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto      ::Ice::Assembler::Asm_X8632;
534a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto
542fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool Is64Bit = false;
552fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool HasPopa = true;
562fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool HasPusha = true;
572fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool UsesX87 = true;
582fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr ::Ice::RegX8632::GPRRegister Last8BitGPR =
592fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      ::Ice::RegX8632::GPRRegister::Encoded_Reg_ebx;
602fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
615d0acff3a2fa421923392aadb4df2742064b6248John Porto  enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
625d0acff3a2fa421923392aadb4df2742064b6248John Porto
635d0acff3a2fa421923392aadb4df2742064b6248John Porto  using GPRRegister = ::Ice::RegX8632::GPRRegister;
645d0acff3a2fa421923392aadb4df2742064b6248John Porto  using ByteRegister = ::Ice::RegX8632::ByteRegister;
655bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  using XmmRegister = ::Ice::RegX8632::XmmRegister;
665d0acff3a2fa421923392aadb4df2742064b6248John Porto  using X87STRegister = ::Ice::RegX8632::X87STRegister;
675d0acff3a2fa421923392aadb4df2742064b6248John Porto
685d0acff3a2fa421923392aadb4df2742064b6248John Porto  using Cond = ::Ice::CondX86;
695d0acff3a2fa421923392aadb4df2742064b6248John Porto
705d0acff3a2fa421923392aadb4df2742064b6248John Porto  using RegisterSet = ::Ice::RegX8632;
718aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static constexpr RegisterSet::AllRegisters StackPtr = RegX8632::Reg_esp;
728aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static constexpr RegisterSet::AllRegisters FramePtr = RegX8632::Reg_ebp;
730c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr GPRRegister Encoded_Reg_Accumulator =
740c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr      RegX8632::Encoded_Reg_eax;
750c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx;
768ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static constexpr FixupKind FK_PcRel = llvm::ELF::R_386_PC32;
778ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static constexpr FixupKind FK_Abs = llvm::ELF::R_386_32;
788ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static constexpr FixupKind FK_Gotoff = llvm::ELF::R_386_GOTOFF;
798ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static constexpr FixupKind FK_GotPC = llvm::ELF::R_386_GOTPC;
805d0acff3a2fa421923392aadb4df2742064b6248John Porto
815d0acff3a2fa421923392aadb4df2742064b6248John Porto  class Operand {
825d0acff3a2fa421923392aadb4df2742064b6248John Porto  public:
835d0acff3a2fa421923392aadb4df2742064b6248John Porto    Operand(const Operand &other)
84921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        : fixup_(other.fixup_), length_(other.length_) {
855d0acff3a2fa421923392aadb4df2742064b6248John Porto      memmove(&encoding_[0], &other.encoding_[0], other.length_);
865d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
875d0acff3a2fa421923392aadb4df2742064b6248John Porto
885d0acff3a2fa421923392aadb4df2742064b6248John Porto    Operand &operator=(const Operand &other) {
895d0acff3a2fa421923392aadb4df2742064b6248John Porto      length_ = other.length_;
905d0acff3a2fa421923392aadb4df2742064b6248John Porto      fixup_ = other.fixup_;
915d0acff3a2fa421923392aadb4df2742064b6248John Porto      memmove(&encoding_[0], &other.encoding_[0], other.length_);
925d0acff3a2fa421923392aadb4df2742064b6248John Porto      return *this;
935d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
945d0acff3a2fa421923392aadb4df2742064b6248John Porto
955d0acff3a2fa421923392aadb4df2742064b6248John Porto    uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
965d0acff3a2fa421923392aadb4df2742064b6248John Porto
975d0acff3a2fa421923392aadb4df2742064b6248John Porto    GPRRegister rm() const {
985d0acff3a2fa421923392aadb4df2742064b6248John Porto      return static_cast<GPRRegister>(encoding_at(0) & 7);
995d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1005d0acff3a2fa421923392aadb4df2742064b6248John Porto
1015d0acff3a2fa421923392aadb4df2742064b6248John Porto    ScaleFactor scale() const {
1025d0acff3a2fa421923392aadb4df2742064b6248John Porto      return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
1035d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1045d0acff3a2fa421923392aadb4df2742064b6248John Porto
1055d0acff3a2fa421923392aadb4df2742064b6248John Porto    GPRRegister index() const {
1065d0acff3a2fa421923392aadb4df2742064b6248John Porto      return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
1075d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1085d0acff3a2fa421923392aadb4df2742064b6248John Porto
1095d0acff3a2fa421923392aadb4df2742064b6248John Porto    GPRRegister base() const {
1105d0acff3a2fa421923392aadb4df2742064b6248John Porto      return static_cast<GPRRegister>(encoding_at(1) & 7);
1115d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1125d0acff3a2fa421923392aadb4df2742064b6248John Porto
1135d0acff3a2fa421923392aadb4df2742064b6248John Porto    int8_t disp8() const {
1145d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(length_ >= 2);
1155d0acff3a2fa421923392aadb4df2742064b6248John Porto      return static_cast<int8_t>(encoding_[length_ - 1]);
1165d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1175d0acff3a2fa421923392aadb4df2742064b6248John Porto
1185d0acff3a2fa421923392aadb4df2742064b6248John Porto    int32_t disp32() const {
1195d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(length_ >= 5);
120b0051dfaca6e957fa62ab61c0ef2a42df7964d37Jim Stichnoth      // TODO(stichnot): This method is not currently used.  Delete it along
121b0051dfaca6e957fa62ab61c0ef2a42df7964d37Jim Stichnoth      // with other unused methods, or use a safe version of bitCopy().
122b0051dfaca6e957fa62ab61c0ef2a42df7964d37Jim Stichnoth      llvm::report_fatal_error("Unexpected call to disp32()");
123b0051dfaca6e957fa62ab61c0ef2a42df7964d37Jim Stichnoth      // return Utils::bitCopy<int32_t>(encoding_[length_ - 4]);
1245d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1255d0acff3a2fa421923392aadb4df2742064b6248John Porto
1265d0acff3a2fa421923392aadb4df2742064b6248John Porto    AssemblerFixup *fixup() const { return fixup_; }
1275d0acff3a2fa421923392aadb4df2742064b6248John Porto
1285d0acff3a2fa421923392aadb4df2742064b6248John Porto  protected:
129921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Operand() : fixup_(nullptr), length_(0) {} // Needed by subclass Address.
1305d0acff3a2fa421923392aadb4df2742064b6248John Porto
1315d0acff3a2fa421923392aadb4df2742064b6248John Porto    void SetModRM(int mod, GPRRegister rm) {
1325d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert((mod & ~3) == 0);
1335d0acff3a2fa421923392aadb4df2742064b6248John Porto      encoding_[0] = (mod << 6) | rm;
1345d0acff3a2fa421923392aadb4df2742064b6248John Porto      length_ = 1;
1355d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1365d0acff3a2fa421923392aadb4df2742064b6248John Porto
1375d0acff3a2fa421923392aadb4df2742064b6248John Porto    void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
1385d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(length_ == 1);
1395d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert((scale & ~3) == 0);
1405d0acff3a2fa421923392aadb4df2742064b6248John Porto      encoding_[1] = (scale << 6) | (index << 3) | base;
1415d0acff3a2fa421923392aadb4df2742064b6248John Porto      length_ = 2;
1425d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1435d0acff3a2fa421923392aadb4df2742064b6248John Porto
1445d0acff3a2fa421923392aadb4df2742064b6248John Porto    void SetDisp8(int8_t disp) {
1455d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(length_ == 1 || length_ == 2);
1465d0acff3a2fa421923392aadb4df2742064b6248John Porto      encoding_[length_++] = static_cast<uint8_t>(disp);
1475d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1485d0acff3a2fa421923392aadb4df2742064b6248John Porto
1495d0acff3a2fa421923392aadb4df2742064b6248John Porto    void SetDisp32(int32_t disp) {
1505d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(length_ == 1 || length_ == 2);
1515d0acff3a2fa421923392aadb4df2742064b6248John Porto      intptr_t disp_size = sizeof(disp);
1525d0acff3a2fa421923392aadb4df2742064b6248John Porto      memmove(&encoding_[length_], &disp, disp_size);
1535d0acff3a2fa421923392aadb4df2742064b6248John Porto      length_ += disp_size;
1545d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1555d0acff3a2fa421923392aadb4df2742064b6248John Porto
1565d0acff3a2fa421923392aadb4df2742064b6248John Porto    void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
1575d0acff3a2fa421923392aadb4df2742064b6248John Porto
1585d0acff3a2fa421923392aadb4df2742064b6248John Porto  private:
1595d0acff3a2fa421923392aadb4df2742064b6248John Porto    AssemblerFixup *fixup_;
160921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    uint8_t encoding_[6];
161921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    uint8_t length_;
1625d0acff3a2fa421923392aadb4df2742064b6248John Porto
1635d0acff3a2fa421923392aadb4df2742064b6248John Porto    explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
1645d0acff3a2fa421923392aadb4df2742064b6248John Porto
165921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// Get the operand encoding byte at the given index.
1665d0acff3a2fa421923392aadb4df2742064b6248John Porto    uint8_t encoding_at(intptr_t index) const {
1675d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(index >= 0 && index < length_);
1685d0acff3a2fa421923392aadb4df2742064b6248John Porto      return encoding_[index];
1695d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1705d0acff3a2fa421923392aadb4df2742064b6248John Porto
171921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// Returns whether or not this operand is really the given register in
172921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// disguise. Used from the assembler to generate better encodings.
1735d0acff3a2fa421923392aadb4df2742064b6248John Porto    bool IsRegister(GPRRegister reg) const {
1745d0acff3a2fa421923392aadb4df2742064b6248John Porto      return ((encoding_[0] & 0xF8) ==
1755d0acff3a2fa421923392aadb4df2742064b6248John Porto              0xC0) // Addressing mode is register only.
1765d0acff3a2fa421923392aadb4df2742064b6248John Porto             &&
1775d0acff3a2fa421923392aadb4df2742064b6248John Porto             ((encoding_[0] & 0x07) == reg); // Register codes match.
1785d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1795d0acff3a2fa421923392aadb4df2742064b6248John Porto
1804a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto    friend class AssemblerX86Base<TargetX8632Traits>;
1815d0acff3a2fa421923392aadb4df2742064b6248John Porto  };
1825d0acff3a2fa421923392aadb4df2742064b6248John Porto
1835d0acff3a2fa421923392aadb4df2742064b6248John Porto  class Address : public Operand {
1845d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address() = delete;
1855d0acff3a2fa421923392aadb4df2742064b6248John Porto
1865d0acff3a2fa421923392aadb4df2742064b6248John Porto  public:
1875d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address(const Address &other) : Operand(other) {}
1885d0acff3a2fa421923392aadb4df2742064b6248John Porto
1895d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address &operator=(const Address &other) {
1905d0acff3a2fa421923392aadb4df2742064b6248John Porto      Operand::operator=(other);
1915d0acff3a2fa421923392aadb4df2742064b6248John Porto      return *this;
1925d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1935d0acff3a2fa421923392aadb4df2742064b6248John Porto
194aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr    Address(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
195aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
196aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetModRM(0, Base);
197aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        if (Base == RegX8632::Encoded_Reg_esp)
198aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr          SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
199aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
200aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetModRM(1, Base);
201aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        if (Base == RegX8632::Encoded_Reg_esp)
202aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr          SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
203aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetDisp8(Disp);
2045d0acff3a2fa421923392aadb4df2742064b6248John Porto      } else {
205aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetModRM(2, Base);
206aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        if (Base == RegX8632::Encoded_Reg_esp)
207aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr          SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
208aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetDisp32(Disp);
209aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        if (Fixup)
210aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr          SetFixup(Fixup);
2115d0acff3a2fa421923392aadb4df2742064b6248John Porto      }
2125d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2135d0acff3a2fa421923392aadb4df2742064b6248John Porto
214aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr    Address(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
215aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr            AssemblerFixup *Fixup) {
216aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
2175d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetModRM(0, RegX8632::Encoded_Reg_esp);
218aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      SetSIB(Scale, Index, RegX8632::Encoded_Reg_ebp);
219aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      SetDisp32(Disp);
220aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      if (Fixup)
221aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetFixup(Fixup);
2225d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2235d0acff3a2fa421923392aadb4df2742064b6248John Porto
224aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr    Address(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
225aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr            int32_t Disp, AssemblerFixup *Fixup) {
226aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
227aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
2285d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetModRM(0, RegX8632::Encoded_Reg_esp);
229aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetSIB(Scale, Index, Base);
230aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
2315d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetModRM(1, RegX8632::Encoded_Reg_esp);
232aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetSIB(Scale, Index, Base);
233aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetDisp8(Disp);
2345d0acff3a2fa421923392aadb4df2742064b6248John Porto      } else {
2355d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetModRM(2, RegX8632::Encoded_Reg_esp);
236aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetSIB(Scale, Index, Base);
237aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetDisp32(Disp);
238aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        if (Fixup)
239aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr          SetFixup(Fixup);
2405d0acff3a2fa421923392aadb4df2742064b6248John Porto      }
2415d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2425d0acff3a2fa421923392aadb4df2742064b6248John Porto
243aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr    /// Generate an absolute address expression on x86-32.
244aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr    Address(RelocOffsetT Offset, AssemblerFixup *Fixup) {
2455d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetModRM(0, RegX8632::Encoded_Reg_ebp);
2465d0acff3a2fa421923392aadb4df2742064b6248John Porto      // Use the Offset in the displacement for now. If we decide to process
2475d0acff3a2fa421923392aadb4df2742064b6248John Porto      // fixups later, we'll need to patch up the emitted displacement.
2485d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetDisp32(Offset);
249aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      if (Fixup)
250aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetFixup(Fixup);
2515d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2525d0acff3a2fa421923392aadb4df2742064b6248John Porto
2535d0acff3a2fa421923392aadb4df2742064b6248John Porto    static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
2545d0acff3a2fa421923392aadb4df2742064b6248John Porto      AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
2555d0acff3a2fa421923392aadb4df2742064b6248John Porto      const RelocOffsetT Offset = 0;
256aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      return Address(Offset, Fixup);
2575d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2585d0acff3a2fa421923392aadb4df2742064b6248John Porto  };
2595d0acff3a2fa421923392aadb4df2742064b6248John Porto
2605d0acff3a2fa421923392aadb4df2742064b6248John Porto  //----------------------------------------------------------------------------
2615d0acff3a2fa421923392aadb4df2742064b6248John Porto  //     __      ______  __     __  ______  ______  __  __   __  ______
2625d0acff3a2fa421923392aadb4df2742064b6248John Porto  //    /\ \    /\  __ \/\ \  _ \ \/\  ___\/\  == \/\ \/\ "-.\ \/\  ___\
2635d0acff3a2fa421923392aadb4df2742064b6248John Porto  //    \ \ \___\ \ \/\ \ \ \/ ".\ \ \  __\\ \  __<\ \ \ \ \-.  \ \ \__ \
2645d0acff3a2fa421923392aadb4df2742064b6248John Porto  //     \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
2655d0acff3a2fa421923392aadb4df2742064b6248John Porto  //      \/_____/\/_____/\/_/   \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
2665d0acff3a2fa421923392aadb4df2742064b6248John Porto  //
2675d0acff3a2fa421923392aadb4df2742064b6248John Porto  //----------------------------------------------------------------------------
2685d0acff3a2fa421923392aadb4df2742064b6248John Porto  enum InstructionSet {
2695d0acff3a2fa421923392aadb4df2742064b6248John Porto    Begin,
2705d0acff3a2fa421923392aadb4df2742064b6248John Porto    // SSE2 is the PNaCl baseline instruction set.
2715d0acff3a2fa421923392aadb4df2742064b6248John Porto    SSE2 = Begin,
2725d0acff3a2fa421923392aadb4df2742064b6248John Porto    SSE4_1,
2735d0acff3a2fa421923392aadb4df2742064b6248John Porto    End
2745d0acff3a2fa421923392aadb4df2742064b6248John Porto  };
2755d0acff3a2fa421923392aadb4df2742064b6248John Porto
276921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const char *TargetName;
2771d235425dab1f3dd059973fc53f1b1d5879469e3John Porto  static constexpr Type WordType = IceType_i32;
278921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
279467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  static const char *getRegName(RegNumT RegNum) {
2804a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const char *const RegNames[RegisterSet::Reg_NUM] = {
2815bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
2825bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
2835bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
2845bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  name,
2855bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8632_TABLE
2865bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
2875bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
2888aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
2895bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return RegNames[RegNum];
2905bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
2915bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
2928aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static GPRRegister getEncodedGPR(RegNumT RegNum) {
2934a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = {
2945bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
2955bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
2965bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
2975bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
298921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        REGX8632_TABLE
299921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
300921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    };
3018aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3025bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
3035bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return GPRRegs[RegNum];
3045bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
305921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
3068aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static ByteRegister getEncodedByteReg(RegNumT RegNum) {
3074a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = {
3085bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
3095bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
3105bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
3115bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
312921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        REGX8632_TABLE
313921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
314921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    };
3158aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3165bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
3175bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return ByteRegs[RegNum];
3185bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
319921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
3208aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static XmmRegister getEncodedXmm(RegNumT RegNum) {
3214a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = {
3225bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
3235bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
3245bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
3255bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
3265bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8632_TABLE
3275bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3285bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3298aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3305bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
3315bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return XmmRegs[RegNum];
3325bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
3335bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
3348aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static uint32_t getEncoding(RegNumT RegNum) {
3354a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const uint32_t Encoding[RegisterSet::Reg_NUM] = {
3365bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
3375bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
3385bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
3395bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  encode,
340921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        REGX8632_TABLE
341921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
342921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    };
3438aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3445bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return Encoding[RegNum];
3455bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
346921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
3478aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getBaseReg(RegNumT RegNum) {
3488aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = {
3495bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
3505bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
3515bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
3525bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  RegisterSet::base,
3535bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8632_TABLE
3545bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3555bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3568aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3575bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return BaseRegs[RegNum];
3585bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
3595bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
360ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnothprivate:
3618aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegisterSet::AllRegisters getFirstGprForType(Type Ty) {
362ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    switch (Ty) {
363ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    default:
364ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth      llvm_unreachable("Invalid type for GPR.");
365ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    case IceType_i1:
366ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    case IceType_i8:
367ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth      return RegisterSet::Reg_al;
368ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    case IceType_i16:
369ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth      return RegisterSet::Reg_ax;
370ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    case IceType_i32:
371ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth      return RegisterSet::Reg_eax;
372ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    }
373ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth  }
374ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth
375ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnothpublic:
3765bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  // Return a register in RegNum's alias set that is suitable for Ty.
3778aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
3785fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler    assert(RegNum.hasValue());
379ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth
380ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    if (!isScalarIntegerType(Ty)) {
381ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth      return RegNum;
382ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    }
383ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth
384b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr    // [abcd]h registers are not convertible to their ?l, ?x, and e?x versions.
385b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr    switch (RegNum) {
386b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr    default:
387b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr      break;
388b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr    case RegisterSet::Reg_ah:
389b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr    case RegisterSet::Reg_bh:
390b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr    case RegisterSet::Reg_ch:
391b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr    case RegisterSet::Reg_dh:
392b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr      assert(isByteSizedType(Ty));
393b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr      return RegNum;
394b19d39cc5fa8dc60c678c2507af02147184f168fDavid Sehr    }
395ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth
3968aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    const RegisterSet::AllRegisters FirstGprForType = getFirstGprForType(Ty);
397ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth
398ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    switch (RegNum) {
399ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    default:
400ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth      llvm::report_fatal_error("Unknown register.");
401ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
402ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
403ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
404ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth  case RegisterSet::val: {                                                     \
405ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    if (!isGPR)                                                                \
406ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth      return RegisterSet::val;                                                 \
407ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    assert((is32) || (is16) || (is8) ||                                        \
408ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth           getBaseReg(RegisterSet::val) == RegisterSet::Reg_esp);              \
4098aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize =               \
410ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth        (((is32) || RegisterSet::val == RegisterSet::Reg_esp)                  \
411ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth             ? RegisterSet::Reg_eax                                            \
412ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth             : (((is16) || RegisterSet::val == RegisterSet::Reg_sp)            \
413ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth                    ? RegisterSet::Reg_ax                                      \
414ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth                    : RegisterSet::Reg_al));                                   \
4158aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    const RegNumT NewRegNum =                                                  \
4168aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth        RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
417ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
418ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth           "Error involving " #val);                                           \
419ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth    return NewRegNum;                                                          \
420ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth  }
421ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth      REGX8632_TABLE
422ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth#undef X
423921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
424921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  }
425921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
4264a308cedda6bfe381dc9506f3508c4547a06275fJohn Portoprivate:
4274a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  /// SizeOf is used to obtain the size of an initializer list as a constexpr
4284a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  /// expression. This is only needed until our C++ library is updated to
4294a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  /// C++ 14 -- which defines constexpr members to std::initializer_list.
4304a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  class SizeOf {
4314a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    SizeOf(const SizeOf &) = delete;
4324a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    SizeOf &operator=(const SizeOf &) = delete;
4334a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4344a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  public:
4354a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    constexpr SizeOf() : Size(0) {}
4364a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    template <typename... T>
4374a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    explicit constexpr SizeOf(T...)
4384a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto        : Size(__length<T...>::value) {}
4394a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    constexpr SizeT size() const { return Size; }
4404a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4414a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  private:
4424a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    template <typename T, typename... U> struct __length {
4434a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      static constexpr std::size_t value = 1 + __length<U...>::value;
4444a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    };
4454a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4464a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    template <typename T> struct __length<T> {
4474a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      static constexpr std::size_t value = 1;
4484a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    };
4494a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4504a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    const std::size_t Size;
4514a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  };
4524a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4534a308cedda6bfe381dc9506f3508c4547a06275fJohn Portopublic:
454bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto  static void initRegisterSet(
45556958cb33d3c1d045f2844408d825442d523f59fJohn Porto      const ::Ice::ClFlags & /*Flags*/,
456e82b560e649f8a68bcb252b9b002708e74d962d3John Porto      std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
457e82b560e649f8a68bcb252b9b002708e74d962d3John Porto      std::array<SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) {
458e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM);
459e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM);
460e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
461e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
462e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
463e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM);
464e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM);
465e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM);
466e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM);
467e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM);
468e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
4694a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4704a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static constexpr struct {
4714a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      uint16_t Val;
472caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is64 : 1;
473caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is32 : 1;
474caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is16 : 1;
475caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is8 : 1;
476caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned IsXmm : 1;
477caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is64To8 : 1;
478caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is32To8 : 1;
479caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is16To8 : 1;
480caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned IsTrunc8Rcvr : 1;
481caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned IsAhRcvr : 1;
4824a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#define NUM_ALIASES_BITS 2
4834a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      SizeT NumAliases : (NUM_ALIASES_BITS + 1);
4844a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      uint16_t Aliases[1 << NUM_ALIASES_BITS];
4854a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#undef NUM_ALIASES_BITS
4864a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    } X8632RegTable[RegisterSet::Reg_NUM] = {
4875bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
4885bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
4895bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
4904a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  {                                                                            \
4914a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    RegisterSet::val, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
49229d15fd619f1d46f8e0c3d22932b9931c4b81367Jim Stichnoth        isTrunc8Rcvr, isAhRcvr, (SizeOf aliases).size(), aliases,              \
4935bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }                                                                            \
4944a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  ,
4954a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto        REGX8632_TABLE
496921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
4974a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    };
4984a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4994a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    for (SizeT ii = 0; ii < llvm::array_lengthof(X8632RegTable); ++ii) {
5004a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      const auto &Entry = X8632RegTable[ii];
5014a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
5024a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
5034a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
5044a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (FloatRegisters)[Entry.Val] = Entry.IsXmm;
5054a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (VectorRegisters)[Entry.Val] = Entry.IsXmm;
5064a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
5074a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
5084a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
5094a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
5104a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
5114a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM);
5124a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      for (int J = 0; J < Entry.NumAliases; J++) {
5134a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto        SizeT Alias = Entry.Aliases[J];
5144a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto        assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
5154a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto        (*RegisterAliases)[Entry.Val].set(Alias);
5164a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      }
5174a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (*RegisterAliases)[Entry.Val].set(Entry.Val);
5184a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    }
519bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto
520c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
521c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
522c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
523c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
524c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
5252544d4d2ef7e340664dc0748a5de966f0ee8ef08Jim Stichnoth    (*TypeToRegisterSet)[RC_i64] = InvalidRegisters;
526c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
527c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
528c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
529c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
530c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
531c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
532c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
533c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
534c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
535c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
536c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
537c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
538c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
539c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
540921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  }
541921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
542e82b560e649f8a68bcb252b9b002708e74d962d3John Porto  static SmallBitVector getRegisterSet(const ::Ice::ClFlags & /*Flags*/,
543e82b560e649f8a68bcb252b9b002708e74d962d3John Porto                                       TargetLowering::RegSetMask Include,
544e82b560e649f8a68bcb252b9b002708e74d962d3John Porto                                       TargetLowering::RegSetMask Exclude) {
545e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector Registers(RegisterSet::Reg_NUM);
546921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
5475bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
5485bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
5495bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
550921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave))         \
551921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = true;                                        \
552921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave))       \
553921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = true;                                        \
554921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer))      \
555921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = true;                                        \
556921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer))      \
557921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = true;                                        \
558921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave))         \
559921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = false;                                       \
560921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave))       \
561921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = false;                                       \
562921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer))      \
563921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = false;                                       \
564921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer))      \
565921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = false;
566921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
567921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    REGX8632_TABLE
568921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
569921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
570921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
571921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    return Registers;
572921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  }
573921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
574d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf  static void makeRandomRegisterPermutation(
575d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf      Cfg *Func, llvm::SmallVectorImpl<RegNumT> &Permutation,
576d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf      const SmallBitVector &ExcludeRegisters, uint64_t Salt) {
577921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // TODO(stichnot): Declaring Permutation this way loses type/size
57857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    // information. Fix this in conjunction with the caller-side TODO.
579921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    assert(Permutation.size() >= RegisterSet::Reg_NUM);
580921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // Expected upper bound on the number of registers in a single equivalence
58157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    // class. For x86-32, this would comprise the 8 XMM registers. This is for
582921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // performance, not correctness.
583921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static const unsigned MaxEquivalenceClassSize = 8;
5848aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    using RegisterList = llvm::SmallVector<RegNumT, MaxEquivalenceClassSize>;
5858072bae156fa62e51e02925997992c4908a2682fAndrew Scull    using EquivalenceClassMap = std::map<uint32_t, RegisterList>;
586921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    EquivalenceClassMap EquivalenceClasses;
587921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    SizeT NumShuffled = 0, NumPreserved = 0;
588921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
589921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto// Build up the equivalence classes of registers by looking at the register
590921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto// properties as well as whether the registers should be explicitly excluded
591921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto// from shuffling.
5925bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
5935bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
5945bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
595921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (ExcludeRegisters[RegisterSet::val]) {                                    \
596921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /* val stays the same in the resulting permutation. */                     \
597921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Permutation[RegisterSet::val] = RegisterSet::val;                          \
598921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    ++NumPreserved;                                                            \
599921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  } else {                                                                     \
6005bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    uint32_t AttrKey = 0;                                                      \
6015bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    uint32_t Index = 0;                                                        \
6025bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    /* Combine relevant attributes into an equivalence class key. */           \
6035bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (scratch << (AttrKey++));                                         \
6045bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (preserved << (AttrKey++));                                       \
6055bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is8 << (AttrKey++));                                             \
6065bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is16 << (AttrKey++));                                            \
6075bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is32 << (AttrKey++));                                            \
608c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (is64 << (AttrKey++));                                            \
6095bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (isXmm << (AttrKey++));                                           \
610c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (is16To8 << (AttrKey++));                                         \
611c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (is32To8 << (AttrKey++));                                         \
612c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (is64To8 << (AttrKey++));                                         \
613c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (isTrunc8Rcvr << (AttrKey++));                                    \
614921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /* val is assigned to an equivalence class based on its properties. */     \
615921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    EquivalenceClasses[Index].push_back(RegisterSet::val);                     \
616921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  }
617921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    REGX8632_TABLE
618921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
619921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
620aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu    // Create a random number generator for regalloc randomization.
621d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf    RandomNumberGenerator RNG(getFlags().getRandomSeed(),
622aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu                              RPE_RegAllocRandomization, Salt);
623aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu    RandomNumberGeneratorWrapper RNGW(RNG);
624921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
625921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // Shuffle the resulting equivalence classes.
626921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    for (auto I : EquivalenceClasses) {
627921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      const RegisterList &List = I.second;
628921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      RegisterList Shuffled(List);
629aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu      RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW);
630921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) {
631921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        Permutation[List[SI]] = Shuffled[SI];
632921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        ++NumShuffled;
633921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      }
634921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
635921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
636921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM);
637921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
638921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    if (Func->isVerbose(IceV_Random)) {
639921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      OstreamLocker L(Func->getContext());
640921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      Ostream &Str = Func->getContext()->getStrDump();
641921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      Str << "Register equivalence classes:\n";
642921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      for (auto I : EquivalenceClasses) {
643921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        Str << "{";
644921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        const RegisterList &List = I.second;
645921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        bool First = true;
6468aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth        for (RegNumT Register : List) {
647921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          if (!First)
648921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto            Str << " ";
649921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          First = false;
6505bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          Str << getRegName(Register);
651921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        }
652921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        Str << "}\n";
653921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      }
654921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
655921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  }
656921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
6578aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getRaxOrDie() {
6583c275ce1e832ba9ccfb730c4235db786cf080465John Porto    llvm::report_fatal_error("no rax in non-64-bit mode.");
6593c275ce1e832ba9ccfb730c4235db786cf080465John Porto  }
6603c275ce1e832ba9ccfb730c4235db786cf080465John Porto
6618aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getRdxOrDie() {
6623c275ce1e832ba9ccfb730c4235db786cf080465John Porto    llvm::report_fatal_error("no rdx in non-64-bit mode.");
6633c275ce1e832ba9ccfb730c4235db786cf080465John Porto  }
6643c275ce1e832ba9ccfb730c4235db786cf080465John Porto
6650c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // x86-32 calling convention:
6660c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  //
6670c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // * The first four arguments of vector type, regardless of their position
6680c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // relative to the other arguments in the argument list, are placed in
6690c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // registers xmm0 - xmm3.
6700c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  //
6710c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // This intends to match the section "IA-32 Function Calling Convention" of
6720c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // the document "OS X ABI Function Call Guide" by Apple.
6730c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr
674921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The maximum number of arguments to pass in XMM registers
6750c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_MAX_XMM_ARGS = 4;
6764163b9fcd92c0e2604a0d5f52ad1eccc86cad266David Sehr  /// The maximum number of arguments to pass in GPR registers
6770c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_MAX_GPR_ARGS = 0;
6780c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  /// Whether scalar floating point arguments are passed in XMM registers
6790c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = false;
6800c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  /// Get the register for a given argument slot in the XMM registers.
6818aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
6820c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    // TODO(sehr): Change to use the CCArg technique used in ARM32.
6830c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
6840c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr                  "Inconsistency between XMM register numbers and ordinals");
6850c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    if (ArgNum >= X86_MAX_XMM_ARGS) {
6865fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler      return RegNumT();
6870c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    }
6888aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
6890c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  }
6900c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  /// Get the register for a given argument slot in the GPRs.
6918aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
6920c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    assert(Ty == IceType_i64 || Ty == IceType_i32);
6930c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    (void)Ty;
6940c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    (void)ArgNum;
6955fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler    return RegNumT();
6960c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  }
6970c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr
698921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The number of bits in a byte
6990c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_CHAR_BIT = 8;
700921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it
701921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// is used as an argument to std::max(), and the default std::less<T> has an
702921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// operator(T const&, T const&) which requires this member to have an
703921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// address.
7045d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const uint32_t X86_STACK_ALIGNMENT_BYTES;
705921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// Size of the return address on the stack
7060c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 4;
707921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The number of different NOP instructions
7080c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5;
7095d0acff3a2fa421923392aadb4df2742064b6248John Porto
710cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// \name Limits for unrolling memory intrinsics.
711cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// @{
712cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
713cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
71435e160025c5a7005f97c5ad55120999cf83a4ce1Jim Stichnoth  static constexpr uint32_t MEMSET_UNROLL_LIMIT = 8;
715cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// @}
716cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull
71757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Value is in bytes. Return Value adjusted to the next highest multiple of
71857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// the stack alignment.
7195d0acff3a2fa421923392aadb4df2742064b6248John Porto  static uint32_t applyStackAlignment(uint32_t Value) {
7205d0acff3a2fa421923392aadb4df2742064b6248John Porto    return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
7215d0acff3a2fa421923392aadb4df2742064b6248John Porto  }
7225d0acff3a2fa421923392aadb4df2742064b6248John Porto
723921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// Return the type which the elements of the vector have in the X86
724921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// representation of the vector.
7255d0acff3a2fa421923392aadb4df2742064b6248John Porto  static Type getInVectorElementType(Type Ty) {
7265d0acff3a2fa421923392aadb4df2742064b6248John Porto    assert(isVectorType(Ty));
7272d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth    assert(Ty < TableTypeX8632AttributesSize);
7285d0acff3a2fa421923392aadb4df2742064b6248John Porto    return TableTypeX8632Attributes[Ty].InVectorElementType;
7295d0acff3a2fa421923392aadb4df2742064b6248John Porto  }
7305d0acff3a2fa421923392aadb4df2742064b6248John Porto
7315d0acff3a2fa421923392aadb4df2742064b6248John Porto  // Note: The following data structures are defined in
7325d0acff3a2fa421923392aadb4df2742064b6248John Porto  // IceTargetLoweringX8632.cpp.
7335d0acff3a2fa421923392aadb4df2742064b6248John Porto
734921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The following table summarizes the logic for lowering the fcmp
735921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// instruction. There is one table entry for each of the 16 conditions.
736921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  ///
737921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The first four columns describe the case when the operands are floating
73857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// point scalar values. A comment in lowerFcmp() describes the lowering
73957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// template. In the most general case, there is a compare followed by two
740921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// conditional branches, because some fcmp conditions don't map to a single
74157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// x86 conditional branch. However, in many cases it is possible to swap the
74257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// operands in the comparison and have a single conditional branch. Since
743921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// it's quite tedious to validate the table by hand, good execution tests are
744921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// helpful.
745921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  ///
746921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The last two columns describe the case when the operands are vectors of
74757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// floating point values. For most fcmp conditions, there is a clear mapping
74857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// to a single x86 cmpps instruction variant. Some fcmp conditions require
749921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// special code to handle and these are marked in the table with a
750921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// Cmpps_Invalid predicate.
751921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// {@
7525d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const struct TableFcmpType {
7535d0acff3a2fa421923392aadb4df2742064b6248John Porto    uint32_t Default;
7545d0acff3a2fa421923392aadb4df2742064b6248John Porto    bool SwapScalarOperands;
755921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Cond::BrCond C1, C2;
7565d0acff3a2fa421923392aadb4df2742064b6248John Porto    bool SwapVectorOperands;
757921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Cond::CmppsCond Predicate;
7585d0acff3a2fa421923392aadb4df2742064b6248John Porto  } TableFcmp[];
7595d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const size_t TableFcmpSize;
760921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// @}
7615d0acff3a2fa421923392aadb4df2742064b6248John Porto
762921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The following table summarizes the logic for lowering the icmp instruction
76357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// for i32 and narrower types. Each icmp condition has a clear mapping to an
764921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// x86 conditional branch instruction.
765921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// {@
766921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[];
7675d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const size_t TableIcmp32Size;
768921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// @}
7695d0acff3a2fa421923392aadb4df2742064b6248John Porto
770921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The following table summarizes the logic for lowering the icmp instruction
77157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
77257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// conditional branches are needed. For the other conditions, three separate
773921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// conditional branches are needed.
774921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// {@
7755d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const struct TableIcmp64Type {
776921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Cond::BrCond C1, C2, C3;
7775d0acff3a2fa421923392aadb4df2742064b6248John Porto  } TableIcmp64[];
7785d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const size_t TableIcmp64Size;
779921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// @}
7805d0acff3a2fa421923392aadb4df2742064b6248John Porto
781921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
7822d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth    assert(Cond < TableIcmp32Size);
7832d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth    return TableIcmp32[Cond].Mapping;
7845d0acff3a2fa421923392aadb4df2742064b6248John Porto  }
7855d0acff3a2fa421923392aadb4df2742064b6248John Porto
7865d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const struct TableTypeX8632AttributesType {
7875d0acff3a2fa421923392aadb4df2742064b6248John Porto    Type InVectorElementType;
7885d0acff3a2fa421923392aadb4df2742064b6248John Porto  } TableTypeX8632Attributes[];
7895d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const size_t TableTypeX8632AttributesSize;
790921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
791921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //----------------------------------------------------------------------------
792921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //      __  __   __  ______  ______
793921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //    /\ \/\ "-.\ \/\  ___\/\__  _\
794921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //    \ \ \ \ \-.  \ \___  \/_/\ \/
795921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //     \ \_\ \_\\"\_\/\_____\ \ \_\
796921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //      \/_/\/_/ \/_/\/_____/  \/_/
797921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //
798921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //----------------------------------------------------------------------------
7994a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using Traits = TargetX8632Traits;
8004a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using Insts = ::Ice::X8632::Insts<Traits>;
801921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
8024a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using TargetLowering = ::Ice::X8632::TargetX86Base<Traits>;
8034a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using ConcreteTarget = ::Ice::X8632::TargetX8632;
8044a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using Assembler = ::Ice::X8632::AssemblerX86Base<Traits>;
805921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
80657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// X86Operand extends the Operand hierarchy. Its subclasses are X86OperandMem
80757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// and VariableSplit.
808921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  class X86Operand : public ::Ice::Operand {
809921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86Operand() = delete;
810921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86Operand(const X86Operand &) = delete;
811921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86Operand &operator=(const X86Operand &) = delete;
812921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
813921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  public:
814921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    enum OperandKindX8632 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit };
815921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    using ::Ice::Operand::dump;
816921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
817921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void dump(const Cfg *, Ostream &Str) const override;
818921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
819921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  protected:
820921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86Operand(OperandKindX8632 Kind, Type Ty)
821921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {}
822921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  };
823921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
824921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// X86OperandMem represents the m32 addressing mode, with optional base and
825921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// index registers, a constant offset, and a fixed shift value for the index
826921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// register.
827921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  class X86OperandMem : public X86Operand {
828921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86OperandMem() = delete;
829921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86OperandMem(const X86OperandMem &) = delete;
830921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86OperandMem &operator=(const X86OperandMem &) = delete;
831921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
832921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  public:
833921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    enum SegmentRegisters {
834921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      DefaultSegment = -1,
835921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, name, prefix) val,
836921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      SEG_REGX8632_TABLE
837921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
838921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          SegReg_NUM
839921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    };
840921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
841921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto                                 Constant *Offset, Variable *Index = nullptr,
842921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto                                 uint16_t Shift = 0,
8438ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth                                 SegmentRegisters SegmentReg = DefaultSegment,
84456958cb33d3c1d045f2844408d825442d523f59fJohn Porto                                 bool IsRebased = false) {
8458ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth      return new (Func->allocate<X86OperandMem>()) X86OperandMem(
84656958cb33d3c1d045f2844408d825442d523f59fJohn Porto          Func, Ty, Base, Offset, Index, Shift, SegmentReg, IsRebased);
84756958cb33d3c1d045f2844408d825442d523f59fJohn Porto    }
84856958cb33d3c1d045f2844408d825442d523f59fJohn Porto    static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
84956958cb33d3c1d045f2844408d825442d523f59fJohn Porto                                 Constant *Offset, bool IsRebased) {
85056958cb33d3c1d045f2844408d825442d523f59fJohn Porto      constexpr Variable *NoIndex = nullptr;
85156958cb33d3c1d045f2844408d825442d523f59fJohn Porto      constexpr uint16_t NoShift = 0;
85256958cb33d3c1d045f2844408d825442d523f59fJohn Porto      return new (Func->allocate<X86OperandMem>()) X86OperandMem(
85356958cb33d3c1d045f2844408d825442d523f59fJohn Porto          Func, Ty, Base, Offset, NoIndex, NoShift, DefaultSegment, IsRebased);
854921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
855921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Variable *getBase() const { return Base; }
856921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Constant *getOffset() const { return Offset; }
857921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Variable *getIndex() const { return Index; }
858921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    uint16_t getShift() const { return Shift; }
859921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    SegmentRegisters getSegmentRegister() const { return SegmentReg; }
860921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void emitSegmentOverride(Assembler *Asm) const;
86156958cb33d3c1d045f2844408d825442d523f59fJohn Porto    bool getIsRebased() const { return IsRebased; }
86256958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Address toAsmAddress(Assembler *Asm, const Ice::TargetLowering *Target,
86356958cb33d3c1d045f2844408d825442d523f59fJohn Porto                         bool LeaAddr = false) const;
864921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
865921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void emit(const Cfg *Func) const override;
866921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    using X86Operand::dump;
867921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void dump(const Cfg *Func, Ostream &Str) const override;
868921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
869921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static bool classof(const Operand *Operand) {
870921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return Operand->getKind() == static_cast<OperandKind>(kMem);
871921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
872921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
873921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void setRandomized(bool R) { Randomized = R; }
874921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
875921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    bool getRandomized() const { return Randomized; }
876921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
877921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  private:
878921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
8798ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth                  Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg,
88056958cb33d3c1d045f2844408d825442d523f59fJohn Porto                  bool IsRebased);
88156958cb33d3c1d045f2844408d825442d523f59fJohn Porto
88256958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Variable *const Base;
88356958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Constant *const Offset;
88456958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Variable *const Index;
88556958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const uint16_t Shift;
88656958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const SegmentRegisters SegmentReg : 16;
88756958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const bool IsRebased;
888921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// A flag to show if this memory operand is a randomized one. Randomized
889921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// memory operands are generated in
890921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// TargetX86Base::randomizeOrPoolImmediate()
8918ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth    bool Randomized = false;
892921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  };
893921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
894921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// VariableSplit is a way to treat an f64 memory location as a pair of i32
89557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// locations (Low and High). This is needed for some cases of the Bitcast
89657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction. Since it's not possible for integer registers to access the
897921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// XMM registers and vice versa, the lowering forces the f64 to be spilled to
898921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// the stack and then accesses through the VariableSplit.
899921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit
900921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  // targets can natively handle these.
901921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  class VariableSplit : public X86Operand {
902921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    VariableSplit() = delete;
903921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    VariableSplit(const VariableSplit &) = delete;
904921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    VariableSplit &operator=(const VariableSplit &) = delete;
905921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
906921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  public:
907921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    enum Portion { Low, High };
908921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
909921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return new (Func->allocate<VariableSplit>())
910921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          VariableSplit(Func, Var, Part);
911921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
912921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    int32_t getOffset() const { return Part == High ? 4 : 0; }
913921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
914921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Address toAsmAddress(const Cfg *Func) const;
915921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void emit(const Cfg *Func) const override;
916921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    using X86Operand::dump;
917921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void dump(const Cfg *Func, Ostream &Str) const override;
918921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
919921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static bool classof(const Operand *Operand) {
920921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return Operand->getKind() == static_cast<OperandKind>(kSplit);
921921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
922921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
923921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  private:
924921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    VariableSplit(Cfg *Func, Variable *Var, Portion Part)
925921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) {
926921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      assert(Var->getType() == IceType_f64);
927921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      Vars = Func->allocateArrayOf<Variable *>(1);
928921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      Vars[0] = Var;
929921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      NumVars = 1;
930921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
931921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
932921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Variable *Var;
933921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Portion Part;
934921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  };
935921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
936921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  // Note: The following data structures are defined in IceInstX8632.cpp.
937921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
938921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const struct InstBrAttributesType {
939921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Cond::BrCond Opposite;
940921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *DisplayString;
941921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *EmitString;
942921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  } InstBrAttributes[];
943921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
944921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const struct InstCmppsAttributesType {
945921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *EmitString;
946921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  } InstCmppsAttributes[];
947921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
948921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const struct TypeAttributesType {
9497638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *CvtString;      // i (integer), s (single FP), d (double FP)
9507638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *SdSsString;     // ss, sd, or <blank>
9517638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *PdPsString;     // ps, pd, or <blank>
952956cfd60e8ee9efcc374cd19513bbf35a20e52eeNicolas Capens    const char *SpSdString;     // ss, sd, ps, pd, or <blank>
9537638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *IntegralString; // b, w, d, or <blank>
9547638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *UnpackString;   // bw, wd, dq, or <blank>
9557638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *PackString;     // wb, dw, or <blank>
9567638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *WidthString;    // b, w, l, q, or <blank>
9577638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *FldString;      // s, l, or <blank>
958921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  } TypeAttributes[];
959921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
960921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const char *InstSegmentRegNames[];
961921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
962921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static uint8_t InstSegmentPrefixes[];
9635d0acff3a2fa421923392aadb4df2742064b6248John Porto};
9645d0acff3a2fa421923392aadb4df2742064b6248John Porto
9654a56686b5b56db6803f90ad53514bf2fa190d9f7John Portousing Traits = ::Ice::X8632::TargetX8632Traits;
9665d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace X8632
9675d0acff3a2fa421923392aadb4df2742064b6248John Porto
9685d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace Ice
9695d0acff3a2fa421923392aadb4df2742064b6248John Porto
9705d0acff3a2fa421923392aadb4df2742064b6248John Porto#endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
971