IceTargetLoweringX8632Traits.h revision bb0a5fe31a71fdc5b3292d62169f428d531437a4
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 11921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto/// This file 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" 255d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceTargetLoweringX8632.def" 26921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#include "IceTargetLowering.h" 275d0acff3a2fa421923392aadb4df2742064b6248John Porto 28bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto#include <array> 29bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto 305d0acff3a2fa421923392aadb4df2742064b6248John Portonamespace Ice { 315d0acff3a2fa421923392aadb4df2742064b6248John Porto 325d0acff3a2fa421923392aadb4df2742064b6248John Portoclass TargetX8632; 335d0acff3a2fa421923392aadb4df2742064b6248John Porto 34921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Portonamespace X8632 { 35921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Portoclass AssemblerX8632; 36921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto} // end of namespace X8632 37921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 385d0acff3a2fa421923392aadb4df2742064b6248John Portonamespace X86Internal { 395d0acff3a2fa421923392aadb4df2742064b6248John Porto 40921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Portotemplate <class Machine> struct Insts; 415d0acff3a2fa421923392aadb4df2742064b6248John Portotemplate <class Machine> struct MachineTraits; 425aeed955e17bac8cc44cc6d2b6ff7513cc714c2fJohn Portotemplate <class Machine> class TargetX86Base; 435d0acff3a2fa421923392aadb4df2742064b6248John Porto 445d0acff3a2fa421923392aadb4df2742064b6248John Portotemplate <> struct MachineTraits<TargetX8632> { 455d0acff3a2fa421923392aadb4df2742064b6248John Porto //---------------------------------------------------------------------------- 465d0acff3a2fa421923392aadb4df2742064b6248John Porto // ______ ______ __ __ 475d0acff3a2fa421923392aadb4df2742064b6248John Porto // /\ __ \/\ ___\/\ "-./ \ 485d0acff3a2fa421923392aadb4df2742064b6248John Porto // \ \ __ \ \___ \ \ \-./\ \ 495d0acff3a2fa421923392aadb4df2742064b6248John Porto // \ \_\ \_\/\_____\ \_\ \ \_\ 505d0acff3a2fa421923392aadb4df2742064b6248John Porto // \/_/\/_/\/_____/\/_/ \/_/ 515d0acff3a2fa421923392aadb4df2742064b6248John Porto // 525d0acff3a2fa421923392aadb4df2742064b6248John Porto //---------------------------------------------------------------------------- 532fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static constexpr bool Is64Bit = false; 542fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static constexpr bool HasPopa = true; 552fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static constexpr bool HasPusha = true; 562fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static constexpr bool UsesX87 = true; 572fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static constexpr ::Ice::RegX8632::GPRRegister Last8BitGPR = 582fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto ::Ice::RegX8632::GPRRegister::Encoded_Reg_ebx; 592fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 605d0acff3a2fa421923392aadb4df2742064b6248John Porto enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; 615d0acff3a2fa421923392aadb4df2742064b6248John Porto 625d0acff3a2fa421923392aadb4df2742064b6248John Porto using GPRRegister = ::Ice::RegX8632::GPRRegister; 635d0acff3a2fa421923392aadb4df2742064b6248John Porto using XmmRegister = ::Ice::RegX8632::XmmRegister; 645d0acff3a2fa421923392aadb4df2742064b6248John Porto using ByteRegister = ::Ice::RegX8632::ByteRegister; 655d0acff3a2fa421923392aadb4df2742064b6248John Porto using X87STRegister = ::Ice::RegX8632::X87STRegister; 665d0acff3a2fa421923392aadb4df2742064b6248John Porto 675d0acff3a2fa421923392aadb4df2742064b6248John Porto using Cond = ::Ice::CondX86; 685d0acff3a2fa421923392aadb4df2742064b6248John Porto 695d0acff3a2fa421923392aadb4df2742064b6248John Porto using RegisterSet = ::Ice::RegX8632; 705d0acff3a2fa421923392aadb4df2742064b6248John Porto static const GPRRegister Encoded_Reg_Accumulator = RegX8632::Encoded_Reg_eax; 715d0acff3a2fa421923392aadb4df2742064b6248John Porto static const GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx; 725d0acff3a2fa421923392aadb4df2742064b6248John Porto static const FixupKind PcRelFixup = llvm::ELF::R_386_PC32; 731d235425dab1f3dd059973fc53f1b1d5879469e3John Porto static const FixupKind RelFixup = llvm::ELF::R_386_32; 745d0acff3a2fa421923392aadb4df2742064b6248John Porto 755d0acff3a2fa421923392aadb4df2742064b6248John Porto class Operand { 765d0acff3a2fa421923392aadb4df2742064b6248John Porto public: 775d0acff3a2fa421923392aadb4df2742064b6248John Porto Operand(const Operand &other) 78921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto : fixup_(other.fixup_), length_(other.length_) { 795d0acff3a2fa421923392aadb4df2742064b6248John Porto memmove(&encoding_[0], &other.encoding_[0], other.length_); 805d0acff3a2fa421923392aadb4df2742064b6248John Porto } 815d0acff3a2fa421923392aadb4df2742064b6248John Porto 825d0acff3a2fa421923392aadb4df2742064b6248John Porto Operand &operator=(const Operand &other) { 835d0acff3a2fa421923392aadb4df2742064b6248John Porto length_ = other.length_; 845d0acff3a2fa421923392aadb4df2742064b6248John Porto fixup_ = other.fixup_; 855d0acff3a2fa421923392aadb4df2742064b6248John Porto memmove(&encoding_[0], &other.encoding_[0], other.length_); 865d0acff3a2fa421923392aadb4df2742064b6248John Porto return *this; 875d0acff3a2fa421923392aadb4df2742064b6248John Porto } 885d0acff3a2fa421923392aadb4df2742064b6248John Porto 895d0acff3a2fa421923392aadb4df2742064b6248John Porto uint8_t mod() const { return (encoding_at(0) >> 6) & 3; } 905d0acff3a2fa421923392aadb4df2742064b6248John Porto 915d0acff3a2fa421923392aadb4df2742064b6248John Porto GPRRegister rm() const { 925d0acff3a2fa421923392aadb4df2742064b6248John Porto return static_cast<GPRRegister>(encoding_at(0) & 7); 935d0acff3a2fa421923392aadb4df2742064b6248John Porto } 945d0acff3a2fa421923392aadb4df2742064b6248John Porto 955d0acff3a2fa421923392aadb4df2742064b6248John Porto ScaleFactor scale() const { 965d0acff3a2fa421923392aadb4df2742064b6248John Porto return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); 975d0acff3a2fa421923392aadb4df2742064b6248John Porto } 985d0acff3a2fa421923392aadb4df2742064b6248John Porto 995d0acff3a2fa421923392aadb4df2742064b6248John Porto GPRRegister index() const { 1005d0acff3a2fa421923392aadb4df2742064b6248John Porto return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7); 1015d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1025d0acff3a2fa421923392aadb4df2742064b6248John Porto 1035d0acff3a2fa421923392aadb4df2742064b6248John Porto GPRRegister base() const { 1045d0acff3a2fa421923392aadb4df2742064b6248John Porto return static_cast<GPRRegister>(encoding_at(1) & 7); 1055d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1065d0acff3a2fa421923392aadb4df2742064b6248John Porto 1075d0acff3a2fa421923392aadb4df2742064b6248John Porto int8_t disp8() const { 1085d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(length_ >= 2); 1095d0acff3a2fa421923392aadb4df2742064b6248John Porto return static_cast<int8_t>(encoding_[length_ - 1]); 1105d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1115d0acff3a2fa421923392aadb4df2742064b6248John Porto 1125d0acff3a2fa421923392aadb4df2742064b6248John Porto int32_t disp32() const { 1135d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(length_ >= 5); 1145d0acff3a2fa421923392aadb4df2742064b6248John Porto return bit_copy<int32_t>(encoding_[length_ - 4]); 1155d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1165d0acff3a2fa421923392aadb4df2742064b6248John Porto 1175d0acff3a2fa421923392aadb4df2742064b6248John Porto AssemblerFixup *fixup() const { return fixup_; } 1185d0acff3a2fa421923392aadb4df2742064b6248John Porto 1195d0acff3a2fa421923392aadb4df2742064b6248John Porto protected: 120921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Operand() : fixup_(nullptr), length_(0) {} // Needed by subclass Address. 1215d0acff3a2fa421923392aadb4df2742064b6248John Porto 1225d0acff3a2fa421923392aadb4df2742064b6248John Porto void SetModRM(int mod, GPRRegister rm) { 1235d0acff3a2fa421923392aadb4df2742064b6248John Porto assert((mod & ~3) == 0); 1245d0acff3a2fa421923392aadb4df2742064b6248John Porto encoding_[0] = (mod << 6) | rm; 1255d0acff3a2fa421923392aadb4df2742064b6248John Porto length_ = 1; 1265d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1275d0acff3a2fa421923392aadb4df2742064b6248John Porto 1285d0acff3a2fa421923392aadb4df2742064b6248John Porto void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { 1295d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(length_ == 1); 1305d0acff3a2fa421923392aadb4df2742064b6248John Porto assert((scale & ~3) == 0); 1315d0acff3a2fa421923392aadb4df2742064b6248John Porto encoding_[1] = (scale << 6) | (index << 3) | base; 1325d0acff3a2fa421923392aadb4df2742064b6248John Porto length_ = 2; 1335d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1345d0acff3a2fa421923392aadb4df2742064b6248John Porto 1355d0acff3a2fa421923392aadb4df2742064b6248John Porto void SetDisp8(int8_t disp) { 1365d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(length_ == 1 || length_ == 2); 1375d0acff3a2fa421923392aadb4df2742064b6248John Porto encoding_[length_++] = static_cast<uint8_t>(disp); 1385d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1395d0acff3a2fa421923392aadb4df2742064b6248John Porto 1405d0acff3a2fa421923392aadb4df2742064b6248John Porto void SetDisp32(int32_t disp) { 1415d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(length_ == 1 || length_ == 2); 1425d0acff3a2fa421923392aadb4df2742064b6248John Porto intptr_t disp_size = sizeof(disp); 1435d0acff3a2fa421923392aadb4df2742064b6248John Porto memmove(&encoding_[length_], &disp, disp_size); 1445d0acff3a2fa421923392aadb4df2742064b6248John Porto length_ += disp_size; 1455d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1465d0acff3a2fa421923392aadb4df2742064b6248John Porto 1475d0acff3a2fa421923392aadb4df2742064b6248John Porto void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; } 1485d0acff3a2fa421923392aadb4df2742064b6248John Porto 1495d0acff3a2fa421923392aadb4df2742064b6248John Porto private: 1505d0acff3a2fa421923392aadb4df2742064b6248John Porto AssemblerFixup *fixup_; 151921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto uint8_t encoding_[6]; 152921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto uint8_t length_; 1535d0acff3a2fa421923392aadb4df2742064b6248John Porto 1545d0acff3a2fa421923392aadb4df2742064b6248John Porto explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); } 1555d0acff3a2fa421923392aadb4df2742064b6248John Porto 156921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// Get the operand encoding byte at the given index. 1575d0acff3a2fa421923392aadb4df2742064b6248John Porto uint8_t encoding_at(intptr_t index) const { 1585d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(index >= 0 && index < length_); 1595d0acff3a2fa421923392aadb4df2742064b6248John Porto return encoding_[index]; 1605d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1615d0acff3a2fa421923392aadb4df2742064b6248John Porto 162921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// Returns whether or not this operand is really the given register in 163921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// disguise. Used from the assembler to generate better encodings. 1645d0acff3a2fa421923392aadb4df2742064b6248John Porto bool IsRegister(GPRRegister reg) const { 1655d0acff3a2fa421923392aadb4df2742064b6248John Porto return ((encoding_[0] & 0xF8) == 1665d0acff3a2fa421923392aadb4df2742064b6248John Porto 0xC0) // Addressing mode is register only. 1675d0acff3a2fa421923392aadb4df2742064b6248John Porto && 1685d0acff3a2fa421923392aadb4df2742064b6248John Porto ((encoding_[0] & 0x07) == reg); // Register codes match. 1695d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1705d0acff3a2fa421923392aadb4df2742064b6248John Porto 1715d0acff3a2fa421923392aadb4df2742064b6248John Porto template <class> friend class AssemblerX86Base; 1725d0acff3a2fa421923392aadb4df2742064b6248John Porto }; 1735d0acff3a2fa421923392aadb4df2742064b6248John Porto 1745d0acff3a2fa421923392aadb4df2742064b6248John Porto class Address : public Operand { 1755d0acff3a2fa421923392aadb4df2742064b6248John Porto Address() = delete; 1765d0acff3a2fa421923392aadb4df2742064b6248John Porto 1775d0acff3a2fa421923392aadb4df2742064b6248John Porto public: 1785d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(const Address &other) : Operand(other) {} 1795d0acff3a2fa421923392aadb4df2742064b6248John Porto 1805d0acff3a2fa421923392aadb4df2742064b6248John Porto Address &operator=(const Address &other) { 1815d0acff3a2fa421923392aadb4df2742064b6248John Porto Operand::operator=(other); 1825d0acff3a2fa421923392aadb4df2742064b6248John Porto return *this; 1835d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1845d0acff3a2fa421923392aadb4df2742064b6248John Porto 1855d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(GPRRegister base, int32_t disp) { 1865d0acff3a2fa421923392aadb4df2742064b6248John Porto if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) { 1875d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(0, base); 1885d0acff3a2fa421923392aadb4df2742064b6248John Porto if (base == RegX8632::Encoded_Reg_esp) 1895d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); 1905d0acff3a2fa421923392aadb4df2742064b6248John Porto } else if (Utils::IsInt(8, disp)) { 1915d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(1, base); 1925d0acff3a2fa421923392aadb4df2742064b6248John Porto if (base == RegX8632::Encoded_Reg_esp) 1935d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); 1945d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp8(disp); 1955d0acff3a2fa421923392aadb4df2742064b6248John Porto } else { 1965d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(2, base); 1975d0acff3a2fa421923392aadb4df2742064b6248John Porto if (base == RegX8632::Encoded_Reg_esp) 1985d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); 1995d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp32(disp); 2005d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2015d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2025d0acff3a2fa421923392aadb4df2742064b6248John Porto 2035d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(GPRRegister index, ScaleFactor scale, int32_t disp) { 2045d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode. 2055d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(0, RegX8632::Encoded_Reg_esp); 2065d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(scale, index, RegX8632::Encoded_Reg_ebp); 2075d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp32(disp); 2085d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2095d0acff3a2fa421923392aadb4df2742064b6248John Porto 2105d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(GPRRegister base, GPRRegister index, ScaleFactor scale, 2115d0acff3a2fa421923392aadb4df2742064b6248John Porto int32_t disp) { 2125d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode. 2135d0acff3a2fa421923392aadb4df2742064b6248John Porto if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) { 2145d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(0, RegX8632::Encoded_Reg_esp); 2155d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(scale, index, base); 2165d0acff3a2fa421923392aadb4df2742064b6248John Porto } else if (Utils::IsInt(8, disp)) { 2175d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(1, RegX8632::Encoded_Reg_esp); 2185d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(scale, index, base); 2195d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp8(disp); 2205d0acff3a2fa421923392aadb4df2742064b6248John Porto } else { 2215d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(2, RegX8632::Encoded_Reg_esp); 2225d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(scale, index, base); 2235d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp32(disp); 2245d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2255d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2265d0acff3a2fa421923392aadb4df2742064b6248John Porto 227921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// AbsoluteTag is a special tag used by clients to create an absolute 228921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// Address. 2295d0acff3a2fa421923392aadb4df2742064b6248John Porto enum AbsoluteTag { ABSOLUTE }; 2305d0acff3a2fa421923392aadb4df2742064b6248John Porto 2315d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(AbsoluteTag, const uintptr_t Addr) { 2325d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(0, RegX8632::Encoded_Reg_ebp); 2335d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp32(Addr); 2345d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2355d0acff3a2fa421923392aadb4df2742064b6248John Porto 2365d0acff3a2fa421923392aadb4df2742064b6248John Porto // TODO(jpp): remove this. 2375d0acff3a2fa421923392aadb4df2742064b6248John Porto static Address Absolute(const uintptr_t Addr) { 2385d0acff3a2fa421923392aadb4df2742064b6248John Porto return Address(ABSOLUTE, Addr); 2395d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2405d0acff3a2fa421923392aadb4df2742064b6248John Porto 2415d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(AbsoluteTag, RelocOffsetT Offset, AssemblerFixup *Fixup) { 2425d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(0, RegX8632::Encoded_Reg_ebp); 2435d0acff3a2fa421923392aadb4df2742064b6248John Porto // Use the Offset in the displacement for now. If we decide to process 2445d0acff3a2fa421923392aadb4df2742064b6248John Porto // fixups later, we'll need to patch up the emitted displacement. 2455d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp32(Offset); 2465d0acff3a2fa421923392aadb4df2742064b6248John Porto SetFixup(Fixup); 2475d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2485d0acff3a2fa421923392aadb4df2742064b6248John Porto 2495d0acff3a2fa421923392aadb4df2742064b6248John Porto // TODO(jpp): remove this. 2505d0acff3a2fa421923392aadb4df2742064b6248John Porto static Address Absolute(RelocOffsetT Offset, AssemblerFixup *Fixup) { 2515d0acff3a2fa421923392aadb4df2742064b6248John Porto return Address(ABSOLUTE, Offset, Fixup); 2525d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2535d0acff3a2fa421923392aadb4df2742064b6248John Porto 2545d0acff3a2fa421923392aadb4df2742064b6248John Porto static Address ofConstPool(Assembler *Asm, const Constant *Imm) { 2555d0acff3a2fa421923392aadb4df2742064b6248John Porto AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm); 2565d0acff3a2fa421923392aadb4df2742064b6248John Porto const RelocOffsetT Offset = 0; 2575d0acff3a2fa421923392aadb4df2742064b6248John Porto return Address(ABSOLUTE, Offset, Fixup); 2585d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2595d0acff3a2fa421923392aadb4df2742064b6248John Porto }; 2605d0acff3a2fa421923392aadb4df2742064b6248John Porto 2615d0acff3a2fa421923392aadb4df2742064b6248John Porto //---------------------------------------------------------------------------- 2625d0acff3a2fa421923392aadb4df2742064b6248John Porto // __ ______ __ __ ______ ______ __ __ __ ______ 2635d0acff3a2fa421923392aadb4df2742064b6248John Porto // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ 2645d0acff3a2fa421923392aadb4df2742064b6248John Porto // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ 2655d0acff3a2fa421923392aadb4df2742064b6248John Porto // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ 2665d0acff3a2fa421923392aadb4df2742064b6248John Porto // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ 2675d0acff3a2fa421923392aadb4df2742064b6248John Porto // 2685d0acff3a2fa421923392aadb4df2742064b6248John Porto //---------------------------------------------------------------------------- 2695d0acff3a2fa421923392aadb4df2742064b6248John Porto enum InstructionSet { 2705d0acff3a2fa421923392aadb4df2742064b6248John Porto Begin, 2715d0acff3a2fa421923392aadb4df2742064b6248John Porto // SSE2 is the PNaCl baseline instruction set. 2725d0acff3a2fa421923392aadb4df2742064b6248John Porto SSE2 = Begin, 2735d0acff3a2fa421923392aadb4df2742064b6248John Porto SSE4_1, 2745d0acff3a2fa421923392aadb4df2742064b6248John Porto End 2755d0acff3a2fa421923392aadb4df2742064b6248John Porto }; 2765d0acff3a2fa421923392aadb4df2742064b6248John Porto 277921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static const char *TargetName; 2781d235425dab1f3dd059973fc53f1b1d5879469e3John Porto static constexpr Type WordType = IceType_i32; 279921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 280921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static IceString getRegName(SizeT RegNum, Type Ty) { 281921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto assert(RegNum < RegisterSet::Reg_NUM); 282921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static const char *RegNames8[] = { 283921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ 284921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto frameptr, isI8, isInt, isFP) \ 285921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto name8, 286921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto REGX8632_TABLE 287921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X 288921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto }; 289921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 290921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static const char *RegNames16[] = { 291921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ 292921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto frameptr, isI8, isInt, isFP) \ 293921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto name16, 294921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto REGX8632_TABLE 295921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X 296921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto }; 297921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 298921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static const char *RegNames[] = { 299921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ 300921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto frameptr, isI8, isInt, isFP) \ 301921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto name, 302921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto REGX8632_TABLE 303921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X 304921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto }; 305921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 306921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto switch (Ty) { 307921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto case IceType_i1: 308921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto case IceType_i8: 309921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto return RegNames8[RegNum]; 310921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto case IceType_i16: 311921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto return RegNames16[RegNum]; 312921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto default: 313921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto return RegNames[RegNum]; 314921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 315921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 316921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 317bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto static void initRegisterSet( 318bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto std::array<llvm::SmallBitVector, IceType_NUM> *TypeToRegisterSet, 319bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto std::array<llvm::SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases, 320bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto llvm::SmallBitVector *ScratchRegs) { 321bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto llvm::SmallBitVector IntegerRegisters(RegisterSet::Reg_NUM); 322bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto llvm::SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM); 323bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto llvm::SmallBitVector FloatRegisters(RegisterSet::Reg_NUM); 324bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto llvm::SmallBitVector VectorRegisters(RegisterSet::Reg_NUM); 325bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto llvm::SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM); 326bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto ScratchRegs->resize(RegisterSet::Reg_NUM); 327921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ 328921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto frameptr, isI8, isInt, isFP) \ 329bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (IntegerRegisters)[RegisterSet::val] = isInt; \ 330bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (IntegerRegistersI8)[RegisterSet::val] = isI8; \ 331bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (FloatRegisters)[RegisterSet::val] = isFP; \ 332bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (VectorRegisters)[RegisterSet::val] = isFP; \ 333bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*RegisterAliases)[RegisterSet::val].resize(RegisterSet::Reg_NUM); \ 334bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*RegisterAliases)[RegisterSet::val].set(RegisterSet::val); \ 335921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto (*ScratchRegs)[RegisterSet::val] = scratch; 336921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto REGX8632_TABLE; 337921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X 338bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto 339bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_void] = InvalidRegisters; 340bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_i1] = IntegerRegistersI8; 341bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_i8] = IntegerRegistersI8; 342bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_i16] = IntegerRegisters; 343bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_i32] = IntegerRegisters; 344bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_i64] = IntegerRegisters; 345bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_f32] = FloatRegisters; 346bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_f64] = FloatRegisters; 347bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_v4i1] = VectorRegisters; 348bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_v8i1] = VectorRegisters; 349bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_v16i1] = VectorRegisters; 350bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_v16i8] = VectorRegisters; 351bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_v8i16] = VectorRegisters; 352bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_v4i32] = VectorRegisters; 353bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto (*TypeToRegisterSet)[IceType_v4f32] = VectorRegisters; 354921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 355921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 356921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static llvm::SmallBitVector 357921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto getRegisterSet(TargetLowering::RegSetMask Include, 358921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto TargetLowering::RegSetMask Exclude) { 359921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto llvm::SmallBitVector Registers(RegisterSet::Reg_NUM); 360921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 361921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ 362921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto frameptr, isI8, isInt, isFP) \ 363921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave)) \ 364921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Registers[RegisterSet::val] = true; \ 365921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave)) \ 366921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Registers[RegisterSet::val] = true; \ 367921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer)) \ 368921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Registers[RegisterSet::val] = true; \ 369921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer)) \ 370921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Registers[RegisterSet::val] = true; \ 371921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave)) \ 372921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Registers[RegisterSet::val] = false; \ 373921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave)) \ 374921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Registers[RegisterSet::val] = false; \ 375921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer)) \ 376921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Registers[RegisterSet::val] = false; \ 377921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer)) \ 378921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Registers[RegisterSet::val] = false; 379921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 380921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto REGX8632_TABLE 381921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 382921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X 383921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 384921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto return Registers; 385921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 386921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 387921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static void 388921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func, 389921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto llvm::SmallVectorImpl<int32_t> &Permutation, 390aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu const llvm::SmallBitVector &ExcludeRegisters, 391aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu uint64_t Salt) { 392921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // TODO(stichnot): Declaring Permutation this way loses type/size 393921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // information. Fix this in conjunction with the caller-side TODO. 394921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto assert(Permutation.size() >= RegisterSet::Reg_NUM); 395921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // Expected upper bound on the number of registers in a single equivalence 396921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // class. For x86-32, this would comprise the 8 XMM registers. This is for 397921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // performance, not correctness. 398921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static const unsigned MaxEquivalenceClassSize = 8; 399921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto typedef llvm::SmallVector<int32_t, MaxEquivalenceClassSize> RegisterList; 400921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto typedef std::map<uint32_t, RegisterList> EquivalenceClassMap; 401921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto EquivalenceClassMap EquivalenceClasses; 402921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto SizeT NumShuffled = 0, NumPreserved = 0; 403921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 404921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto// Build up the equivalence classes of registers by looking at the register 405921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto// properties as well as whether the registers should be explicitly excluded 406921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto// from shuffling. 407921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ 408921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto frameptr, isI8, isInt, isFP) \ 409921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (ExcludeRegisters[RegisterSet::val]) { \ 410921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /* val stays the same in the resulting permutation. */ \ 411921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Permutation[RegisterSet::val] = RegisterSet::val; \ 412921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto ++NumPreserved; \ 413921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } else { \ 414921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const uint32_t Index = (scratch << 0) | (preserved << 1) | (isI8 << 2) | \ 415921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto (isInt << 3) | (isFP << 4); \ 416921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /* val is assigned to an equivalence class based on its properties. */ \ 417921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto EquivalenceClasses[Index].push_back(RegisterSet::val); \ 418921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 419921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto REGX8632_TABLE 420921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X 421921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 422aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu // Create a random number generator for regalloc randomization. 423aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), 424aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RPE_RegAllocRandomization, Salt); 425aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RandomNumberGeneratorWrapper RNGW(RNG); 426921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 427921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // Shuffle the resulting equivalence classes. 428921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto for (auto I : EquivalenceClasses) { 429921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const RegisterList &List = I.second; 430921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto RegisterList Shuffled(List); 431aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW); 432921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { 433921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Permutation[List[SI]] = Shuffled[SI]; 434921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto ++NumShuffled; 435921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 436921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 437921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 438921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM); 439921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 440921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (Func->isVerbose(IceV_Random)) { 441921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto OstreamLocker L(Func->getContext()); 442921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Ostream &Str = Func->getContext()->getStrDump(); 443921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Str << "Register equivalence classes:\n"; 444921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto for (auto I : EquivalenceClasses) { 445921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Str << "{"; 446921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const RegisterList &List = I.second; 447921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto bool First = true; 448921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto for (int32_t Register : List) { 449921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto if (!First) 450921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Str << " "; 451921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto First = false; 452921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Str << getRegName(Register, IceType_i32); 453921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 454921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Str << "}\n"; 455921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 456921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 457921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 458921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 459921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// The maximum number of arguments to pass in XMM registers 4605d0acff3a2fa421923392aadb4df2742064b6248John Porto static const uint32_t X86_MAX_XMM_ARGS = 4; 461921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// The number of bits in a byte 4625d0acff3a2fa421923392aadb4df2742064b6248John Porto static const uint32_t X86_CHAR_BIT = 8; 463921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it 464921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// is used as an argument to std::max(), and the default std::less<T> has an 465921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// operator(T const&, T const&) which requires this member to have an 466921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// address. 4675d0acff3a2fa421923392aadb4df2742064b6248John Porto static const uint32_t X86_STACK_ALIGNMENT_BYTES; 468921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// Size of the return address on the stack 4695d0acff3a2fa421923392aadb4df2742064b6248John Porto static const uint32_t X86_RET_IP_SIZE_BYTES = 4; 470921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// The number of different NOP instructions 4715d0acff3a2fa421923392aadb4df2742064b6248John Porto static const uint32_t X86_NUM_NOP_VARIANTS = 5; 4725d0acff3a2fa421923392aadb4df2742064b6248John Porto 473cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull /// \name Limits for unrolling memory intrinsics. 474cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull /// @{ 475cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8; 476cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8; 477cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull static constexpr uint32_t MEMSET_UNROLL_LIMIT = 16; 478cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull /// @} 479cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull 480921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// Value is in bytes. Return Value adjusted to the next highest multiple 481921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// of the stack alignment. 4825d0acff3a2fa421923392aadb4df2742064b6248John Porto static uint32_t applyStackAlignment(uint32_t Value) { 4835d0acff3a2fa421923392aadb4df2742064b6248John Porto return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); 4845d0acff3a2fa421923392aadb4df2742064b6248John Porto } 4855d0acff3a2fa421923392aadb4df2742064b6248John Porto 486921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// Return the type which the elements of the vector have in the X86 487921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// representation of the vector. 4885d0acff3a2fa421923392aadb4df2742064b6248John Porto static Type getInVectorElementType(Type Ty) { 4895d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(isVectorType(Ty)); 4905d0acff3a2fa421923392aadb4df2742064b6248John Porto size_t Index = static_cast<size_t>(Ty); 4915d0acff3a2fa421923392aadb4df2742064b6248John Porto (void)Index; 4925d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(Index < TableTypeX8632AttributesSize); 4935d0acff3a2fa421923392aadb4df2742064b6248John Porto return TableTypeX8632Attributes[Ty].InVectorElementType; 4945d0acff3a2fa421923392aadb4df2742064b6248John Porto } 4955d0acff3a2fa421923392aadb4df2742064b6248John Porto 4965d0acff3a2fa421923392aadb4df2742064b6248John Porto // Note: The following data structures are defined in 4975d0acff3a2fa421923392aadb4df2742064b6248John Porto // IceTargetLoweringX8632.cpp. 4985d0acff3a2fa421923392aadb4df2742064b6248John Porto 499921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// The following table summarizes the logic for lowering the fcmp 500921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// instruction. There is one table entry for each of the 16 conditions. 501921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// 502921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// The first four columns describe the case when the operands are floating 503921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// point scalar values. A comment in lowerFcmp() describes the lowering 504921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// template. In the most general case, there is a compare followed by two 505921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// conditional branches, because some fcmp conditions don't map to a single 506921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// x86 conditional branch. However, in many cases it is possible to swap the 507921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// operands in the comparison and have a single conditional branch. Since 508921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// it's quite tedious to validate the table by hand, good execution tests are 509921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// helpful. 510921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// 511921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// The last two columns describe the case when the operands are vectors of 512921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// floating point values. For most fcmp conditions, there is a clear mapping 513921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// to a single x86 cmpps instruction variant. Some fcmp conditions require 514921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// special code to handle and these are marked in the table with a 515921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// Cmpps_Invalid predicate. 516921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// {@ 5175d0acff3a2fa421923392aadb4df2742064b6248John Porto static const struct TableFcmpType { 5185d0acff3a2fa421923392aadb4df2742064b6248John Porto uint32_t Default; 5195d0acff3a2fa421923392aadb4df2742064b6248John Porto bool SwapScalarOperands; 520921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Cond::BrCond C1, C2; 5215d0acff3a2fa421923392aadb4df2742064b6248John Porto bool SwapVectorOperands; 522921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Cond::CmppsCond Predicate; 5235d0acff3a2fa421923392aadb4df2742064b6248John Porto } TableFcmp[]; 5245d0acff3a2fa421923392aadb4df2742064b6248John Porto static const size_t TableFcmpSize; 525921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// @} 5265d0acff3a2fa421923392aadb4df2742064b6248John Porto 527921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// The following table summarizes the logic for lowering the icmp instruction 528921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// for i32 and narrower types. Each icmp condition has a clear mapping to an 529921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// x86 conditional branch instruction. 530921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// {@ 531921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[]; 5325d0acff3a2fa421923392aadb4df2742064b6248John Porto static const size_t TableIcmp32Size; 533921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// @} 5345d0acff3a2fa421923392aadb4df2742064b6248John Porto 535921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// The following table summarizes the logic for lowering the icmp instruction 536921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and 537921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// conditional branches are needed. For the other conditions, three separate 538921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// conditional branches are needed. 539921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// {@ 5405d0acff3a2fa421923392aadb4df2742064b6248John Porto static const struct TableIcmp64Type { 541921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Cond::BrCond C1, C2, C3; 5425d0acff3a2fa421923392aadb4df2742064b6248John Porto } TableIcmp64[]; 5435d0acff3a2fa421923392aadb4df2742064b6248John Porto static const size_t TableIcmp64Size; 544921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// @} 5455d0acff3a2fa421923392aadb4df2742064b6248John Porto 546921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { 5475d0acff3a2fa421923392aadb4df2742064b6248John Porto size_t Index = static_cast<size_t>(Cond); 5485d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(Index < TableIcmp32Size); 5495d0acff3a2fa421923392aadb4df2742064b6248John Porto return TableIcmp32[Index].Mapping; 5505d0acff3a2fa421923392aadb4df2742064b6248John Porto } 5515d0acff3a2fa421923392aadb4df2742064b6248John Porto 5525d0acff3a2fa421923392aadb4df2742064b6248John Porto static const struct TableTypeX8632AttributesType { 5535d0acff3a2fa421923392aadb4df2742064b6248John Porto Type InVectorElementType; 5545d0acff3a2fa421923392aadb4df2742064b6248John Porto } TableTypeX8632Attributes[]; 5555d0acff3a2fa421923392aadb4df2742064b6248John Porto static const size_t TableTypeX8632AttributesSize; 556921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 557921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto //---------------------------------------------------------------------------- 558921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // __ __ __ ______ ______ 559921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // /\ \/\ "-.\ \/\ ___\/\__ _\ 560921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // \ \ \ \ \-. \ \___ \/_/\ \/ 561921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // \ \_\ \_\\"\_\/\_____\ \ \_\ 562921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // \/_/\/_/ \/_/\/_____/ \/_/ 563921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // 564921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto //---------------------------------------------------------------------------- 565921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto using Insts = ::Ice::X86Internal::Insts<TargetX8632>; 566921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 5675aeed955e17bac8cc44cc6d2b6ff7513cc714c2fJohn Porto using TargetLowering = ::Ice::X86Internal::TargetX86Base<TargetX8632>; 568921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto using Assembler = X8632::AssemblerX8632; 569921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 570921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// X86Operand extends the Operand hierarchy. Its subclasses are 571921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// X86OperandMem and VariableSplit. 572921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto class X86Operand : public ::Ice::Operand { 573921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto X86Operand() = delete; 574921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto X86Operand(const X86Operand &) = delete; 575921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto X86Operand &operator=(const X86Operand &) = delete; 576921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 577921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto public: 578921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto enum OperandKindX8632 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit }; 579921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto using ::Ice::Operand::dump; 580921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 581921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto void dump(const Cfg *, Ostream &Str) const override; 582921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 583921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto protected: 584921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto X86Operand(OperandKindX8632 Kind, Type Ty) 585921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {} 586921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto }; 587921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 588921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// X86OperandMem represents the m32 addressing mode, with optional base and 589921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// index registers, a constant offset, and a fixed shift value for the index 590921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// register. 591921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto class X86OperandMem : public X86Operand { 592921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto X86OperandMem() = delete; 593921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto X86OperandMem(const X86OperandMem &) = delete; 594921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto X86OperandMem &operator=(const X86OperandMem &) = delete; 595921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 596921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto public: 597921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto enum SegmentRegisters { 598921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto DefaultSegment = -1, 599921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, name, prefix) val, 600921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto SEG_REGX8632_TABLE 601921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X 602921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto SegReg_NUM 603921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto }; 604921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base, 605921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Constant *Offset, Variable *Index = nullptr, 606921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto uint16_t Shift = 0, 607921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto SegmentRegisters SegmentReg = DefaultSegment) { 608921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto return new (Func->allocate<X86OperandMem>()) 609921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto X86OperandMem(Func, Ty, Base, Offset, Index, Shift, SegmentReg); 610921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 611921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Variable *getBase() const { return Base; } 612921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Constant *getOffset() const { return Offset; } 613921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Variable *getIndex() const { return Index; } 614921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto uint16_t getShift() const { return Shift; } 615921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto SegmentRegisters getSegmentRegister() const { return SegmentReg; } 616921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto void emitSegmentOverride(Assembler *Asm) const; 617921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Address toAsmAddress(Assembler *Asm) const; 618921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 619921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto void emit(const Cfg *Func) const override; 620921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto using X86Operand::dump; 621921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto void dump(const Cfg *Func, Ostream &Str) const override; 622921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 623921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static bool classof(const Operand *Operand) { 624921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto return Operand->getKind() == static_cast<OperandKind>(kMem); 625921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 626921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 627921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto void setRandomized(bool R) { Randomized = R; } 628921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 629921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto bool getRandomized() const { return Randomized; } 630921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 631921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto private: 632921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, 633921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg); 634921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 635921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Variable *Base; 636921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Constant *Offset; 637921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Variable *Index; 638921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto uint16_t Shift; 639921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto SegmentRegisters SegmentReg : 16; 640921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// A flag to show if this memory operand is a randomized one. Randomized 641921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// memory operands are generated in 642921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// TargetX86Base::randomizeOrPoolImmediate() 643921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto bool Randomized; 644921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto }; 645921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 646921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// VariableSplit is a way to treat an f64 memory location as a pair of i32 647921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// locations (Low and High). This is needed for some cases of the Bitcast 648921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// instruction. Since it's not possible for integer registers to access the 649921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// XMM registers and vice versa, the lowering forces the f64 to be spilled to 650921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// the stack and then accesses through the VariableSplit. 651921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit 652921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // targets can natively handle these. 653921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto class VariableSplit : public X86Operand { 654921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto VariableSplit() = delete; 655921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto VariableSplit(const VariableSplit &) = delete; 656921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto VariableSplit &operator=(const VariableSplit &) = delete; 657921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 658921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto public: 659921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto enum Portion { Low, High }; 660921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) { 661921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto return new (Func->allocate<VariableSplit>()) 662921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto VariableSplit(Func, Var, Part); 663921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 664921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto int32_t getOffset() const { return Part == High ? 4 : 0; } 665921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 666921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Address toAsmAddress(const Cfg *Func) const; 667921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto void emit(const Cfg *Func) const override; 668921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto using X86Operand::dump; 669921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto void dump(const Cfg *Func, Ostream &Str) const override; 670921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 671921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static bool classof(const Operand *Operand) { 672921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto return Operand->getKind() == static_cast<OperandKind>(kSplit); 673921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 674921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 675921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto private: 676921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto VariableSplit(Cfg *Func, Variable *Var, Portion Part) 677921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) { 678921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto assert(Var->getType() == IceType_f64); 679921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Vars = Func->allocateArrayOf<Variable *>(1); 680921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Vars[0] = Var; 681921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto NumVars = 1; 682921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 683921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 684921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Variable *Var; 685921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Portion Part; 686921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto }; 687921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 688921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// SpillVariable decorates a Variable by linking it to another Variable. 689921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// When stack frame offsets are computed, the SpillVariable is given a 690921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// distinct stack slot only if its linked Variable has a register. If the 691921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// linked Variable has a stack slot, then the Variable and SpillVariable 692921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto /// share that slot. 693921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto class SpillVariable : public Variable { 694921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto SpillVariable() = delete; 695921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto SpillVariable(const SpillVariable &) = delete; 696921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto SpillVariable &operator=(const SpillVariable &) = delete; 697921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 698921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto public: 699921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) { 700921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index); 701921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 702921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const static OperandKind SpillVariableKind = 703921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static_cast<OperandKind>(kVariable_Target); 704921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static bool classof(const Operand *Operand) { 705921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto return Operand->getKind() == SpillVariableKind; 706921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } 707921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto void setLinkedTo(Variable *Var) { LinkedTo = Var; } 708921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Variable *getLinkedTo() const { return LinkedTo; } 709921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // Inherit dump() and emit() from Variable. 710921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 711921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto private: 712921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto SpillVariable(Type Ty, SizeT Index) 713921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto : Variable(SpillVariableKind, Ty, Index), LinkedTo(nullptr) {} 714921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Variable *LinkedTo; 715921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto }; 716921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 717921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto // Note: The following data structures are defined in IceInstX8632.cpp. 718921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 719921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static const struct InstBrAttributesType { 720921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto Cond::BrCond Opposite; 721921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const char *DisplayString; 722921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const char *EmitString; 723921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } InstBrAttributes[]; 724921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 725921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static const struct InstCmppsAttributesType { 726921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const char *EmitString; 727921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } InstCmppsAttributes[]; 728921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 729921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static const struct TypeAttributesType { 730921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const char *CvtString; // i (integer), s (single FP), d (double FP) 731921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const char *SdSsString; // ss, sd, or <blank> 732921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const char *PackString; // b, w, d, or <blank> 733921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const char *WidthString; // b, w, l, q, or <blank> 734921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto const char *FldString; // s, l, or <blank> 735921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto } TypeAttributes[]; 736921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 737921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static const char *InstSegmentRegNames[]; 738921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto 739921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto static uint8_t InstSegmentPrefixes[]; 7405d0acff3a2fa421923392aadb4df2742064b6248John Porto}; 7415d0acff3a2fa421923392aadb4df2742064b6248John Porto 7425d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace X86Internal 7435d0acff3a2fa421923392aadb4df2742064b6248John Porto 7445d0acff3a2fa421923392aadb4df2742064b6248John Portonamespace X8632 { 7455d0acff3a2fa421923392aadb4df2742064b6248John Portousing Traits = ::Ice::X86Internal::MachineTraits<TargetX8632>; 7465d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace X8632 7475d0acff3a2fa421923392aadb4df2742064b6248John Porto 7485d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace Ice 7495d0acff3a2fa421923392aadb4df2742064b6248John Porto 7505d0acff3a2fa421923392aadb4df2742064b6248John Porto#endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H 751