IceTargetLoweringX8632Traits.h revision 5d0acff3a2fa421923392aadb4df2742064b6248
15d0acff3a2fa421923392aadb4df2742064b6248John Porto//===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- C++ -*-=// 25d0acff3a2fa421923392aadb4df2742064b6248John Porto// 35d0acff3a2fa421923392aadb4df2742064b6248John Porto// The Subzero Code Generator 45d0acff3a2fa421923392aadb4df2742064b6248John Porto// 55d0acff3a2fa421923392aadb4df2742064b6248John Porto// This file is distributed under the University of Illinois Open Source 65d0acff3a2fa421923392aadb4df2742064b6248John Porto// License. See LICENSE.TXT for details. 75d0acff3a2fa421923392aadb4df2742064b6248John Porto// 85d0acff3a2fa421923392aadb4df2742064b6248John Porto//===----------------------------------------------------------------------===// 95d0acff3a2fa421923392aadb4df2742064b6248John Porto// 105d0acff3a2fa421923392aadb4df2742064b6248John Porto// This file defines the X8632 Target Lowering Traits. 115d0acff3a2fa421923392aadb4df2742064b6248John Porto// 125d0acff3a2fa421923392aadb4df2742064b6248John Porto//===----------------------------------------------------------------------===// 135d0acff3a2fa421923392aadb4df2742064b6248John Porto 145d0acff3a2fa421923392aadb4df2742064b6248John Porto#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H 155d0acff3a2fa421923392aadb4df2742064b6248John Porto#define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H 165d0acff3a2fa421923392aadb4df2742064b6248John Porto 175d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceAssembler.h" 185d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceConditionCodesX8632.h" 195d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceDefs.h" 205d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceInst.h" 215d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceInstX8632.def" 225d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceRegistersX8632.h" 235d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceTargetLoweringX8632.def" 245d0acff3a2fa421923392aadb4df2742064b6248John Porto 255d0acff3a2fa421923392aadb4df2742064b6248John Portonamespace Ice { 265d0acff3a2fa421923392aadb4df2742064b6248John Porto 275d0acff3a2fa421923392aadb4df2742064b6248John Portoclass TargetX8632; 285d0acff3a2fa421923392aadb4df2742064b6248John Porto 295d0acff3a2fa421923392aadb4df2742064b6248John Portonamespace X86Internal { 305d0acff3a2fa421923392aadb4df2742064b6248John Porto 315d0acff3a2fa421923392aadb4df2742064b6248John Portotemplate <class Machine> struct MachineTraits; 325d0acff3a2fa421923392aadb4df2742064b6248John Porto 335d0acff3a2fa421923392aadb4df2742064b6248John Portotemplate <> struct MachineTraits<TargetX8632> { 345d0acff3a2fa421923392aadb4df2742064b6248John Porto //---------------------------------------------------------------------------- 355d0acff3a2fa421923392aadb4df2742064b6248John Porto // ______ ______ __ __ 365d0acff3a2fa421923392aadb4df2742064b6248John Porto // /\ __ \/\ ___\/\ "-./ \ 375d0acff3a2fa421923392aadb4df2742064b6248John Porto // \ \ __ \ \___ \ \ \-./\ \ 385d0acff3a2fa421923392aadb4df2742064b6248John Porto // \ \_\ \_\/\_____\ \_\ \ \_\ 395d0acff3a2fa421923392aadb4df2742064b6248John Porto // \/_/\/_/\/_____/\/_/ \/_/ 405d0acff3a2fa421923392aadb4df2742064b6248John Porto // 415d0acff3a2fa421923392aadb4df2742064b6248John Porto //---------------------------------------------------------------------------- 425d0acff3a2fa421923392aadb4df2742064b6248John Porto enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; 435d0acff3a2fa421923392aadb4df2742064b6248John Porto 445d0acff3a2fa421923392aadb4df2742064b6248John Porto using GPRRegister = ::Ice::RegX8632::GPRRegister; 455d0acff3a2fa421923392aadb4df2742064b6248John Porto using XmmRegister = ::Ice::RegX8632::XmmRegister; 465d0acff3a2fa421923392aadb4df2742064b6248John Porto using ByteRegister = ::Ice::RegX8632::ByteRegister; 475d0acff3a2fa421923392aadb4df2742064b6248John Porto using X87STRegister = ::Ice::RegX8632::X87STRegister; 485d0acff3a2fa421923392aadb4df2742064b6248John Porto 495d0acff3a2fa421923392aadb4df2742064b6248John Porto using Cond = ::Ice::CondX86; 505d0acff3a2fa421923392aadb4df2742064b6248John Porto 515d0acff3a2fa421923392aadb4df2742064b6248John Porto using RegisterSet = ::Ice::RegX8632; 525d0acff3a2fa421923392aadb4df2742064b6248John Porto static const GPRRegister Encoded_Reg_Accumulator = RegX8632::Encoded_Reg_eax; 535d0acff3a2fa421923392aadb4df2742064b6248John Porto static const GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx; 545d0acff3a2fa421923392aadb4df2742064b6248John Porto static const FixupKind PcRelFixup = llvm::ELF::R_386_PC32; 555d0acff3a2fa421923392aadb4df2742064b6248John Porto 565d0acff3a2fa421923392aadb4df2742064b6248John Porto class Operand { 575d0acff3a2fa421923392aadb4df2742064b6248John Porto public: 585d0acff3a2fa421923392aadb4df2742064b6248John Porto Operand(const Operand &other) 595d0acff3a2fa421923392aadb4df2742064b6248John Porto : length_(other.length_), fixup_(other.fixup_) { 605d0acff3a2fa421923392aadb4df2742064b6248John Porto memmove(&encoding_[0], &other.encoding_[0], other.length_); 615d0acff3a2fa421923392aadb4df2742064b6248John Porto } 625d0acff3a2fa421923392aadb4df2742064b6248John Porto 635d0acff3a2fa421923392aadb4df2742064b6248John Porto Operand &operator=(const Operand &other) { 645d0acff3a2fa421923392aadb4df2742064b6248John Porto length_ = other.length_; 655d0acff3a2fa421923392aadb4df2742064b6248John Porto fixup_ = other.fixup_; 665d0acff3a2fa421923392aadb4df2742064b6248John Porto memmove(&encoding_[0], &other.encoding_[0], other.length_); 675d0acff3a2fa421923392aadb4df2742064b6248John Porto return *this; 685d0acff3a2fa421923392aadb4df2742064b6248John Porto } 695d0acff3a2fa421923392aadb4df2742064b6248John Porto 705d0acff3a2fa421923392aadb4df2742064b6248John Porto uint8_t mod() const { return (encoding_at(0) >> 6) & 3; } 715d0acff3a2fa421923392aadb4df2742064b6248John Porto 725d0acff3a2fa421923392aadb4df2742064b6248John Porto GPRRegister rm() const { 735d0acff3a2fa421923392aadb4df2742064b6248John Porto return static_cast<GPRRegister>(encoding_at(0) & 7); 745d0acff3a2fa421923392aadb4df2742064b6248John Porto } 755d0acff3a2fa421923392aadb4df2742064b6248John Porto 765d0acff3a2fa421923392aadb4df2742064b6248John Porto ScaleFactor scale() const { 775d0acff3a2fa421923392aadb4df2742064b6248John Porto return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); 785d0acff3a2fa421923392aadb4df2742064b6248John Porto } 795d0acff3a2fa421923392aadb4df2742064b6248John Porto 805d0acff3a2fa421923392aadb4df2742064b6248John Porto GPRRegister index() const { 815d0acff3a2fa421923392aadb4df2742064b6248John Porto return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7); 825d0acff3a2fa421923392aadb4df2742064b6248John Porto } 835d0acff3a2fa421923392aadb4df2742064b6248John Porto 845d0acff3a2fa421923392aadb4df2742064b6248John Porto GPRRegister base() const { 855d0acff3a2fa421923392aadb4df2742064b6248John Porto return static_cast<GPRRegister>(encoding_at(1) & 7); 865d0acff3a2fa421923392aadb4df2742064b6248John Porto } 875d0acff3a2fa421923392aadb4df2742064b6248John Porto 885d0acff3a2fa421923392aadb4df2742064b6248John Porto int8_t disp8() const { 895d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(length_ >= 2); 905d0acff3a2fa421923392aadb4df2742064b6248John Porto return static_cast<int8_t>(encoding_[length_ - 1]); 915d0acff3a2fa421923392aadb4df2742064b6248John Porto } 925d0acff3a2fa421923392aadb4df2742064b6248John Porto 935d0acff3a2fa421923392aadb4df2742064b6248John Porto int32_t disp32() const { 945d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(length_ >= 5); 955d0acff3a2fa421923392aadb4df2742064b6248John Porto return bit_copy<int32_t>(encoding_[length_ - 4]); 965d0acff3a2fa421923392aadb4df2742064b6248John Porto } 975d0acff3a2fa421923392aadb4df2742064b6248John Porto 985d0acff3a2fa421923392aadb4df2742064b6248John Porto AssemblerFixup *fixup() const { return fixup_; } 995d0acff3a2fa421923392aadb4df2742064b6248John Porto 1005d0acff3a2fa421923392aadb4df2742064b6248John Porto protected: 1015d0acff3a2fa421923392aadb4df2742064b6248John Porto Operand() : length_(0), fixup_(nullptr) {} // Needed by subclass Address. 1025d0acff3a2fa421923392aadb4df2742064b6248John Porto 1035d0acff3a2fa421923392aadb4df2742064b6248John Porto void SetModRM(int mod, GPRRegister rm) { 1045d0acff3a2fa421923392aadb4df2742064b6248John Porto assert((mod & ~3) == 0); 1055d0acff3a2fa421923392aadb4df2742064b6248John Porto encoding_[0] = (mod << 6) | rm; 1065d0acff3a2fa421923392aadb4df2742064b6248John Porto length_ = 1; 1075d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1085d0acff3a2fa421923392aadb4df2742064b6248John Porto 1095d0acff3a2fa421923392aadb4df2742064b6248John Porto void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { 1105d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(length_ == 1); 1115d0acff3a2fa421923392aadb4df2742064b6248John Porto assert((scale & ~3) == 0); 1125d0acff3a2fa421923392aadb4df2742064b6248John Porto encoding_[1] = (scale << 6) | (index << 3) | base; 1135d0acff3a2fa421923392aadb4df2742064b6248John Porto length_ = 2; 1145d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1155d0acff3a2fa421923392aadb4df2742064b6248John Porto 1165d0acff3a2fa421923392aadb4df2742064b6248John Porto void SetDisp8(int8_t disp) { 1175d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(length_ == 1 || length_ == 2); 1185d0acff3a2fa421923392aadb4df2742064b6248John Porto encoding_[length_++] = static_cast<uint8_t>(disp); 1195d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1205d0acff3a2fa421923392aadb4df2742064b6248John Porto 1215d0acff3a2fa421923392aadb4df2742064b6248John Porto void SetDisp32(int32_t disp) { 1225d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(length_ == 1 || length_ == 2); 1235d0acff3a2fa421923392aadb4df2742064b6248John Porto intptr_t disp_size = sizeof(disp); 1245d0acff3a2fa421923392aadb4df2742064b6248John Porto memmove(&encoding_[length_], &disp, disp_size); 1255d0acff3a2fa421923392aadb4df2742064b6248John Porto length_ += disp_size; 1265d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1275d0acff3a2fa421923392aadb4df2742064b6248John Porto 1285d0acff3a2fa421923392aadb4df2742064b6248John Porto void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; } 1295d0acff3a2fa421923392aadb4df2742064b6248John Porto 1305d0acff3a2fa421923392aadb4df2742064b6248John Porto private: 1315d0acff3a2fa421923392aadb4df2742064b6248John Porto uint8_t length_; 1325d0acff3a2fa421923392aadb4df2742064b6248John Porto uint8_t encoding_[6]; 1335d0acff3a2fa421923392aadb4df2742064b6248John Porto AssemblerFixup *fixup_; 1345d0acff3a2fa421923392aadb4df2742064b6248John Porto 1355d0acff3a2fa421923392aadb4df2742064b6248John Porto explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); } 1365d0acff3a2fa421923392aadb4df2742064b6248John Porto 1375d0acff3a2fa421923392aadb4df2742064b6248John Porto // Get the operand encoding byte at the given index. 1385d0acff3a2fa421923392aadb4df2742064b6248John Porto uint8_t encoding_at(intptr_t index) const { 1395d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(index >= 0 && index < length_); 1405d0acff3a2fa421923392aadb4df2742064b6248John Porto return encoding_[index]; 1415d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1425d0acff3a2fa421923392aadb4df2742064b6248John Porto 1435d0acff3a2fa421923392aadb4df2742064b6248John Porto // Returns whether or not this operand is really the given register in 1445d0acff3a2fa421923392aadb4df2742064b6248John Porto // disguise. Used from the assembler to generate better encodings. 1455d0acff3a2fa421923392aadb4df2742064b6248John Porto bool IsRegister(GPRRegister reg) const { 1465d0acff3a2fa421923392aadb4df2742064b6248John Porto return ((encoding_[0] & 0xF8) == 1475d0acff3a2fa421923392aadb4df2742064b6248John Porto 0xC0) // Addressing mode is register only. 1485d0acff3a2fa421923392aadb4df2742064b6248John Porto && 1495d0acff3a2fa421923392aadb4df2742064b6248John Porto ((encoding_[0] & 0x07) == reg); // Register codes match. 1505d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1515d0acff3a2fa421923392aadb4df2742064b6248John Porto 1525d0acff3a2fa421923392aadb4df2742064b6248John Porto template <class> friend class AssemblerX86Base; 1535d0acff3a2fa421923392aadb4df2742064b6248John Porto }; 1545d0acff3a2fa421923392aadb4df2742064b6248John Porto 1555d0acff3a2fa421923392aadb4df2742064b6248John Porto class Address : public Operand { 1565d0acff3a2fa421923392aadb4df2742064b6248John Porto Address() = delete; 1575d0acff3a2fa421923392aadb4df2742064b6248John Porto 1585d0acff3a2fa421923392aadb4df2742064b6248John Porto public: 1595d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(const Address &other) : Operand(other) {} 1605d0acff3a2fa421923392aadb4df2742064b6248John Porto 1615d0acff3a2fa421923392aadb4df2742064b6248John Porto Address &operator=(const Address &other) { 1625d0acff3a2fa421923392aadb4df2742064b6248John Porto Operand::operator=(other); 1635d0acff3a2fa421923392aadb4df2742064b6248John Porto return *this; 1645d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1655d0acff3a2fa421923392aadb4df2742064b6248John Porto 1665d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(GPRRegister base, int32_t disp) { 1675d0acff3a2fa421923392aadb4df2742064b6248John Porto if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) { 1685d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(0, base); 1695d0acff3a2fa421923392aadb4df2742064b6248John Porto if (base == RegX8632::Encoded_Reg_esp) 1705d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); 1715d0acff3a2fa421923392aadb4df2742064b6248John Porto } else if (Utils::IsInt(8, disp)) { 1725d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(1, base); 1735d0acff3a2fa421923392aadb4df2742064b6248John Porto if (base == RegX8632::Encoded_Reg_esp) 1745d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); 1755d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp8(disp); 1765d0acff3a2fa421923392aadb4df2742064b6248John Porto } else { 1775d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(2, base); 1785d0acff3a2fa421923392aadb4df2742064b6248John Porto if (base == RegX8632::Encoded_Reg_esp) 1795d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); 1805d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp32(disp); 1815d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1825d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1835d0acff3a2fa421923392aadb4df2742064b6248John Porto 1845d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(GPRRegister index, ScaleFactor scale, int32_t disp) { 1855d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode. 1865d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(0, RegX8632::Encoded_Reg_esp); 1875d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(scale, index, RegX8632::Encoded_Reg_ebp); 1885d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp32(disp); 1895d0acff3a2fa421923392aadb4df2742064b6248John Porto } 1905d0acff3a2fa421923392aadb4df2742064b6248John Porto 1915d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(GPRRegister base, GPRRegister index, ScaleFactor scale, 1925d0acff3a2fa421923392aadb4df2742064b6248John Porto int32_t disp) { 1935d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode. 1945d0acff3a2fa421923392aadb4df2742064b6248John Porto if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) { 1955d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(0, RegX8632::Encoded_Reg_esp); 1965d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(scale, index, base); 1975d0acff3a2fa421923392aadb4df2742064b6248John Porto } else if (Utils::IsInt(8, disp)) { 1985d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(1, RegX8632::Encoded_Reg_esp); 1995d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(scale, index, base); 2005d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp8(disp); 2015d0acff3a2fa421923392aadb4df2742064b6248John Porto } else { 2025d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(2, RegX8632::Encoded_Reg_esp); 2035d0acff3a2fa421923392aadb4df2742064b6248John Porto SetSIB(scale, index, base); 2045d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp32(disp); 2055d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2065d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2075d0acff3a2fa421923392aadb4df2742064b6248John Porto 2085d0acff3a2fa421923392aadb4df2742064b6248John Porto // AbsoluteTag is a special tag used by clients to create an absolute 2095d0acff3a2fa421923392aadb4df2742064b6248John Porto // Address. 2105d0acff3a2fa421923392aadb4df2742064b6248John Porto enum AbsoluteTag { ABSOLUTE }; 2115d0acff3a2fa421923392aadb4df2742064b6248John Porto 2125d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(AbsoluteTag, const uintptr_t Addr) { 2135d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(0, RegX8632::Encoded_Reg_ebp); 2145d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp32(Addr); 2155d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2165d0acff3a2fa421923392aadb4df2742064b6248John Porto 2175d0acff3a2fa421923392aadb4df2742064b6248John Porto // TODO(jpp): remove this. 2185d0acff3a2fa421923392aadb4df2742064b6248John Porto static Address Absolute(const uintptr_t Addr) { 2195d0acff3a2fa421923392aadb4df2742064b6248John Porto return Address(ABSOLUTE, Addr); 2205d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2215d0acff3a2fa421923392aadb4df2742064b6248John Porto 2225d0acff3a2fa421923392aadb4df2742064b6248John Porto Address(AbsoluteTag, RelocOffsetT Offset, AssemblerFixup *Fixup) { 2235d0acff3a2fa421923392aadb4df2742064b6248John Porto SetModRM(0, RegX8632::Encoded_Reg_ebp); 2245d0acff3a2fa421923392aadb4df2742064b6248John Porto // Use the Offset in the displacement for now. If we decide to process 2255d0acff3a2fa421923392aadb4df2742064b6248John Porto // fixups later, we'll need to patch up the emitted displacement. 2265d0acff3a2fa421923392aadb4df2742064b6248John Porto SetDisp32(Offset); 2275d0acff3a2fa421923392aadb4df2742064b6248John Porto SetFixup(Fixup); 2285d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2295d0acff3a2fa421923392aadb4df2742064b6248John Porto 2305d0acff3a2fa421923392aadb4df2742064b6248John Porto // TODO(jpp): remove this. 2315d0acff3a2fa421923392aadb4df2742064b6248John Porto static Address Absolute(RelocOffsetT Offset, AssemblerFixup *Fixup) { 2325d0acff3a2fa421923392aadb4df2742064b6248John Porto return Address(ABSOLUTE, Offset, Fixup); 2335d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2345d0acff3a2fa421923392aadb4df2742064b6248John Porto 2355d0acff3a2fa421923392aadb4df2742064b6248John Porto static Address ofConstPool(Assembler *Asm, const Constant *Imm) { 2365d0acff3a2fa421923392aadb4df2742064b6248John Porto AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm); 2375d0acff3a2fa421923392aadb4df2742064b6248John Porto const RelocOffsetT Offset = 0; 2385d0acff3a2fa421923392aadb4df2742064b6248John Porto return Address(ABSOLUTE, Offset, Fixup); 2395d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2405d0acff3a2fa421923392aadb4df2742064b6248John Porto }; 2415d0acff3a2fa421923392aadb4df2742064b6248John Porto 2425d0acff3a2fa421923392aadb4df2742064b6248John Porto //---------------------------------------------------------------------------- 2435d0acff3a2fa421923392aadb4df2742064b6248John Porto // __ ______ __ __ ______ ______ __ __ __ ______ 2445d0acff3a2fa421923392aadb4df2742064b6248John Porto // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ 2455d0acff3a2fa421923392aadb4df2742064b6248John Porto // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ 2465d0acff3a2fa421923392aadb4df2742064b6248John Porto // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ 2475d0acff3a2fa421923392aadb4df2742064b6248John Porto // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ 2485d0acff3a2fa421923392aadb4df2742064b6248John Porto // 2495d0acff3a2fa421923392aadb4df2742064b6248John Porto //---------------------------------------------------------------------------- 2505d0acff3a2fa421923392aadb4df2742064b6248John Porto enum InstructionSet { 2515d0acff3a2fa421923392aadb4df2742064b6248John Porto Begin, 2525d0acff3a2fa421923392aadb4df2742064b6248John Porto // SSE2 is the PNaCl baseline instruction set. 2535d0acff3a2fa421923392aadb4df2742064b6248John Porto SSE2 = Begin, 2545d0acff3a2fa421923392aadb4df2742064b6248John Porto SSE4_1, 2555d0acff3a2fa421923392aadb4df2742064b6248John Porto End 2565d0acff3a2fa421923392aadb4df2742064b6248John Porto }; 2575d0acff3a2fa421923392aadb4df2742064b6248John Porto 2585d0acff3a2fa421923392aadb4df2742064b6248John Porto // The maximum number of arguments to pass in XMM registers 2595d0acff3a2fa421923392aadb4df2742064b6248John Porto static const uint32_t X86_MAX_XMM_ARGS = 4; 2605d0acff3a2fa421923392aadb4df2742064b6248John Porto // The number of bits in a byte 2615d0acff3a2fa421923392aadb4df2742064b6248John Porto static const uint32_t X86_CHAR_BIT = 8; 2625d0acff3a2fa421923392aadb4df2742064b6248John Porto // Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it 2635d0acff3a2fa421923392aadb4df2742064b6248John Porto // is used as an argument to std::max(), and the default std::less<T> has an 2645d0acff3a2fa421923392aadb4df2742064b6248John Porto // operator(T const&, T const&) which requires this member to have an address. 2655d0acff3a2fa421923392aadb4df2742064b6248John Porto static const uint32_t X86_STACK_ALIGNMENT_BYTES; 2665d0acff3a2fa421923392aadb4df2742064b6248John Porto // Size of the return address on the stack 2675d0acff3a2fa421923392aadb4df2742064b6248John Porto static const uint32_t X86_RET_IP_SIZE_BYTES = 4; 2685d0acff3a2fa421923392aadb4df2742064b6248John Porto // The number of different NOP instructions 2695d0acff3a2fa421923392aadb4df2742064b6248John Porto static const uint32_t X86_NUM_NOP_VARIANTS = 5; 2705d0acff3a2fa421923392aadb4df2742064b6248John Porto 2715d0acff3a2fa421923392aadb4df2742064b6248John Porto // Value is in bytes. Return Value adjusted to the next highest multiple 2725d0acff3a2fa421923392aadb4df2742064b6248John Porto // of the stack alignment. 2735d0acff3a2fa421923392aadb4df2742064b6248John Porto static uint32_t applyStackAlignment(uint32_t Value) { 2745d0acff3a2fa421923392aadb4df2742064b6248John Porto return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); 2755d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2765d0acff3a2fa421923392aadb4df2742064b6248John Porto 2775d0acff3a2fa421923392aadb4df2742064b6248John Porto // Return the type which the elements of the vector have in the X86 2785d0acff3a2fa421923392aadb4df2742064b6248John Porto // representation of the vector. 2795d0acff3a2fa421923392aadb4df2742064b6248John Porto static Type getInVectorElementType(Type Ty) { 2805d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(isVectorType(Ty)); 2815d0acff3a2fa421923392aadb4df2742064b6248John Porto size_t Index = static_cast<size_t>(Ty); 2825d0acff3a2fa421923392aadb4df2742064b6248John Porto (void)Index; 2835d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(Index < TableTypeX8632AttributesSize); 2845d0acff3a2fa421923392aadb4df2742064b6248John Porto return TableTypeX8632Attributes[Ty].InVectorElementType; 2855d0acff3a2fa421923392aadb4df2742064b6248John Porto } 2865d0acff3a2fa421923392aadb4df2742064b6248John Porto 2875d0acff3a2fa421923392aadb4df2742064b6248John Porto // Note: The following data structures are defined in 2885d0acff3a2fa421923392aadb4df2742064b6248John Porto // IceTargetLoweringX8632.cpp. 2895d0acff3a2fa421923392aadb4df2742064b6248John Porto 2905d0acff3a2fa421923392aadb4df2742064b6248John Porto // The following table summarizes the logic for lowering the fcmp 2915d0acff3a2fa421923392aadb4df2742064b6248John Porto // instruction. There is one table entry for each of the 16 conditions. 2925d0acff3a2fa421923392aadb4df2742064b6248John Porto // 2935d0acff3a2fa421923392aadb4df2742064b6248John Porto // The first four columns describe the case when the operands are 2945d0acff3a2fa421923392aadb4df2742064b6248John Porto // floating point scalar values. A comment in lowerFcmp() describes the 2955d0acff3a2fa421923392aadb4df2742064b6248John Porto // lowering template. In the most general case, there is a compare 2965d0acff3a2fa421923392aadb4df2742064b6248John Porto // followed by two conditional branches, because some fcmp conditions 2975d0acff3a2fa421923392aadb4df2742064b6248John Porto // don't map to a single x86 conditional branch. However, in many cases 2985d0acff3a2fa421923392aadb4df2742064b6248John Porto // it is possible to swap the operands in the comparison and have a 2995d0acff3a2fa421923392aadb4df2742064b6248John Porto // single conditional branch. Since it's quite tedious to validate the 3005d0acff3a2fa421923392aadb4df2742064b6248John Porto // table by hand, good execution tests are helpful. 3015d0acff3a2fa421923392aadb4df2742064b6248John Porto // 3025d0acff3a2fa421923392aadb4df2742064b6248John Porto // The last two columns describe the case when the operands are vectors 3035d0acff3a2fa421923392aadb4df2742064b6248John Porto // of floating point values. For most fcmp conditions, there is a clear 3045d0acff3a2fa421923392aadb4df2742064b6248John Porto // mapping to a single x86 cmpps instruction variant. Some fcmp 3055d0acff3a2fa421923392aadb4df2742064b6248John Porto // conditions require special code to handle and these are marked in the 3065d0acff3a2fa421923392aadb4df2742064b6248John Porto // table with a Cmpps_Invalid predicate. 3075d0acff3a2fa421923392aadb4df2742064b6248John Porto static const struct TableFcmpType { 3085d0acff3a2fa421923392aadb4df2742064b6248John Porto uint32_t Default; 3095d0acff3a2fa421923392aadb4df2742064b6248John Porto bool SwapScalarOperands; 3105d0acff3a2fa421923392aadb4df2742064b6248John Porto CondX86::BrCond C1, C2; 3115d0acff3a2fa421923392aadb4df2742064b6248John Porto bool SwapVectorOperands; 3125d0acff3a2fa421923392aadb4df2742064b6248John Porto CondX86::CmppsCond Predicate; 3135d0acff3a2fa421923392aadb4df2742064b6248John Porto } TableFcmp[]; 3145d0acff3a2fa421923392aadb4df2742064b6248John Porto static const size_t TableFcmpSize; 3155d0acff3a2fa421923392aadb4df2742064b6248John Porto 3165d0acff3a2fa421923392aadb4df2742064b6248John Porto // The following table summarizes the logic for lowering the icmp instruction 3175d0acff3a2fa421923392aadb4df2742064b6248John Porto // for i32 and narrower types. Each icmp condition has a clear mapping to an 3185d0acff3a2fa421923392aadb4df2742064b6248John Porto // x86 conditional branch instruction. 3195d0acff3a2fa421923392aadb4df2742064b6248John Porto 3205d0acff3a2fa421923392aadb4df2742064b6248John Porto static const struct TableIcmp32Type { 3215d0acff3a2fa421923392aadb4df2742064b6248John Porto CondX86::BrCond Mapping; 3225d0acff3a2fa421923392aadb4df2742064b6248John Porto } TableIcmp32[]; 3235d0acff3a2fa421923392aadb4df2742064b6248John Porto static const size_t TableIcmp32Size; 3245d0acff3a2fa421923392aadb4df2742064b6248John Porto 3255d0acff3a2fa421923392aadb4df2742064b6248John Porto // The following table summarizes the logic for lowering the icmp instruction 3265d0acff3a2fa421923392aadb4df2742064b6248John Porto // for the i64 type. For Eq and Ne, two separate 32-bit comparisons and 3275d0acff3a2fa421923392aadb4df2742064b6248John Porto // conditional branches are needed. For the other conditions, three separate 3285d0acff3a2fa421923392aadb4df2742064b6248John Porto // conditional branches are needed. 3295d0acff3a2fa421923392aadb4df2742064b6248John Porto static const struct TableIcmp64Type { 3305d0acff3a2fa421923392aadb4df2742064b6248John Porto CondX86::BrCond C1, C2, C3; 3315d0acff3a2fa421923392aadb4df2742064b6248John Porto } TableIcmp64[]; 3325d0acff3a2fa421923392aadb4df2742064b6248John Porto static const size_t TableIcmp64Size; 3335d0acff3a2fa421923392aadb4df2742064b6248John Porto 3345d0acff3a2fa421923392aadb4df2742064b6248John Porto static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { 3355d0acff3a2fa421923392aadb4df2742064b6248John Porto size_t Index = static_cast<size_t>(Cond); 3365d0acff3a2fa421923392aadb4df2742064b6248John Porto assert(Index < TableIcmp32Size); 3375d0acff3a2fa421923392aadb4df2742064b6248John Porto return TableIcmp32[Index].Mapping; 3385d0acff3a2fa421923392aadb4df2742064b6248John Porto } 3395d0acff3a2fa421923392aadb4df2742064b6248John Porto 3405d0acff3a2fa421923392aadb4df2742064b6248John Porto static const struct TableTypeX8632AttributesType { 3415d0acff3a2fa421923392aadb4df2742064b6248John Porto Type InVectorElementType; 3425d0acff3a2fa421923392aadb4df2742064b6248John Porto } TableTypeX8632Attributes[]; 3435d0acff3a2fa421923392aadb4df2742064b6248John Porto static const size_t TableTypeX8632AttributesSize; 3445d0acff3a2fa421923392aadb4df2742064b6248John Porto}; 3455d0acff3a2fa421923392aadb4df2742064b6248John Porto 3465d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace X86Internal 3475d0acff3a2fa421923392aadb4df2742064b6248John Porto 3485d0acff3a2fa421923392aadb4df2742064b6248John Portonamespace X8632 { 3495d0acff3a2fa421923392aadb4df2742064b6248John Portousing Traits = ::Ice::X86Internal::MachineTraits<TargetX8632>; 3505d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace X8632 3515d0acff3a2fa421923392aadb4df2742064b6248John Porto 3525d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace Ice 3535d0acff3a2fa421923392aadb4df2742064b6248John Porto 3545d0acff3a2fa421923392aadb4df2742064b6248John Porto#endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H 355