IceTargetLoweringX8664Traits.h revision d1bd1d330c8eb8116811ad4dc01fe636b80b86cb
12fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto//===- subzero/src/IceTargetLoweringX8664Traits.h - x86-64 traits -*- C++ -*-=// 22fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto// 32fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto// The Subzero Code Generator 42fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto// 52fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto// This file is distributed under the University of Illinois Open Source 62fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto// License. See LICENSE.TXT for details. 72fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto// 82fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto//===----------------------------------------------------------------------===// 92fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto/// 102fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto/// \file 1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Declares the X8664 Target Lowering Traits. 122fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto/// 132fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto//===----------------------------------------------------------------------===// 142fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 152fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H 162fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#define SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H 172fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 182fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceAssembler.h" 192fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceConditionCodesX8664.h" 202fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceDefs.h" 212fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceInst.h" 222fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceInstX8664.def" 232fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceOperand.h" 242fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceRegistersX8664.h" 252fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceTargetLowering.h" 26453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#include "IceTargetLoweringX8664.def" 27c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth#include "IceTargetLoweringX86RegClass.h" 282fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 29bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto#include <array> 304a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#include <initializer_list> 31bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto 322fea26cae5a6b140c67e18aec3dcf645a16694d5John Portonamespace Ice { 332fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 342fea26cae5a6b140c67e18aec3dcf645a16694d5John Portonamespace X8664 { 354a56686b5b56db6803f90ad53514bf2fa190d9f7John Portousing namespace ::Ice::X86; 362fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 374a56686b5b56db6803f90ad53514bf2fa190d9f7John Portotemplate <class TraitsType> class AssemblerX86Base; 384a56686b5b56db6803f90ad53514bf2fa190d9f7John Portotemplate <class TraitsType> struct Insts; 394a56686b5b56db6803f90ad53514bf2fa190d9f7John Portotemplate <class TraitsType> class TargetX86Base; 402fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 414a56686b5b56db6803f90ad53514bf2fa190d9f7John Portoclass TargetX8664; 422fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 434a56686b5b56db6803f90ad53514bf2fa190d9f7John Portostruct TargetX8664Traits { 442fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto //---------------------------------------------------------------------------- 452fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // ______ ______ __ __ 462fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // /\ __ \/\ ___\/\ "-./ \ 472fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // \ \ __ \ \___ \ \ \-./\ \ 482fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // \ \_\ \_\/\_____\ \_\ \ \_\ 492fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // \/_/\/_/\/_____/\/_/ \/_/ 502fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // 512fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto //---------------------------------------------------------------------------- 524a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto static constexpr ::Ice::Assembler::AssemblerKind AsmKind = 534a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto ::Ice::Assembler::Asm_X8632; 544a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto 552fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static constexpr bool Is64Bit = true; 562fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static constexpr bool HasPopa = false; 572fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static constexpr bool HasPusha = false; 582fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static constexpr bool UsesX87 = false; 592fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static constexpr ::Ice::RegX8664::GPRRegister Last8BitGPR = 602fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto ::Ice::RegX8664::GPRRegister::Encoded_Reg_r15d; 612fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 622fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; 632fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 642fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto using GPRRegister = ::Ice::RegX8664::GPRRegister; 652fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto using ByteRegister = ::Ice::RegX8664::ByteRegister; 665bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth using XmmRegister = ::Ice::RegX8664::XmmRegister; 672fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 682fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto using Cond = ::Ice::CondX8664; 692fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 702fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto using RegisterSet = ::Ice::RegX8664; 710c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr SizeT StackPtr = RegX8664::Reg_rsp; 720c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr SizeT FramePtr = RegX8664::Reg_rbp; 730c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr GPRRegister Encoded_Reg_Accumulator = 740c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr RegX8664::Encoded_Reg_eax; 750c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr GPRRegister Encoded_Reg_Counter = RegX8664::Encoded_Reg_ecx; 768ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth static constexpr FixupKind FK_PcRel = llvm::ELF::R_X86_64_PC32; 778ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth static constexpr FixupKind FK_Abs = llvm::ELF::R_X86_64_32; 788ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth static constexpr FixupKind FK_Gotoff = llvm::ELF::R_X86_64_GOTOFF64; 798ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth static constexpr FixupKind FK_GotPC = llvm::ELF::R_X86_64_GOTPC32; 802fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 812fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto class Operand { 822fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto public: 832fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto enum RexBits { 842fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto RexNone = 0x00, 852fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto RexBase = 0x40, 862fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto RexW = RexBase | (1 << 3), 872fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto RexR = RexBase | (1 << 2), 882fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto RexX = RexBase | (1 << 1), 892fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto RexB = RexBase | (1 << 0), 902fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto }; 912fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 92d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto protected: 93d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto // Needed by subclass Address. 94d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Operand() = default; 952fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 96d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto public: 97d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Operand(const Operand &) = default; 98d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Operand(Operand &&) = default; 99d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Operand &operator=(const Operand &) = default; 100d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Operand &operator=(Operand &&) = default; 1012fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1022fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto uint8_t mod() const { return (encoding_at(0) >> 6) & 3; } 1032fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1042fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto uint8_t rexX() const { return (rex_ & RexX) != RexX ? RexNone : RexX; } 1052fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto uint8_t rexB() const { return (rex_ & RexB) != RexB ? RexNone : RexB; } 1062fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1072fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto GPRRegister rm() const { 1082fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) | 1092fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto (encoding_at(0) & 7)); 1102fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1112fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1122fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto ScaleFactor scale() const { 1132fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); 1142fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1152fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1162fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto GPRRegister index() const { 1172fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto return static_cast<GPRRegister>((rexX() != 0 ? 0x08 : 0) | 1182fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto ((encoding_at(1) >> 3) & 7)); 1192fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1202fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1212fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto GPRRegister base() const { 1222fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) | 1232fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto (encoding_at(1) & 7)); 1242fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1252fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1262fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto int8_t disp8() const { 1272fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto assert(length_ >= 2); 1282fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto return static_cast<int8_t>(encoding_[length_ - 1]); 1292fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1302fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1312fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto AssemblerFixup *fixup() const { return fixup_; } 1322fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1332fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto protected: 1342fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto void SetModRM(int mod, GPRRegister rm) { 1352fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto assert((mod & ~3) == 0); 1362fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto encoding_[0] = (mod << 6) | (rm & 0x07); 1372fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto rex_ = (rm & 0x08) ? RexB : RexNone; 1382fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto length_ = 1; 1392fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1402fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1412fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { 1422fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto assert(length_ == 1); 1432fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto assert((scale & ~3) == 0); 1442fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto encoding_[1] = (scale << 6) | ((index & 0x07) << 3) | (base & 0x07); 1452fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto rex_ = 1462fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto ((base & 0x08) ? RexB : RexNone) | ((index & 0x08) ? RexX : RexNone); 1472fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto length_ = 2; 1482fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1492fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1502fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto void SetDisp8(int8_t disp) { 1512fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto assert(length_ == 1 || length_ == 2); 1522fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto encoding_[length_++] = static_cast<uint8_t>(disp); 1532fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1542fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1552fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto void SetDisp32(int32_t disp) { 1562fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto assert(length_ == 1 || length_ == 2); 1572fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto intptr_t disp_size = sizeof(disp); 1582fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto memmove(&encoding_[length_], &disp, disp_size); 1592fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto length_ += disp_size; 1602fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1612fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1622fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; } 1632fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1642fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto private: 165d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto AssemblerFixup *fixup_ = nullptr; 1662fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto uint8_t rex_ = 0; 1672fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto uint8_t encoding_[6]; 168d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto uint8_t length_ = 0; 1692fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1702fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); } 1712fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1722fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto /// Get the operand encoding byte at the given index. 1732fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto uint8_t encoding_at(intptr_t index) const { 1742fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto assert(index >= 0 && index < length_); 1752fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto return encoding_[index]; 1762fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1772fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1782fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto /// Returns whether or not this operand is really the given register in 1792fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto /// disguise. Used from the assembler to generate better encodings. 1802fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto bool IsRegister(GPRRegister reg) const { 1812fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto return ((encoding_[0] & 0xF8) == 1822fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 0xC0) // Addressing mode is register only. 1832fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto && 1842fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto (rm() == reg); // Register codes match. 1852fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 1862fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1874a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto friend class AssemblerX86Base<TargetX8664Traits>; 1882fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto }; 1892fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1902fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto class Address : public Operand { 191d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Address() = default; 1922fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 1932fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto public: 194d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Address(const Address &) = default; 195d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Address(Address &&) = default; 196d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Address &operator=(const Address &) = default; 197d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Address &operator=(Address &&) = default; 1982fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 199aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr Address(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) { 200aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr if (Fixup == nullptr && Disp == 0 && 201d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto (Base & 7) != RegX8664::Encoded_Reg_rbp) { 202aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetModRM(0, Base); 203d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto if ((Base & 7) == RegX8664::Encoded_Reg_rsp) 204d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base); 205aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) { 206aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetModRM(1, Base); 207d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto if ((Base & 7) == RegX8664::Encoded_Reg_rsp) 208d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base); 209aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetDisp8(Disp); 2102fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } else { 211aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetModRM(2, Base); 212d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto if ((Base & 7) == RegX8664::Encoded_Reg_rsp) 213d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base); 214aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetDisp32(Disp); 215aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr if (Fixup) 216aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetFixup(Fixup); 2172fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 2182fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 2192fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 220aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr Address(GPRRegister Index, ScaleFactor Scale, int32_t Disp, 221aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr AssemblerFixup *Fixup) { 222d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode. 223d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto SetModRM(0, RegX8664::Encoded_Reg_rsp); 224d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto SetSIB(Scale, Index, RegX8664::Encoded_Reg_rbp); 225aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetDisp32(Disp); 226aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr if (Fixup) 227aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetFixup(Fixup); 2282fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 2292fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 230aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr Address(GPRRegister Base, GPRRegister Index, ScaleFactor Scale, 231aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr int32_t Disp, AssemblerFixup *Fixup) { 232d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode. 233aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr if (Fixup == nullptr && Disp == 0 && 234d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto (Base & 7) != RegX8664::Encoded_Reg_rbp) { 235d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto SetModRM(0, RegX8664::Encoded_Reg_rsp); 236aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetSIB(Scale, Index, Base); 237aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) { 238d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto SetModRM(1, RegX8664::Encoded_Reg_rsp); 239aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetSIB(Scale, Index, Base); 240aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetDisp8(Disp); 2412fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } else { 242d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto SetModRM(2, RegX8664::Encoded_Reg_rsp); 243aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetSIB(Scale, Index, Base); 244aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetDisp32(Disp); 245aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr if (Fixup) 246aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr SetFixup(Fixup); 2472fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 2482fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 2492fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 250aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr /// Generate a RIP-relative address expression on x86-64. 251d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto static Address RipRelative(RelocOffsetT Offset, AssemblerFixup *Fixup) { 252d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto assert(Fixup != nullptr); 253d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto assert(Fixup->kind() == FK_PcRel); 254d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Address NewAddress; 255d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto NewAddress.SetModRM(0x0, RegX8664::Encoded_Reg_rbp); 2563c275ce1e832ba9ccfb730c4235db786cf080465John Porto 2572fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // Use the Offset in the displacement for now. If we decide to process 2582fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // fixups later, we'll need to patch up the emitted displacement. 259d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto NewAddress.SetDisp32(Offset); 260aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr if (Fixup) 261d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto NewAddress.SetFixup(Fixup); 262d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto 263d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto return NewAddress; 264d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto } 265d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto 266d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto /// Generate an absolute address. 267d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto static Address Absolute(RelocOffsetT Addr) { 268d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto Address NewAddress; 269d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto NewAddress.SetModRM(0x0, RegX8664::Encoded_Reg_rsp); 270d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto static constexpr ScaleFactor NoScale = TIMES_1; 271d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto NewAddress.SetSIB(NoScale, RegX8664::Encoded_Reg_rsp, 272d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto RegX8664::Encoded_Reg_rbp); 273d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto NewAddress.SetDisp32(Addr); 274d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto return NewAddress; 2752fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 2762fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 2772fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto static Address ofConstPool(Assembler *Asm, const Constant *Imm) { 2782fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // TODO(jpp): ??? 2798ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth AssemblerFixup *Fixup = Asm->createFixup(FK_Abs, Imm); 2801d235425dab1f3dd059973fc53f1b1d5879469e3John Porto const RelocOffsetT Offset = 4; 281d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto return Address::RipRelative(Offset, Fixup); 2822fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto } 2832fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto }; 2842fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 2852fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto //---------------------------------------------------------------------------- 2862fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // __ ______ __ __ ______ ______ __ __ __ ______ 2872fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ 2882fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ 2892fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ 2902fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ 2912fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto // 2922fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto //---------------------------------------------------------------------------- 293453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto enum InstructionSet { 294453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Begin, 295453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // SSE2 is the PNaCl baseline instruction set. 296453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto SSE2 = Begin, 297453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto SSE4_1, 298453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto End 299453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto }; 300453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 301453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const char *TargetName; 3021d235425dab1f3dd059973fc53f1b1d5879469e3John Porto static constexpr Type WordType = IceType_i64; 303453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 3045bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth static IceString getRegName(int32_t RegNum) { 3054a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static const char *const RegNames[RegisterSet::Reg_NUM] = { 3065bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 30756958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 30856958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 3095bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth name, 3105bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth REGX8664_TABLE 3115bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X 3125bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth }; 3135bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum >= 0); 314453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(RegNum < RegisterSet::Reg_NUM); 3155bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return RegNames[RegNum]; 3165bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } 3175bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth 3185bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth static GPRRegister getEncodedGPR(int32_t RegNum) { 3194a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = { 3205bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 32156958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 32256958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 3235bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR), 324453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto REGX8664_TABLE 325453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X 326453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto }; 3275bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum >= 0); 3285bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum < RegisterSet::Reg_NUM); 3295bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR); 3305bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return GPRRegs[RegNum]; 3315bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } 332453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 3335bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth static ByteRegister getEncodedByteReg(int32_t RegNum) { 3344a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = { 3355bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 33656958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 33756958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 3385bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg), 3395bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth REGX8664_TABLE 3405bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X 3415bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth }; 3425bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum >= 0); 3435bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum < RegisterSet::Reg_NUM); 3445bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg); 3455bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return ByteRegs[RegNum]; 346453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 347453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 3485bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth static XmmRegister getEncodedXmm(int32_t RegNum) { 3494a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = { 3505bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 35156958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 35256958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 3535bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm), 3545bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth REGX8664_TABLE 3555bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X 3565bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth }; 3575bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum >= 0); 3585bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum < RegisterSet::Reg_NUM); 3595bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm); 3605bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return XmmRegs[RegNum]; 3615bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } 3625bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth 3635bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth static uint32_t getEncoding(int32_t RegNum) { 3644a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static const uint32_t Encoding[RegisterSet::Reg_NUM] = { 3655bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 36656958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 36756958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 3685bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth encode, 3695bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth REGX8664_TABLE 3705bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X 3715bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth }; 3725bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum >= 0); 3735bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum < RegisterSet::Reg_NUM); 3745bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return Encoding[RegNum]; 3755bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } 3765bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth 3775bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth static inline int32_t getBaseReg(int32_t RegNum) { 3784a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static const int32_t BaseRegs[RegisterSet::Reg_NUM] = { 3795bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 38056958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 38156958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 38256958cb33d3c1d045f2844408d825442d523f59fJohn Porto encode, 3835bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth REGX8664_TABLE 3845bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X 3855bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth }; 3865bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum >= 0); 3875bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(RegNum < RegisterSet::Reg_NUM); 3885bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return BaseRegs[RegNum]; 3895bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } 3905bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth 391008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Portoprivate: 392008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto static int32_t getFirstGprForType(Type Ty) { 393008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto switch (Ty) { 394008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto default: 395008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto llvm_unreachable("Invalid type for GPR."); 396008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case IceType_i1: 397008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case IceType_i8: 398008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegisterSet::Reg_al; 399008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case IceType_i16: 400008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegisterSet::Reg_ax; 401008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case IceType_i32: 402008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegisterSet::Reg_eax; 403008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case IceType_i64: 404008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegisterSet::Reg_rax; 405008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 406008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 407008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 408008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Portopublic: 409008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto static int32_t getGprForType(Type Ty, int32_t RegNum) { 410008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(RegNum != Variable::NoRegister); 411008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 412008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto if (!isScalarIntegerType(Ty)) { 413008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegNum; 414008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 415008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 416008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(Ty == IceType_i1 || Ty == IceType_i8 || Ty == IceType_i16 || 417008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto Ty == IceType_i32 || Ty == IceType_i64); 418008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 419008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto if (RegNum == RegisterSet::Reg_ah) { 420008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(Ty == IceType_i8); 421008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegNum; 422008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 423008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 424008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(RegNum != RegisterSet::Reg_bh); 425008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(RegNum != RegisterSet::Reg_ch); 426008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(RegNum != RegisterSet::Reg_dh); 427008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 428008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto const int32_t FirstGprForType = getFirstGprForType(Ty); 429008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 430008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto switch (RegNum) { 431008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto default: 432008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto llvm::report_fatal_error("Unknown register."); 433008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 43456958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 43556958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 436008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case RegisterSet::val: { \ 43756958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (!isGPR) \ 43856958cb33d3c1d045f2844408d825442d523f59fJohn Porto return RegisterSet::val; \ 439008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert((is64) || (is32) || (is16) || (is8) || \ 44056958cb33d3c1d045f2844408d825442d523f59fJohn Porto getBaseReg(RegisterSet::val) == RegisterSet::Reg_rsp || \ 44156958cb33d3c1d045f2844408d825442d523f59fJohn Porto getBaseReg(RegisterSet::val) == RegisterSet::Reg_rbp); \ 442008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto constexpr int32_t FirstGprWithRegNumSize = \ 44356958cb33d3c1d045f2844408d825442d523f59fJohn Porto ((is64) || RegisterSet::val == RegisterSet::Reg_rsp || \ 44456958cb33d3c1d045f2844408d825442d523f59fJohn Porto RegisterSet::val == RegisterSet::Reg_rbp) \ 445008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto ? RegisterSet::Reg_rax \ 44656958cb33d3c1d045f2844408d825442d523f59fJohn Porto : (((is32) || RegisterSet::val == RegisterSet::Reg_esp || \ 44756958cb33d3c1d045f2844408d825442d523f59fJohn Porto RegisterSet::val == RegisterSet::Reg_ebp) \ 448008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto ? RegisterSet::Reg_eax \ 44956958cb33d3c1d045f2844408d825442d523f59fJohn Porto : (((is16) || RegisterSet::val == RegisterSet::Reg_sp || \ 45056958cb33d3c1d045f2844408d825442d523f59fJohn Porto RegisterSet::val == RegisterSet::Reg_bp) \ 451008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto ? RegisterSet::Reg_ax \ 452008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto : RegisterSet::Reg_al)); \ 453008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto const int32_t NewRegNum = \ 454008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto RegNum - FirstGprWithRegNumSize + FirstGprForType; \ 455008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) && \ 456008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto "Error involving " #val); \ 457008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return NewRegNum; \ 458008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 459008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto REGX8664_TABLE 460008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto#undef X 461008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 462008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 4635bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth 4644a308cedda6bfe381dc9506f3508c4547a06275fJohn Portoprivate: 4654a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto /// SizeOf is used to obtain the size of an initializer list as a constexpr 4664a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto /// expression. This is only needed until our C++ library is updated to 4674a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto /// C++ 14 -- which defines constexpr members to std::initializer_list. 4684a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto class SizeOf { 4694a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto SizeOf(const SizeOf &) = delete; 4704a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto SizeOf &operator=(const SizeOf &) = delete; 4714a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 4724a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto public: 4734a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto constexpr SizeOf() : Size(0) {} 4744a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto template <typename... T> 4754a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto explicit constexpr SizeOf(T...) 47656958cb33d3c1d045f2844408d825442d523f59fJohn Porto : Size(length<T...>::value) {} 4774a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto constexpr SizeT size() const { return Size; } 4784a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 4794a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto private: 48056958cb33d3c1d045f2844408d825442d523f59fJohn Porto template <typename T, typename... U> struct length { 48156958cb33d3c1d045f2844408d825442d523f59fJohn Porto static constexpr std::size_t value = 1 + length<U...>::value; 4824a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto }; 4834a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 48456958cb33d3c1d045f2844408d825442d523f59fJohn Porto template <typename T> struct length<T> { 4854a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static constexpr std::size_t value = 1; 4864a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto }; 4874a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 4884a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto const std::size_t Size; 4894a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto }; 4904a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 4914a308cedda6bfe381dc9506f3508c4547a06275fJohn Portopublic: 492bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto static void initRegisterSet( 49356958cb33d3c1d045f2844408d825442d523f59fJohn Porto const ::Ice::ClFlags &Flags, 494c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth std::array<llvm::SmallBitVector, RCX86_NUM> *TypeToRegisterSet, 49529d15fd619f1d46f8e0c3d22932b9931c4b81367Jim Stichnoth std::array<llvm::SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) { 4965bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth llvm::SmallBitVector IntegerRegistersI64(RegisterSet::Reg_NUM); 4975bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth llvm::SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM); 4985bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth llvm::SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM); 499bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto llvm::SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM); 500bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto llvm::SmallBitVector FloatRegisters(RegisterSet::Reg_NUM); 501bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto llvm::SmallBitVector VectorRegisters(RegisterSet::Reg_NUM); 502c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth llvm::SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM); 503c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth llvm::SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM); 504c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth llvm::SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM); 505c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth llvm::SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM); 506c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth llvm::SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM); 507bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto llvm::SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM); 508bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto 5094a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static constexpr struct { 5104a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto uint16_t Val; 51156958cb33d3c1d045f2844408d825442d523f59fJohn Porto unsigned IsReservedWhenSandboxing : 1; 512caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is64 : 1; 513caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is32 : 1; 514caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is16 : 1; 515caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is8 : 1; 516caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned IsXmm : 1; 517caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is64To8 : 1; 518caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is32To8 : 1; 519caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is16To8 : 1; 520caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned IsTrunc8Rcvr : 1; 521caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned IsAhRcvr : 1; 5224a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#define NUM_ALIASES_BITS 2 5234a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto SizeT NumAliases : (NUM_ALIASES_BITS + 1); 5244a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto uint16_t Aliases[1 << NUM_ALIASES_BITS]; 5254a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#undef NUM_ALIASES_BITS 5264a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto } X8664RegTable[RegisterSet::Reg_NUM] = { 5275bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 52856958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 52956958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 5304a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto { \ 53156958cb33d3c1d045f2844408d825442d523f59fJohn Porto RegisterSet::val, sboxres, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 53229d15fd619f1d46f8e0c3d22932b9931c4b81367Jim Stichnoth is16To8, isTrunc8Rcvr, isAhRcvr, (SizeOf aliases).size(), aliases, \ 5335bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } \ 5344a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto , 5354a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto REGX8664_TABLE 536453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X 5374a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto }; 5384a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 53956958cb33d3c1d045f2844408d825442d523f59fJohn Porto const bool NeedSandboxing = Flags.getUseSandboxing(); 5404a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto for (SizeT ii = 0; ii < llvm::array_lengthof(X8664RegTable); ++ii) { 5414a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto const auto &Entry = X8664RegTable[ii]; 54256958cb33d3c1d045f2844408d825442d523f59fJohn Porto // Even though the register is disabled for register allocation, it might 54356958cb33d3c1d045f2844408d825442d523f59fJohn Porto // still be used by the Target Lowering (e.g., base pointer), so the 54456958cb33d3c1d045f2844408d825442d523f59fJohn Porto // register alias table still needs to be defined. 54556958cb33d3c1d045f2844408d825442d523f59fJohn Porto (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM); 54656958cb33d3c1d045f2844408d825442d523f59fJohn Porto for (int J = 0; J < Entry.NumAliases; ++J) { 54756958cb33d3c1d045f2844408d825442d523f59fJohn Porto SizeT Alias = Entry.Aliases[J]; 54856958cb33d3c1d045f2844408d825442d523f59fJohn Porto assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias"); 54956958cb33d3c1d045f2844408d825442d523f59fJohn Porto (*RegisterAliases)[Entry.Val].set(Alias); 55056958cb33d3c1d045f2844408d825442d523f59fJohn Porto } 55156958cb33d3c1d045f2844408d825442d523f59fJohn Porto 55256958cb33d3c1d045f2844408d825442d523f59fJohn Porto (*RegisterAliases)[Entry.Val].set(Entry.Val); 55356958cb33d3c1d045f2844408d825442d523f59fJohn Porto const bool DisabledRegister = 55456958cb33d3c1d045f2844408d825442d523f59fJohn Porto NeedSandboxing && Entry.IsReservedWhenSandboxing; 55556958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (DisabledRegister) { 55656958cb33d3c1d045f2844408d825442d523f59fJohn Porto continue; 55756958cb33d3c1d045f2844408d825442d523f59fJohn Porto } 5584a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (IntegerRegistersI64)[Entry.Val] = Entry.Is64; 5594a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (IntegerRegistersI32)[Entry.Val] = Entry.Is32; 5604a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (IntegerRegistersI16)[Entry.Val] = Entry.Is16; 5614a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (IntegerRegistersI8)[Entry.Val] = Entry.Is8; 5624a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (FloatRegisters)[Entry.Val] = Entry.IsXmm; 5634a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (VectorRegisters)[Entry.Val] = Entry.IsXmm; 5644a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8; 5654a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8; 5664a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8; 5674a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr; 5684a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr; 5694a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto } 570bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto 571c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_void] = InvalidRegisters; 572c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8; 573c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8; 574c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16; 575c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32; 576c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_i64] = IntegerRegistersI64; 577c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_f32] = FloatRegisters; 578c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_f64] = FloatRegisters; 579c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters; 580c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters; 581c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters; 582c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters; 583c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters; 584c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters; 585c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters; 586c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers; 587c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers; 588c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers; 589c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters; 590c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters; 591453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 592453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 593453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static llvm::SmallBitVector 59456958cb33d3c1d045f2844408d825442d523f59fJohn Porto getRegisterSet(const ::Ice::ClFlags &Flags, 59556958cb33d3c1d045f2844408d825442d523f59fJohn Porto TargetLowering::RegSetMask Include, 596453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto TargetLowering::RegSetMask Exclude) { 597453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto llvm::SmallBitVector Registers(RegisterSet::Reg_NUM); 598453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 59956958cb33d3c1d045f2844408d825442d523f59fJohn Porto const bool NeedSandboxing = Flags.getUseSandboxing(); 6005bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 60156958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 60256958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 60356958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (!NeedSandboxing || !(sboxres)) { \ 60456958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave)) \ 60556958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = true; \ 60656958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave)) \ 60756958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = true; \ 60856958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer)) \ 60956958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = true; \ 61056958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer)) \ 61156958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = true; \ 61256958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave)) \ 61356958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = false; \ 61456958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave)) \ 61556958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = false; \ 61656958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer)) \ 61756958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = false; \ 61856958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer)) \ 61956958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = false; \ 62056958cb33d3c1d045f2844408d825442d523f59fJohn Porto } 621453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 622453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto REGX8664_TABLE 623453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 624453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X 625453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 626453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return Registers; 627453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 628453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 629453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static void 630453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func, 631453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto llvm::SmallVectorImpl<int32_t> &Permutation, 632aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu const llvm::SmallBitVector &ExcludeRegisters, 633aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu uint64_t Salt) { 634453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // TODO(stichnot): Declaring Permutation this way loses type/size 63557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // information. Fix this in conjunction with the caller-side TODO. 636453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(Permutation.size() >= RegisterSet::Reg_NUM); 637453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // Expected upper bound on the number of registers in a single equivalence 63857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // class. For x86-64, this would comprise the 16 XMM registers. This is 639453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // for performance, not correctness. 640453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const unsigned MaxEquivalenceClassSize = 8; 6418072bae156fa62e51e02925997992c4908a2682fAndrew Scull using RegisterList = llvm::SmallVector<int32_t, MaxEquivalenceClassSize>; 6428072bae156fa62e51e02925997992c4908a2682fAndrew Scull using EquivalenceClassMap = std::map<uint32_t, RegisterList>; 643453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto EquivalenceClassMap EquivalenceClasses; 644453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto SizeT NumShuffled = 0, NumPreserved = 0; 645453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 646453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// Build up the equivalence classes of registers by looking at the register 647453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// properties as well as whether the registers should be explicitly excluded 648453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// from shuffling. 6495bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 65056958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 65156958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 652453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto if (ExcludeRegisters[RegisterSet::val]) { \ 653453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /* val stays the same in the resulting permutation. */ \ 654453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Permutation[RegisterSet::val] = RegisterSet::val; \ 655453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto ++NumPreserved; \ 656453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } else { \ 6575bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth uint32_t AttrKey = 0; \ 6585bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth uint32_t Index = 0; \ 6595bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth /* Combine relevant attributes into an equivalence class key. */ \ 6605bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (scratch << (AttrKey++)); \ 6615bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (preserved << (AttrKey++)); \ 6625bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (is8 << (AttrKey++)); \ 6635bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (is16 << (AttrKey++)); \ 6645bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (is32 << (AttrKey++)); \ 6655bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (is64 << (AttrKey++)); \ 6665bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (isXmm << (AttrKey++)); \ 667c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth Index |= (is16To8 << (AttrKey++)); \ 668c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth Index |= (is32To8 << (AttrKey++)); \ 669c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth Index |= (is64To8 << (AttrKey++)); \ 670c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth Index |= (isTrunc8Rcvr << (AttrKey++)); \ 671453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /* val is assigned to an equivalence class based on its properties. */ \ 672453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto EquivalenceClasses[Index].push_back(RegisterSet::val); \ 673453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 674453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto REGX8664_TABLE 675453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X 676453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 677aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu // Create a random number generator for regalloc randomization. 678aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), 679aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RPE_RegAllocRandomization, Salt); 680aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RandomNumberGeneratorWrapper RNGW(RNG); 681453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 682453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // Shuffle the resulting equivalence classes. 683453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto for (auto I : EquivalenceClasses) { 684453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const RegisterList &List = I.second; 685453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto RegisterList Shuffled(List); 686aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW); 687453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { 688453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Permutation[List[SI]] = Shuffled[SI]; 689453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto ++NumShuffled; 690453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 691453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 692453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 693453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM); 694453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 695453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto if (Func->isVerbose(IceV_Random)) { 696453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto OstreamLocker L(Func->getContext()); 697453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Ostream &Str = Func->getContext()->getStrDump(); 698453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Str << "Register equivalence classes:\n"; 699453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto for (auto I : EquivalenceClasses) { 700453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Str << "{"; 701453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const RegisterList &List = I.second; 702453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto bool First = true; 703453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto for (int32_t Register : List) { 704453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto if (!First) 705453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Str << " "; 706453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto First = false; 7075bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Str << getRegName(Register); 708453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 709453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Str << "}\n"; 710453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 711453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 712453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 713453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 7143c275ce1e832ba9ccfb730c4235db786cf080465John Porto static int32_t getRaxOrDie() { return RegisterSet::Reg_rax; } 7153c275ce1e832ba9ccfb730c4235db786cf080465John Porto 7163c275ce1e832ba9ccfb730c4235db786cf080465John Porto static int32_t getRdxOrDie() { return RegisterSet::Reg_rdx; } 7173c275ce1e832ba9ccfb730c4235db786cf080465John Porto 7180c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // x86-64 calling convention: 7190c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // 7200c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // * The first eight arguments of vector/fp type, regardless of their 7210c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // position relative to the other arguments in the argument list, are placed 7220c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // in registers %xmm0 - %xmm7. 7230c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // 7240c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // * The first six arguments of integer types, regardless of their position 7250c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // relative to the other arguments in the argument list, are placed in 7260c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9. 7270c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // 7280c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // This intends to match the section "Function Calling Sequence" of the 7290c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // document "System V Application Binary Interface." 7300c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr 731453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The maximum number of arguments to pass in XMM registers 7320c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr uint32_t X86_MAX_XMM_ARGS = 8; 733e0d9afa80ee55711d25fae87e50d11685d1ad6d7John Porto /// The maximum number of arguments to pass in GPR registers 7340c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr uint32_t X86_MAX_GPR_ARGS = 6; 7350c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr /// Whether scalar floating point arguments are passed in XMM registers 7360c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = true; 7370c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr /// Get the register for a given argument slot in the XMM registers. 7380c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static int32_t getRegisterForXmmArgNum(uint32_t ArgNum) { 7390c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // TODO(sehr): Change to use the CCArg technique used in ARM32. 7400c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1, 7410c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr "Inconsistency between XMM register numbers and ordinals"); 7420c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr if (ArgNum >= X86_MAX_XMM_ARGS) { 7430c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr return Variable::NoRegister; 7440c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr } 7450c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr return static_cast<int32_t>(RegisterSet::Reg_xmm0 + ArgNum); 7460c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr } 7470c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr /// Get the register for a given argument slot in the GPRs. 7480c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static int32_t getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) { 7490c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr if (ArgNum >= X86_MAX_GPR_ARGS) { 7500c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr return Variable::NoRegister; 7510c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr } 7520c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static const RegisterSet::AllRegisters GprForArgNum[] = { 7530c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr RegisterSet::Reg_rdi, RegisterSet::Reg_rsi, RegisterSet::Reg_rdx, 7540c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr RegisterSet::Reg_rcx, RegisterSet::Reg_r8, RegisterSet::Reg_r9, 7550c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr }; 7560c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS, 7570c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr "Mismatch between MAX_GPR_ARGS and GprForArgNum."); 7580c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr assert(Ty == IceType_i64 || Ty == IceType_i32); 7590c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr return static_cast<int32_t>(getGprForType(Ty, GprForArgNum[ArgNum])); 7600c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr } 7610c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr 762453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The number of bits in a byte 7630c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr uint32_t X86_CHAR_BIT = 8; 764453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// Stack alignment. This is defined in IceTargetLoweringX8664.cpp because it 765453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// is used as an argument to std::max(), and the default std::less<T> has an 766453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// operator(T const&, T const&) which requires this member to have an 767453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// address. 768453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const uint32_t X86_STACK_ALIGNMENT_BYTES; 769453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// Size of the return address on the stack 7700c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 8; 771453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The number of different NOP instructions 7720c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5; 773453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 774cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull /// \name Limits for unrolling memory intrinsics. 775cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull /// @{ 776cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8; 777cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8; 778cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull static constexpr uint32_t MEMSET_UNROLL_LIMIT = 16; 779cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull /// @} 780cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull 78157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Value is in bytes. Return Value adjusted to the next highest multiple of 78257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// the stack alignment. 783453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static uint32_t applyStackAlignment(uint32_t Value) { 784453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); 785453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 786453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 787453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// Return the type which the elements of the vector have in the X86 788453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// representation of the vector. 789453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static Type getInVectorElementType(Type Ty) { 790453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(isVectorType(Ty)); 791453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto size_t Index = static_cast<size_t>(Ty); 792453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto (void)Index; 793453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(Index < TableTypeX8664AttributesSize); 794453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return TableTypeX8664Attributes[Ty].InVectorElementType; 795453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 796453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 797453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // Note: The following data structures are defined in 798453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // IceTargetLoweringX8664.cpp. 799453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 800453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The following table summarizes the logic for lowering the fcmp 801453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// instruction. There is one table entry for each of the 16 conditions. 802453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// 803453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The first four columns describe the case when the operands are floating 80457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// point scalar values. A comment in lowerFcmp() describes the lowering 80557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// template. In the most general case, there is a compare followed by two 806453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// conditional branches, because some fcmp conditions don't map to a single 80757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// x86 conditional branch. However, in many cases it is possible to swap the 80857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// operands in the comparison and have a single conditional branch. Since 809453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// it's quite tedious to validate the table by hand, good execution tests are 810453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// helpful. 811453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// 812453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The last two columns describe the case when the operands are vectors of 81357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// floating point values. For most fcmp conditions, there is a clear mapping 81457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// to a single x86 cmpps instruction variant. Some fcmp conditions require 815453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// special code to handle and these are marked in the table with a 816453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// Cmpps_Invalid predicate. 817453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// {@ 818453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct TableFcmpType { 819453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto uint32_t Default; 820453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto bool SwapScalarOperands; 821453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Cond::BrCond C1, C2; 822453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto bool SwapVectorOperands; 823453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Cond::CmppsCond Predicate; 824453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } TableFcmp[]; 825453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const size_t TableFcmpSize; 826453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// @} 827453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 828453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The following table summarizes the logic for lowering the icmp instruction 82957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// for i32 and narrower types. Each icmp condition has a clear mapping to an 830453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// x86 conditional branch instruction. 831453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// {@ 832453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[]; 833453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const size_t TableIcmp32Size; 834453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// @} 835453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 836453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The following table summarizes the logic for lowering the icmp instruction 83757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and 83857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// conditional branches are needed. For the other conditions, three separate 839453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// conditional branches are needed. 840453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// {@ 841453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct TableIcmp64Type { 842453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Cond::BrCond C1, C2, C3; 843453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } TableIcmp64[]; 844453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const size_t TableIcmp64Size; 845453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// @} 846453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 847453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { 848453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto size_t Index = static_cast<size_t>(Cond); 849453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(Index < TableIcmp32Size); 850453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return TableIcmp32[Index].Mapping; 851453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 852453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 853453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct TableTypeX8664AttributesType { 854453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Type InVectorElementType; 855453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } TableTypeX8664Attributes[]; 856453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const size_t TableTypeX8664AttributesSize; 857453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 858453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto //---------------------------------------------------------------------------- 859453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // __ __ __ ______ ______ 860453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // /\ \/\ "-.\ \/\ ___\/\__ _\ 861453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // \ \ \ \ \-. \ \___ \/_/\ \/ 862453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // \ \_\ \_\\"\_\/\_____\ \ \_\ 863453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // \/_/\/_/ \/_/\/_____/ \/_/ 864453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // 865453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto //---------------------------------------------------------------------------- 8664a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto using Traits = TargetX8664Traits; 8674a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto using Insts = ::Ice::X8664::Insts<Traits>; 868453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 8694a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto using TargetLowering = ::Ice::X8664::TargetX86Base<Traits>; 8704a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto using ConcreteTarget = ::Ice::X8664::TargetX8664; 8714a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto using Assembler = ::Ice::X8664::AssemblerX86Base<Traits>; 872453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 87357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// X86Operand extends the Operand hierarchy. Its subclasses are X86OperandMem 87457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// and VariableSplit. 875453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto class X86Operand : public ::Ice::Operand { 876453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86Operand() = delete; 877453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86Operand(const X86Operand &) = delete; 878453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86Operand &operator=(const X86Operand &) = delete; 879453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 880453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto public: 881453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto enum OperandKindX8664 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit }; 882453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto using ::Ice::Operand::dump; 883453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 884453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void dump(const Cfg *, Ostream &Str) const override; 885453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 886453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto protected: 887453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86Operand(OperandKindX8664 Kind, Type Ty) 888453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {} 889453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto }; 890453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 891453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// X86OperandMem represents the m64 addressing mode, with optional base and 892453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// index registers, a constant offset, and a fixed shift value for the index 893453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// register. 894453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto class X86OperandMem : public X86Operand { 895453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86OperandMem() = delete; 896453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86OperandMem(const X86OperandMem &) = delete; 897453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86OperandMem &operator=(const X86OperandMem &) = delete; 898453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 899453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto public: 900453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto enum SegmentRegisters { DefaultSegment = -1, SegReg_NUM }; 901453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static X86OperandMem * 902453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto create(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, 903453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Variable *Index = nullptr, uint16_t Shift = 0, 9048ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth SegmentRegisters SegmentRegister = DefaultSegment, 90556958cb33d3c1d045f2844408d825442d523f59fJohn Porto bool IsRebased = false) { 906453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(SegmentRegister == DefaultSegment); 907453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto (void)SegmentRegister; 908453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return new (Func->allocate<X86OperandMem>()) 90956958cb33d3c1d045f2844408d825442d523f59fJohn Porto X86OperandMem(Func, Ty, Base, Offset, Index, Shift, IsRebased); 91056958cb33d3c1d045f2844408d825442d523f59fJohn Porto } 91156958cb33d3c1d045f2844408d825442d523f59fJohn Porto static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base, 91256958cb33d3c1d045f2844408d825442d523f59fJohn Porto Constant *Offset, bool IsRebased) { 91356958cb33d3c1d045f2844408d825442d523f59fJohn Porto constexpr Variable *NoIndex = nullptr; 91456958cb33d3c1d045f2844408d825442d523f59fJohn Porto constexpr uint16_t NoShift = 0; 91556958cb33d3c1d045f2844408d825442d523f59fJohn Porto return new (Func->allocate<X86OperandMem>()) 91656958cb33d3c1d045f2844408d825442d523f59fJohn Porto X86OperandMem(Func, Ty, Base, Offset, NoIndex, NoShift, IsRebased); 917453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 918453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Variable *getBase() const { return Base; } 919453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Constant *getOffset() const { return Offset; } 920453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Variable *getIndex() const { return Index; } 921453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto uint16_t getShift() const { return Shift; } 922453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto SegmentRegisters getSegmentRegister() const { return DefaultSegment; } 923453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void emitSegmentOverride(Assembler *) const {} 92456958cb33d3c1d045f2844408d825442d523f59fJohn Porto bool getIsRebased() const { return IsRebased; } 92556958cb33d3c1d045f2844408d825442d523f59fJohn Porto Address toAsmAddress(Assembler *Asm, const Ice::TargetLowering *Target, 92656958cb33d3c1d045f2844408d825442d523f59fJohn Porto bool IsLeaAddr = false) const; 927453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 928453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void emit(const Cfg *Func) const override; 929453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto using X86Operand::dump; 930453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void dump(const Cfg *Func, Ostream &Str) const override; 931453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 932453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static bool classof(const Operand *Operand) { 933453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return Operand->getKind() == static_cast<OperandKind>(kMem); 934453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 935453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 936453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void setRandomized(bool R) { Randomized = R; } 937453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 938453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto bool getRandomized() const { return Randomized; } 939453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 940453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto private: 941453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, 94256958cb33d3c1d045f2844408d825442d523f59fJohn Porto Variable *Index, uint16_t Shift, bool IsRebased); 943453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 94456958cb33d3c1d045f2844408d825442d523f59fJohn Porto Variable *const Base; 94556958cb33d3c1d045f2844408d825442d523f59fJohn Porto Constant *const Offset; 94656958cb33d3c1d045f2844408d825442d523f59fJohn Porto Variable *const Index; 94756958cb33d3c1d045f2844408d825442d523f59fJohn Porto const uint16_t Shift; 94856958cb33d3c1d045f2844408d825442d523f59fJohn Porto const bool IsRebased; 949453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// A flag to show if this memory operand is a randomized one. Randomized 950453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// memory operands are generated in 951453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// TargetX86Base::randomizeOrPoolImmediate() 952453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto bool Randomized = false; 953453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto }; 954453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 955453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// VariableSplit is a way to treat an f64 memory location as a pair of i32 95657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// locations (Low and High). This is needed for some cases of the Bitcast 95757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// instruction. Since it's not possible for integer registers to access the 958453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// XMM registers and vice versa, the lowering forces the f64 to be spilled to 959453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// the stack and then accesses through the VariableSplit. 960453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit 961453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // targets can natively handle these. 962453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto class VariableSplit : public X86Operand { 963453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto VariableSplit() = delete; 964453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto VariableSplit(const VariableSplit &) = delete; 965453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto VariableSplit &operator=(const VariableSplit &) = delete; 966453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 967453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto public: 968453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto enum Portion { Low, High }; 969453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) { 970453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return new (Func->allocate<VariableSplit>()) 971453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto VariableSplit(Func, Var, Part); 972453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 973453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto int32_t getOffset() const { return Part == High ? 4 : 0; } 974453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 975453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Address toAsmAddress(const Cfg *Func) const; 976453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void emit(const Cfg *Func) const override; 977453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto using X86Operand::dump; 978453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void dump(const Cfg *Func, Ostream &Str) const override; 979453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 980453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static bool classof(const Operand *Operand) { 981453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return Operand->getKind() == static_cast<OperandKind>(kSplit); 982453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 983453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 984453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto private: 985453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto VariableSplit(Cfg *Func, Variable *Var, Portion Part) 986453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) { 987453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(Var->getType() == IceType_f64); 988453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Vars = Func->allocateArrayOf<Variable *>(1); 989453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Vars[0] = Var; 990453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto NumVars = 1; 991453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 992453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 993453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Variable *Var; 994453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Portion Part; 995453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto }; 996453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 99757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// SpillVariable decorates a Variable by linking it to another Variable. When 99857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// stack frame offsets are computed, the SpillVariable is given a distinct 99957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// stack slot only if its linked Variable has a register. If the linked 100057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Variable has a stack slot, then the Variable and SpillVariable share that 100157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// slot. 1002453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto class SpillVariable : public Variable { 1003453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto SpillVariable() = delete; 1004453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto SpillVariable(const SpillVariable &) = delete; 1005453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto SpillVariable &operator=(const SpillVariable &) = delete; 1006453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1007453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto public: 1008453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) { 1009453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index); 1010453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 1011453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const static OperandKind SpillVariableKind = 1012453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static_cast<OperandKind>(kVariable_Target); 1013453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static bool classof(const Operand *Operand) { 1014453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return Operand->getKind() == SpillVariableKind; 1015453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 1016453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void setLinkedTo(Variable *Var) { LinkedTo = Var; } 1017453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Variable *getLinkedTo() const { return LinkedTo; } 1018453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // Inherit dump() and emit() from Variable. 1019453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1020453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto private: 1021453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto SpillVariable(Type Ty, SizeT Index) 1022453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto : Variable(SpillVariableKind, Ty, Index), LinkedTo(nullptr) {} 1023453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Variable *LinkedTo; 1024453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto }; 1025453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1026453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // Note: The following data structures are defined in IceInstX8664.cpp. 1027453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1028453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct InstBrAttributesType { 1029453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Cond::BrCond Opposite; 1030453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *DisplayString; 1031453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *EmitString; 1032453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } InstBrAttributes[]; 1033453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1034453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct InstCmppsAttributesType { 1035453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *EmitString; 1036453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } InstCmppsAttributes[]; 1037453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1038453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct TypeAttributesType { 1039453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *CvtString; // i (integer), s (single FP), d (double FP) 1040453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *SdSsString; // ss, sd, or <blank> 1041e398428c3ef8ed2339c0f334dd30a7d3f0ed4b6eDavid Sehr const char *PdPsString; // ps, pd, or <blank> 1042e398428c3ef8ed2339c0f334dd30a7d3f0ed4b6eDavid Sehr const char *SpSdString; // ss, sd, ps, pd, or <blank> 1043453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *PackString; // b, w, d, or <blank> 1044453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *WidthString; // b, w, l, q, or <blank> 1045453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *FldString; // s, l, or <blank> 1046453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } TypeAttributes[]; 10472fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto}; 10482fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 10494a56686b5b56db6803f90ad53514bf2fa190d9f7John Portousing Traits = ::Ice::X8664::TargetX8664Traits; 10502fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto} // end of namespace X8664 10512fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 10522fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto} // end of namespace Ice 10532fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 10542fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H 1055