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 = 53464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens ::Ice::Assembler::Asm_X8664; 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; 718aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static constexpr RegisterSet::AllRegisters StackPtr = RegX8664::Reg_rsp; 728aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static constexpr RegisterSet::AllRegisters 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; 7727fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto static constexpr FixupKind FK_Abs = llvm::ELF::R_X86_64_32S; 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 304467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth static const char *getRegName(RegNumT 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 }; 3138aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNum.assertIsValid(); 3145bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return RegNames[RegNum]; 3155bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } 3165bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth 3178aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static GPRRegister getEncodedGPR(RegNumT RegNum) { 3184a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = { 3195bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 32056958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 32156958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 3225bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR), 323453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto REGX8664_TABLE 324453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X 325453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto }; 3268aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNum.assertIsValid(); 3275bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR); 3285bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return GPRRegs[RegNum]; 3295bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } 330453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 3318aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static ByteRegister getEncodedByteReg(RegNumT RegNum) { 3324a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = { 3335bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 33456958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 33556958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 3365bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg), 3375bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth REGX8664_TABLE 3385bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X 3395bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth }; 3408aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNum.assertIsValid(); 3415bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg); 3425bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return ByteRegs[RegNum]; 343453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 344453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 3458aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static XmmRegister getEncodedXmm(RegNumT RegNum) { 3464a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = { 3475bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 34856958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 34956958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 3505bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm), 3515bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth REGX8664_TABLE 3525bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X 3535bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth }; 3548aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNum.assertIsValid(); 3555bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm); 3565bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return XmmRegs[RegNum]; 3575bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } 3585bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth 3598aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static uint32_t getEncoding(RegNumT RegNum) { 3604a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static const uint32_t Encoding[RegisterSet::Reg_NUM] = { 3615bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 36256958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 36356958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 3645bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth encode, 3655bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth REGX8664_TABLE 3665bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X 3675bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth }; 3688aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNum.assertIsValid(); 3695bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return Encoding[RegNum]; 3705bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } 3715bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth 3728aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static inline RegNumT getBaseReg(RegNumT RegNum) { 3738aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = { 3745bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 37556958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 37656958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 3778aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegisterSet::base, 3785bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth REGX8664_TABLE 3795bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X 3805bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth }; 3818aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNum.assertIsValid(); 3825bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth return BaseRegs[RegNum]; 3835bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } 3845bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth 385008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Portoprivate: 3868aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static RegNumT getFirstGprForType(Type Ty) { 387008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto switch (Ty) { 388008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto default: 389008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto llvm_unreachable("Invalid type for GPR."); 390008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case IceType_i1: 391008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case IceType_i8: 392008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegisterSet::Reg_al; 393008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case IceType_i16: 394008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegisterSet::Reg_ax; 395008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case IceType_i32: 396008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegisterSet::Reg_eax; 397008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case IceType_i64: 398008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegisterSet::Reg_rax; 399008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 400008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 401008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 402008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Portopublic: 4038aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static RegNumT getGprForType(Type Ty, RegNumT RegNum) { 4045fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler assert(RegNum.hasValue()); 405008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 406008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto if (!isScalarIntegerType(Ty)) { 407008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegNum; 408008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 409008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 410008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(Ty == IceType_i1 || Ty == IceType_i8 || Ty == IceType_i16 || 411008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto Ty == IceType_i32 || Ty == IceType_i64); 412008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 413008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto if (RegNum == RegisterSet::Reg_ah) { 414008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(Ty == IceType_i8); 415008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return RegNum; 416008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 417008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 418008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(RegNum != RegisterSet::Reg_bh); 419008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(RegNum != RegisterSet::Reg_ch); 420008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(RegNum != RegisterSet::Reg_dh); 421008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 4228aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth const RegNumT FirstGprForType = getFirstGprForType(Ty); 423008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto 424008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto switch (RegNum) { 425008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto default: 426008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto llvm::report_fatal_error("Unknown register."); 427008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 42856958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 42956958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 430008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto case RegisterSet::val: { \ 43156958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (!isGPR) \ 43256958cb33d3c1d045f2844408d825442d523f59fJohn Porto return RegisterSet::val; \ 433008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert((is64) || (is32) || (is16) || (is8) || \ 434ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth getBaseReg(RegisterSet::val) == RegisterSet::Reg_rsp); \ 4358aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize = \ 436ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth ((is64) || RegisterSet::val == RegisterSet::Reg_rsp) \ 437008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto ? RegisterSet::Reg_rax \ 438ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth : (((is32) || RegisterSet::val == RegisterSet::Reg_esp) \ 439008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto ? RegisterSet::Reg_eax \ 440ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth : (((is16) || RegisterSet::val == RegisterSet::Reg_sp) \ 441008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto ? RegisterSet::Reg_ax \ 442008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto : RegisterSet::Reg_al)); \ 4438aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth const auto NewRegNum = \ 4448aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType); \ 445008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) && \ 446008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto "Error involving " #val); \ 447008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto return NewRegNum; \ 448008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 449008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto REGX8664_TABLE 450008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto#undef X 451008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 452008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto } 4535bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth 4544a308cedda6bfe381dc9506f3508c4547a06275fJohn Portoprivate: 4554a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto /// SizeOf is used to obtain the size of an initializer list as a constexpr 4564a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto /// expression. This is only needed until our C++ library is updated to 4574a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto /// C++ 14 -- which defines constexpr members to std::initializer_list. 4584a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto class SizeOf { 4594a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto SizeOf(const SizeOf &) = delete; 4604a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto SizeOf &operator=(const SizeOf &) = delete; 4614a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 4624a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto public: 4634a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto constexpr SizeOf() : Size(0) {} 4644a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto template <typename... T> 4654a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto explicit constexpr SizeOf(T...) 46656958cb33d3c1d045f2844408d825442d523f59fJohn Porto : Size(length<T...>::value) {} 4674a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto constexpr SizeT size() const { return Size; } 4684a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 4694a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto private: 47056958cb33d3c1d045f2844408d825442d523f59fJohn Porto template <typename T, typename... U> struct length { 47156958cb33d3c1d045f2844408d825442d523f59fJohn Porto static constexpr std::size_t value = 1 + length<U...>::value; 4724a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto }; 4734a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 47456958cb33d3c1d045f2844408d825442d523f59fJohn Porto template <typename T> struct length<T> { 4754a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static constexpr std::size_t value = 1; 4764a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto }; 4774a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 4784a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto const std::size_t Size; 4794a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto }; 4804a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 4814a308cedda6bfe381dc9506f3508c4547a06275fJohn Portopublic: 482bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto static void initRegisterSet( 48356958cb33d3c1d045f2844408d825442d523f59fJohn Porto const ::Ice::ClFlags &Flags, 484e82b560e649f8a68bcb252b9b002708e74d962d3John Porto std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet, 485e82b560e649f8a68bcb252b9b002708e74d962d3John Porto std::array<SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) { 486e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector IntegerRegistersI64(RegisterSet::Reg_NUM); 487e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM); 488e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM); 489e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM); 490e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector FloatRegisters(RegisterSet::Reg_NUM); 491e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector VectorRegisters(RegisterSet::Reg_NUM); 492e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM); 493e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM); 494e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM); 495e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM); 496e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM); 497e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM); 498bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto 4994a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto static constexpr struct { 5004a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto uint16_t Val; 50156958cb33d3c1d045f2844408d825442d523f59fJohn Porto unsigned IsReservedWhenSandboxing : 1; 502caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is64 : 1; 503caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is32 : 1; 504caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is16 : 1; 505caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is8 : 1; 506caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned IsXmm : 1; 507caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is64To8 : 1; 508caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is32To8 : 1; 509caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned Is16To8 : 1; 510caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned IsTrunc8Rcvr : 1; 511caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth unsigned IsAhRcvr : 1; 5124a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#define NUM_ALIASES_BITS 2 5134a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto SizeT NumAliases : (NUM_ALIASES_BITS + 1); 5144a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto uint16_t Aliases[1 << NUM_ALIASES_BITS]; 5154a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#undef NUM_ALIASES_BITS 5164a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto } X8664RegTable[RegisterSet::Reg_NUM] = { 5175bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 51856958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 51956958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 5204a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto { \ 52156958cb33d3c1d045f2844408d825442d523f59fJohn Porto RegisterSet::val, sboxres, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 52229d15fd619f1d46f8e0c3d22932b9931c4b81367Jim Stichnoth is16To8, isTrunc8Rcvr, isAhRcvr, (SizeOf aliases).size(), aliases, \ 5235bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth } \ 5244a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto , 5254a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto REGX8664_TABLE 526453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X 5274a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto }; 5284a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto 52956958cb33d3c1d045f2844408d825442d523f59fJohn Porto const bool NeedSandboxing = Flags.getUseSandboxing(); 5304a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto for (SizeT ii = 0; ii < llvm::array_lengthof(X8664RegTable); ++ii) { 5314a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto const auto &Entry = X8664RegTable[ii]; 53256958cb33d3c1d045f2844408d825442d523f59fJohn Porto // Even though the register is disabled for register allocation, it might 53356958cb33d3c1d045f2844408d825442d523f59fJohn Porto // still be used by the Target Lowering (e.g., base pointer), so the 53456958cb33d3c1d045f2844408d825442d523f59fJohn Porto // register alias table still needs to be defined. 53556958cb33d3c1d045f2844408d825442d523f59fJohn Porto (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM); 53656958cb33d3c1d045f2844408d825442d523f59fJohn Porto for (int J = 0; J < Entry.NumAliases; ++J) { 53756958cb33d3c1d045f2844408d825442d523f59fJohn Porto SizeT Alias = Entry.Aliases[J]; 53856958cb33d3c1d045f2844408d825442d523f59fJohn Porto assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias"); 53956958cb33d3c1d045f2844408d825442d523f59fJohn Porto (*RegisterAliases)[Entry.Val].set(Alias); 54056958cb33d3c1d045f2844408d825442d523f59fJohn Porto } 54156958cb33d3c1d045f2844408d825442d523f59fJohn Porto 54256958cb33d3c1d045f2844408d825442d523f59fJohn Porto (*RegisterAliases)[Entry.Val].set(Entry.Val); 54356958cb33d3c1d045f2844408d825442d523f59fJohn Porto const bool DisabledRegister = 54456958cb33d3c1d045f2844408d825442d523f59fJohn Porto NeedSandboxing && Entry.IsReservedWhenSandboxing; 54556958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (DisabledRegister) { 54656958cb33d3c1d045f2844408d825442d523f59fJohn Porto continue; 54756958cb33d3c1d045f2844408d825442d523f59fJohn Porto } 5484a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (IntegerRegistersI64)[Entry.Val] = Entry.Is64; 5494a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (IntegerRegistersI32)[Entry.Val] = Entry.Is32; 5504a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (IntegerRegistersI16)[Entry.Val] = Entry.Is16; 5514a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (IntegerRegistersI8)[Entry.Val] = Entry.Is8; 5524a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (FloatRegisters)[Entry.Val] = Entry.IsXmm; 5534a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (VectorRegisters)[Entry.Val] = Entry.IsXmm; 5544a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8; 5554a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8; 5564a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8; 5574a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr; 5584a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr; 5594a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto } 560bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto 561c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_void] = InvalidRegisters; 562c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8; 563c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8; 564c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16; 565c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32; 566c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_i64] = IntegerRegistersI64; 567c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_f32] = FloatRegisters; 568c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_f64] = FloatRegisters; 569c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters; 570c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters; 571c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters; 572c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters; 573c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters; 574c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters; 575c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters; 576c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers; 577c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers; 578c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers; 579c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters; 580c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters; 581453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 582453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 583e82b560e649f8a68bcb252b9b002708e74d962d3John Porto static SmallBitVector getRegisterSet(const ::Ice::ClFlags &Flags, 584e82b560e649f8a68bcb252b9b002708e74d962d3John Porto TargetLowering::RegSetMask Include, 585e82b560e649f8a68bcb252b9b002708e74d962d3John Porto TargetLowering::RegSetMask Exclude) { 586e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector Registers(RegisterSet::Reg_NUM); 587453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 58856958cb33d3c1d045f2844408d825442d523f59fJohn Porto const bool NeedSandboxing = Flags.getUseSandboxing(); 5895bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 59056958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 59156958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 59256958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (!NeedSandboxing || !(sboxres)) { \ 59356958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave)) \ 59456958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = true; \ 59556958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave)) \ 59656958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = true; \ 59756958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer)) \ 59856958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = true; \ 59956958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer)) \ 60056958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = true; \ 60156958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave)) \ 60256958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = false; \ 60356958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave)) \ 60456958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = false; \ 60556958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer)) \ 60656958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = false; \ 60756958cb33d3c1d045f2844408d825442d523f59fJohn Porto if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer)) \ 60856958cb33d3c1d045f2844408d825442d523f59fJohn Porto Registers[RegisterSet::val] = false; \ 60956958cb33d3c1d045f2844408d825442d523f59fJohn Porto } 610453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 611453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto REGX8664_TABLE 612453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 613453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X 614453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 615453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return Registers; 616453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 617453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 618d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf static void makeRandomRegisterPermutation( 619d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf Cfg *Func, llvm::SmallVectorImpl<RegNumT> &Permutation, 620d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf const SmallBitVector &ExcludeRegisters, uint64_t Salt) { 621453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // TODO(stichnot): Declaring Permutation this way loses type/size 62257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // information. Fix this in conjunction with the caller-side TODO. 623453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(Permutation.size() >= RegisterSet::Reg_NUM); 624453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // Expected upper bound on the number of registers in a single equivalence 62557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // class. For x86-64, this would comprise the 16 XMM registers. This is 626453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // for performance, not correctness. 627453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const unsigned MaxEquivalenceClassSize = 8; 6288aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth using RegisterList = llvm::SmallVector<RegNumT, MaxEquivalenceClassSize>; 6298072bae156fa62e51e02925997992c4908a2682fAndrew Scull using EquivalenceClassMap = std::map<uint32_t, RegisterList>; 630453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto EquivalenceClassMap EquivalenceClasses; 631453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto SizeT NumShuffled = 0, NumPreserved = 0; 632453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 633453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// Build up the equivalence classes of registers by looking at the register 634453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// properties as well as whether the registers should be explicitly excluded 635453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// from shuffling. 6365bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 63756958cb33d3c1d045f2844408d825442d523f59fJohn Porto sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 63856958cb33d3c1d045f2844408d825442d523f59fJohn Porto is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 639453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto if (ExcludeRegisters[RegisterSet::val]) { \ 640453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /* val stays the same in the resulting permutation. */ \ 641453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Permutation[RegisterSet::val] = RegisterSet::val; \ 642453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto ++NumPreserved; \ 643453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } else { \ 6445bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth uint32_t AttrKey = 0; \ 6455bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth uint32_t Index = 0; \ 6465bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth /* Combine relevant attributes into an equivalence class key. */ \ 6475bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (scratch << (AttrKey++)); \ 6485bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (preserved << (AttrKey++)); \ 6495bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (is8 << (AttrKey++)); \ 6505bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (is16 << (AttrKey++)); \ 6515bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (is32 << (AttrKey++)); \ 6525bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (is64 << (AttrKey++)); \ 6535bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Index |= (isXmm << (AttrKey++)); \ 654c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth Index |= (is16To8 << (AttrKey++)); \ 655c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth Index |= (is32To8 << (AttrKey++)); \ 656c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth Index |= (is64To8 << (AttrKey++)); \ 657c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth Index |= (isTrunc8Rcvr << (AttrKey++)); \ 658453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /* val is assigned to an equivalence class based on its properties. */ \ 659453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto EquivalenceClasses[Index].push_back(RegisterSet::val); \ 660453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 661453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto REGX8664_TABLE 662453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X 663453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 664aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu // Create a random number generator for regalloc randomization. 665d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf RandomNumberGenerator RNG(getFlags().getRandomSeed(), 666aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RPE_RegAllocRandomization, Salt); 667aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RandomNumberGeneratorWrapper RNGW(RNG); 668453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 669453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // Shuffle the resulting equivalence classes. 670453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto for (auto I : EquivalenceClasses) { 671453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const RegisterList &List = I.second; 672453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto RegisterList Shuffled(List); 673aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW); 674453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { 675453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Permutation[List[SI]] = Shuffled[SI]; 676453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto ++NumShuffled; 677453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 678453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 679453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 680453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM); 681453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 682453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto if (Func->isVerbose(IceV_Random)) { 683453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto OstreamLocker L(Func->getContext()); 684453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Ostream &Str = Func->getContext()->getStrDump(); 685453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Str << "Register equivalence classes:\n"; 686453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto for (auto I : EquivalenceClasses) { 687453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Str << "{"; 688453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const RegisterList &List = I.second; 689453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto bool First = true; 6908aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth for (RegNumT Register : List) { 691453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto if (!First) 692453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Str << " "; 693453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto First = false; 6945bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth Str << getRegName(Register); 695453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 696453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Str << "}\n"; 697453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 698453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 699453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 700453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 7018aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static RegNumT getRaxOrDie() { return RegisterSet::Reg_rax; } 7023c275ce1e832ba9ccfb730c4235db786cf080465John Porto 7038aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static RegNumT getRdxOrDie() { return RegisterSet::Reg_rdx; } 7043c275ce1e832ba9ccfb730c4235db786cf080465John Porto 7054e679e51f645b99940f43c80fec7f146d59eb00fNicolas Capens#if defined(SUBZERO_USE_MICROSOFT_ABI) 706464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // Microsoft x86-64 calling convention: 707464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // 708464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // * The first four arguments of vector/fp type, regardless of their 709464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // position relative to the other arguments in the argument list, are placed 710464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // in registers %xmm0 - %xmm3. 711464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // 712464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // * The first four arguments of integer types, regardless of their position 713464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // relative to the other arguments in the argument list, are placed in 714464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // registers %rcx, %rdx, %r8, and %r9. 715464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens 716464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens /// The maximum number of arguments to pass in XMM registers 717464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens static constexpr uint32_t X86_MAX_XMM_ARGS = 4; 718464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens /// The maximum number of arguments to pass in GPR registers 719464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens static constexpr uint32_t X86_MAX_GPR_ARGS = 4; 720464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) { 721464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens if (ArgNum >= X86_MAX_GPR_ARGS) { 722464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens return RegNumT(); 723464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens } 724464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens static const RegisterSet::AllRegisters GprForArgNum[] = { 725464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens RegisterSet::Reg_rcx, RegisterSet::Reg_rdx, RegisterSet::Reg_r8, 726464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens RegisterSet::Reg_r9, 727464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens }; 728464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS, 729464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens "Mismatch between MAX_GPR_ARGS and GprForArgNum."); 730464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens assert(Ty == IceType_i64 || Ty == IceType_i32); 731464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens return getGprForType(Ty, GprForArgNum[ArgNum]); 732464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens } 7334b1bdae3955769f62e563e826065d10ddfe040eaNicolas Capens#else 734464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // System V x86-64 calling convention: 7350c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // 7360c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // * The first eight arguments of vector/fp type, regardless of their 7370c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // position relative to the other arguments in the argument list, are placed 7380c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // in registers %xmm0 - %xmm7. 7390c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // 7400c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // * The first six arguments of integer types, regardless of their position 7410c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // relative to the other arguments in the argument list, are placed in 7420c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9. 7430c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // 7440c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // This intends to match the section "Function Calling Sequence" of the 7450c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr // document "System V Application Binary Interface." 7460c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr 747453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The maximum number of arguments to pass in XMM registers 7480c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr uint32_t X86_MAX_XMM_ARGS = 8; 749e0d9afa80ee55711d25fae87e50d11685d1ad6d7John Porto /// The maximum number of arguments to pass in GPR registers 7500c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr uint32_t X86_MAX_GPR_ARGS = 6; 7510c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr /// Get the register for a given argument slot in the GPRs. 7528aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) { 7530c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr if (ArgNum >= X86_MAX_GPR_ARGS) { 7545fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler return RegNumT(); 7550c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr } 7560c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static const RegisterSet::AllRegisters GprForArgNum[] = { 7570c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr RegisterSet::Reg_rdi, RegisterSet::Reg_rsi, RegisterSet::Reg_rdx, 7580c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr RegisterSet::Reg_rcx, RegisterSet::Reg_r8, RegisterSet::Reg_r9, 7590c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr }; 7600c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS, 7610c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr "Mismatch between MAX_GPR_ARGS and GprForArgNum."); 7620c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr assert(Ty == IceType_i64 || Ty == IceType_i32); 7638aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth return getGprForType(Ty, GprForArgNum[ArgNum]); 7640c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr } 76573ae4fdc32345ad1dc44cc5268204174555b2b55Nicolas Capens#endif 766464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens 767464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens /// Whether scalar floating point arguments are passed in XMM registers 768464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = true; 769464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens /// Get the register for a given argument slot in the XMM registers. 770464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) { 771464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens // TODO(sehr): Change to use the CCArg technique used in ARM32. 772464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1, 773464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens "Inconsistency between XMM register numbers and ordinals"); 774464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens if (ArgNum >= X86_MAX_XMM_ARGS) { 775464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens return RegNumT(); 776464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens } 777464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum); 778464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens } 7790c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr 780453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The number of bits in a byte 7810c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr uint32_t X86_CHAR_BIT = 8; 782453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// Stack alignment. This is defined in IceTargetLoweringX8664.cpp because it 783453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// is used as an argument to std::max(), and the default std::less<T> has an 784453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// operator(T const&, T const&) which requires this member to have an 785453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// address. 786453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const uint32_t X86_STACK_ALIGNMENT_BYTES; 787453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// Size of the return address on the stack 7880c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 8; 789453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The number of different NOP instructions 7900c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5; 791453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 792cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull /// \name Limits for unrolling memory intrinsics. 793cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull /// @{ 794cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8; 795cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8; 79635e160025c5a7005f97c5ad55120999cf83a4ce1Jim Stichnoth static constexpr uint32_t MEMSET_UNROLL_LIMIT = 8; 797cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull /// @} 798cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull 79957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Value is in bytes. Return Value adjusted to the next highest multiple of 80057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// the stack alignment. 801453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static uint32_t applyStackAlignment(uint32_t Value) { 802453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); 803453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 804453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 805453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// Return the type which the elements of the vector have in the X86 806453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// representation of the vector. 807453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static Type getInVectorElementType(Type Ty) { 808453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(isVectorType(Ty)); 8092d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth assert(Ty < TableTypeX8664AttributesSize); 810453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return TableTypeX8664Attributes[Ty].InVectorElementType; 811453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 812453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 813453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // Note: The following data structures are defined in 814453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // IceTargetLoweringX8664.cpp. 815453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 816453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The following table summarizes the logic for lowering the fcmp 817453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// instruction. There is one table entry for each of the 16 conditions. 818453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// 819453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The first four columns describe the case when the operands are floating 82057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// point scalar values. A comment in lowerFcmp() describes the lowering 82157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// template. In the most general case, there is a compare followed by two 822453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// conditional branches, because some fcmp conditions don't map to a single 82357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// x86 conditional branch. However, in many cases it is possible to swap the 82457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// operands in the comparison and have a single conditional branch. Since 825453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// it's quite tedious to validate the table by hand, good execution tests are 826453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// helpful. 827453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// 828453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The last two columns describe the case when the operands are vectors of 82957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// floating point values. For most fcmp conditions, there is a clear mapping 83057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// to a single x86 cmpps instruction variant. Some fcmp conditions require 831453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// special code to handle and these are marked in the table with a 832453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// Cmpps_Invalid predicate. 833453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// {@ 834453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct TableFcmpType { 835453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto uint32_t Default; 836453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto bool SwapScalarOperands; 837453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Cond::BrCond C1, C2; 838453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto bool SwapVectorOperands; 839453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Cond::CmppsCond Predicate; 840453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } TableFcmp[]; 841453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const size_t TableFcmpSize; 842453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// @} 843453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 844453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The following table summarizes the logic for lowering the icmp instruction 84557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// for i32 and narrower types. Each icmp condition has a clear mapping to an 846453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// x86 conditional branch instruction. 847453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// {@ 848453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[]; 849453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const size_t TableIcmp32Size; 850453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// @} 851453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 852453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// The following table summarizes the logic for lowering the icmp instruction 85357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and 85457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// conditional branches are needed. For the other conditions, three separate 855453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// conditional branches are needed. 856453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// {@ 857453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct TableIcmp64Type { 858453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Cond::BrCond C1, C2, C3; 859453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } TableIcmp64[]; 860453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const size_t TableIcmp64Size; 861453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// @} 862453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 863453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { 8642d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth assert(Cond < TableIcmp32Size); 8652d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth return TableIcmp32[Cond].Mapping; 866453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 867453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 868453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct TableTypeX8664AttributesType { 869453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Type InVectorElementType; 870453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } TableTypeX8664Attributes[]; 871453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const size_t TableTypeX8664AttributesSize; 872453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 873453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto //---------------------------------------------------------------------------- 874453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // __ __ __ ______ ______ 875453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // /\ \/\ "-.\ \/\ ___\/\__ _\ 876453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // \ \ \ \ \-. \ \___ \/_/\ \/ 877453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // \ \_\ \_\\"\_\/\_____\ \ \_\ 878453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // \/_/\/_/ \/_/\/_____/ \/_/ 879453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // 880453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto //---------------------------------------------------------------------------- 8814a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto using Traits = TargetX8664Traits; 8824a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto using Insts = ::Ice::X8664::Insts<Traits>; 883453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 8844a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto using TargetLowering = ::Ice::X8664::TargetX86Base<Traits>; 8854a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto using ConcreteTarget = ::Ice::X8664::TargetX8664; 8864a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto using Assembler = ::Ice::X8664::AssemblerX86Base<Traits>; 887453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 88857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// X86Operand extends the Operand hierarchy. Its subclasses are X86OperandMem 88957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// and VariableSplit. 890453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto class X86Operand : public ::Ice::Operand { 891453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86Operand() = delete; 892453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86Operand(const X86Operand &) = delete; 893453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86Operand &operator=(const X86Operand &) = delete; 894453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 895453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto public: 896453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto enum OperandKindX8664 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit }; 897453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto using ::Ice::Operand::dump; 898453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 899453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void dump(const Cfg *, Ostream &Str) const override; 900453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 901453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto protected: 902453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86Operand(OperandKindX8664 Kind, Type Ty) 903453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {} 904453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto }; 905453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 906453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// X86OperandMem represents the m64 addressing mode, with optional base and 907453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// index registers, a constant offset, and a fixed shift value for the index 908453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// register. 909453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto class X86OperandMem : public X86Operand { 910453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86OperandMem() = delete; 911453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86OperandMem(const X86OperandMem &) = delete; 912453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86OperandMem &operator=(const X86OperandMem &) = delete; 913453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 914453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto public: 915453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto enum SegmentRegisters { DefaultSegment = -1, SegReg_NUM }; 916453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static X86OperandMem * 917453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto create(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, 918453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Variable *Index = nullptr, uint16_t Shift = 0, 9198ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth SegmentRegisters SegmentRegister = DefaultSegment, 92056958cb33d3c1d045f2844408d825442d523f59fJohn Porto bool IsRebased = false) { 921453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(SegmentRegister == DefaultSegment); 922453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto (void)SegmentRegister; 923453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return new (Func->allocate<X86OperandMem>()) 92456958cb33d3c1d045f2844408d825442d523f59fJohn Porto X86OperandMem(Func, Ty, Base, Offset, Index, Shift, IsRebased); 92556958cb33d3c1d045f2844408d825442d523f59fJohn Porto } 92656958cb33d3c1d045f2844408d825442d523f59fJohn Porto static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base, 92756958cb33d3c1d045f2844408d825442d523f59fJohn Porto Constant *Offset, bool IsRebased) { 92856958cb33d3c1d045f2844408d825442d523f59fJohn Porto constexpr Variable *NoIndex = nullptr; 92956958cb33d3c1d045f2844408d825442d523f59fJohn Porto constexpr uint16_t NoShift = 0; 93056958cb33d3c1d045f2844408d825442d523f59fJohn Porto return new (Func->allocate<X86OperandMem>()) 93156958cb33d3c1d045f2844408d825442d523f59fJohn Porto X86OperandMem(Func, Ty, Base, Offset, NoIndex, NoShift, IsRebased); 932453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 933453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Variable *getBase() const { return Base; } 934453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Constant *getOffset() const { return Offset; } 935453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Variable *getIndex() const { return Index; } 936453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto uint16_t getShift() const { return Shift; } 937453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto SegmentRegisters getSegmentRegister() const { return DefaultSegment; } 938453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void emitSegmentOverride(Assembler *) const {} 93956958cb33d3c1d045f2844408d825442d523f59fJohn Porto bool getIsRebased() const { return IsRebased; } 94056958cb33d3c1d045f2844408d825442d523f59fJohn Porto Address toAsmAddress(Assembler *Asm, const Ice::TargetLowering *Target, 94156958cb33d3c1d045f2844408d825442d523f59fJohn Porto bool IsLeaAddr = false) const; 942453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 943453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void emit(const Cfg *Func) const override; 944453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto using X86Operand::dump; 945453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void dump(const Cfg *Func, Ostream &Str) const override; 946453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 947453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static bool classof(const Operand *Operand) { 948453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return Operand->getKind() == static_cast<OperandKind>(kMem); 949453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 950453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 951453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void setRandomized(bool R) { Randomized = R; } 952453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 953453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto bool getRandomized() const { return Randomized; } 954453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 955453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto private: 956453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, 95756958cb33d3c1d045f2844408d825442d523f59fJohn Porto Variable *Index, uint16_t Shift, bool IsRebased); 958453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 95956958cb33d3c1d045f2844408d825442d523f59fJohn Porto Variable *const Base; 96056958cb33d3c1d045f2844408d825442d523f59fJohn Porto Constant *const Offset; 96156958cb33d3c1d045f2844408d825442d523f59fJohn Porto Variable *const Index; 96256958cb33d3c1d045f2844408d825442d523f59fJohn Porto const uint16_t Shift; 96356958cb33d3c1d045f2844408d825442d523f59fJohn Porto const bool IsRebased; 964453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// A flag to show if this memory operand is a randomized one. Randomized 965453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// memory operands are generated in 966453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// TargetX86Base::randomizeOrPoolImmediate() 967453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto bool Randomized = false; 968453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto }; 969453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 970453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// VariableSplit is a way to treat an f64 memory location as a pair of i32 97157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// locations (Low and High). This is needed for some cases of the Bitcast 97257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// instruction. Since it's not possible for integer registers to access the 973453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// XMM registers and vice versa, the lowering forces the f64 to be spilled to 974453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto /// the stack and then accesses through the VariableSplit. 975453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit 976453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // targets can natively handle these. 977453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto class VariableSplit : public X86Operand { 978453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto VariableSplit() = delete; 979453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto VariableSplit(const VariableSplit &) = delete; 980453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto VariableSplit &operator=(const VariableSplit &) = delete; 981453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 982453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto public: 983453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto enum Portion { Low, High }; 984453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) { 985453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return new (Func->allocate<VariableSplit>()) 986453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto VariableSplit(Func, Var, Part); 987453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 988453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto int32_t getOffset() const { return Part == High ? 4 : 0; } 989453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 990453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Address toAsmAddress(const Cfg *Func) const; 991453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void emit(const Cfg *Func) const override; 992453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto using X86Operand::dump; 993453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto void dump(const Cfg *Func, Ostream &Str) const override; 994453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 995453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static bool classof(const Operand *Operand) { 996453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto return Operand->getKind() == static_cast<OperandKind>(kSplit); 997453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 998453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 999453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto private: 1000453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto VariableSplit(Cfg *Func, Variable *Var, Portion Part) 1001453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) { 1002453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto assert(Var->getType() == IceType_f64); 1003453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Vars = Func->allocateArrayOf<Variable *>(1); 1004453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Vars[0] = Var; 1005453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto NumVars = 1; 1006453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } 1007453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1008453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Variable *Var; 1009453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Portion Part; 1010453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto }; 1011453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1012453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto // Note: The following data structures are defined in IceInstX8664.cpp. 1013453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1014453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct InstBrAttributesType { 1015453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto Cond::BrCond Opposite; 1016453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *DisplayString; 1017453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *EmitString; 1018453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } InstBrAttributes[]; 1019453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1020453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct InstCmppsAttributesType { 1021453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto const char *EmitString; 1022453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } InstCmppsAttributes[]; 1023453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto 1024453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto static const struct TypeAttributesType { 10257638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens const char *CvtString; // i (integer), s (single FP), d (double FP) 10267638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens const char *SdSsString; // ss, sd, or <blank> 10277638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens const char *PdPsString; // ps, pd, or <blank> 10287638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens const char *SpSdString; // ss, sd, ps, pd, or <blank> 10297638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens const char *IntegralString; // b, w, d, or <blank> 10307638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens const char *UnpackString; // bw, wd, dq, or <blank> 10317638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens const char *PackString; // wb, dw, or <blank> 10327638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens const char *WidthString; // b, w, l, q, or <blank> 10337638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens const char *FldString; // s, l, or <blank> 1034453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto } TypeAttributes[]; 10352fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto}; 10362fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 10374a56686b5b56db6803f90ad53514bf2fa190d9f7John Portousing Traits = ::Ice::X8664::TargetX8664Traits; 10382fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto} // end of namespace X8664 10392fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 10402fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto} // end of namespace Ice 10412fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto 10422fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H 1043