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