diff options
Diffstat (limited to 'lib/Target/Hexagon')
70 files changed, 8535 insertions, 3890 deletions
diff --git a/lib/Target/Hexagon/CMakeLists.txt b/lib/Target/Hexagon/CMakeLists.txt index 81b0e5680547..af7914f30366 100644 --- a/lib/Target/Hexagon/CMakeLists.txt +++ b/lib/Target/Hexagon/CMakeLists.txt @@ -1,28 +1,32 @@ set(LLVM_TARGET_DEFINITIONS Hexagon.td) -tablegen(LLVM HexagonGenRegisterInfo.inc -gen-register-info) -tablegen(LLVM HexagonGenInstrInfo.inc -gen-instr-info) tablegen(LLVM HexagonGenAsmWriter.inc -gen-asm-writer) -tablegen(LLVM HexagonGenDAGISel.inc -gen-dag-isel) tablegen(LLVM HexagonGenCallingConv.inc -gen-callingconv) -tablegen(LLVM HexagonGenSubtargetInfo.inc -gen-subtarget) +tablegen(LLVM HexagonGenDAGISel.inc -gen-dag-isel) tablegen(LLVM HexagonGenDFAPacketizer.inc -gen-dfa-packetizer) +tablegen(LLVM HexagonGenDisassemblerTables.inc -gen-disassembler) +tablegen(LLVM HexagonGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM HexagonGenMCCodeEmitter.inc -gen-emitter) +tablegen(LLVM HexagonGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM HexagonGenSubtargetInfo.inc -gen-subtarget) add_public_tablegen_target(HexagonCommonTableGen) add_llvm_target(HexagonCodeGen HexagonAsmPrinter.cpp HexagonCallingConvLower.cpp HexagonCFGOptimizer.cpp + HexagonCopyToCombine.cpp HexagonExpandPredSpillCode.cpp + HexagonFixupHwLoops.cpp HexagonFrameLowering.cpp HexagonHardwareLoops.cpp - HexagonFixupHwLoops.cpp - HexagonMachineFunctionInfo.cpp - HexagonMachineScheduler.cpp - HexagonMCInstLower.cpp HexagonInstrInfo.cpp HexagonISelDAGToDAG.cpp HexagonISelLowering.cpp + HexagonMachineFunctionInfo.cpp + HexagonMachineScheduler.cpp + HexagonMCInstLower.cpp + HexagonNewValueJump.cpp HexagonPeephole.cpp HexagonRegisterInfo.cpp HexagonRemoveSZExtArgs.cpp @@ -33,11 +37,8 @@ add_llvm_target(HexagonCodeGen HexagonTargetMachine.cpp HexagonTargetObjectFile.cpp HexagonVLIWPacketizer.cpp - HexagonNewValueJump.cpp - HexagonCopyToCombine.cpp ) add_subdirectory(TargetInfo) -add_subdirectory(InstPrinter) add_subdirectory(MCTargetDesc) - +add_subdirectory(Disassembler) diff --git a/lib/Target/Hexagon/Disassembler/CMakeLists.txt b/lib/Target/Hexagon/Disassembler/CMakeLists.txt new file mode 100644 index 000000000000..755a45e2df8b --- /dev/null +++ b/lib/Target/Hexagon/Disassembler/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMHexagonDisassembler + HexagonDisassembler.cpp + ) diff --git a/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp b/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp new file mode 100644 index 000000000000..44f9d93e8fc7 --- /dev/null +++ b/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp @@ -0,0 +1,181 @@ +//===-- HexagonDisassembler.cpp - Disassembler for Hexagon ISA ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/HexagonBaseInfo.h" +#include "MCTargetDesc/HexagonMCInst.h" +#include "MCTargetDesc/HexagonMCTargetDesc.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixedLenDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include <array> +#include <vector> + +using namespace llvm; + +#define DEBUG_TYPE "hexagon-disassembler" + +// Pull DecodeStatus and its enum values into the global namespace. +typedef llvm::MCDisassembler::DecodeStatus DecodeStatus; + +namespace { +/// \brief Hexagon disassembler for all Hexagon platforms. +class HexagonDisassembler : public MCDisassembler { +public: + HexagonDisassembler(MCSubtargetInfo const &STI, MCContext &Ctx) + : MCDisassembler(STI, Ctx) {} + + DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const override; +}; +} + +static DecodeStatus DecodeModRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); +static DecodeStatus DecodeCtrRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); + +static const uint16_t IntRegDecoderTable[] = { + Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4, + Hexagon::R5, Hexagon::R6, Hexagon::R7, Hexagon::R8, Hexagon::R9, + Hexagon::R10, Hexagon::R11, Hexagon::R12, Hexagon::R13, Hexagon::R14, + Hexagon::R15, Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19, + Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23, Hexagon::R24, + Hexagon::R25, Hexagon::R26, Hexagon::R27, Hexagon::R28, Hexagon::R29, + Hexagon::R30, Hexagon::R31 }; + +static const uint16_t PredRegDecoderTable[] = { Hexagon::P0, Hexagon::P1, +Hexagon::P2, Hexagon::P3 }; + +static DecodeStatus DecodeRegisterClass(MCInst &Inst, unsigned RegNo, + const uint16_t Table[], size_t Size) { + if (RegNo < Size) { + Inst.addOperand(MCOperand::CreateReg(Table[RegNo])); + return MCDisassembler::Success; + } + else + return MCDisassembler::Fail; +} + +static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t /*Address*/, + void const *Decoder) { + if (RegNo > 31) + return MCDisassembler::Fail; + + unsigned Register = IntRegDecoderTable[RegNo]; + Inst.addOperand(MCOperand::CreateReg(Register)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeCtrRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t /*Address*/, const void *Decoder) { + static const uint16_t CtrlRegDecoderTable[] = { + Hexagon::SA0, Hexagon::LC0, Hexagon::SA1, Hexagon::LC1, + Hexagon::P3_0, Hexagon::NoRegister, Hexagon::C6, Hexagon::C7, + Hexagon::USR, Hexagon::PC, Hexagon::UGP, Hexagon::GP, + Hexagon::CS0, Hexagon::CS1, Hexagon::UPCL, Hexagon::UPCH + }; + + if (RegNo >= sizeof(CtrlRegDecoderTable) / sizeof(CtrlRegDecoderTable[0])) + return MCDisassembler::Fail; + + if (CtrlRegDecoderTable[RegNo] == Hexagon::NoRegister) + return MCDisassembler::Fail; + + unsigned Register = CtrlRegDecoderTable[RegNo]; + Inst.addOperand(MCOperand::CreateReg(Register)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeModRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t /*Address*/, const void *Decoder) { + unsigned Register = 0; + switch (RegNo) { + case 0: + Register = Hexagon::M0; + break; + case 1: + Register = Hexagon::M1; + break; + default: + return MCDisassembler::Fail; + } + Inst.addOperand(MCOperand::CreateReg(Register)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeDoubleRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t /*Address*/, const void *Decoder) { + static const uint16_t DoubleRegDecoderTable[] = { + Hexagon::D0, Hexagon::D1, Hexagon::D2, Hexagon::D3, + Hexagon::D4, Hexagon::D5, Hexagon::D6, Hexagon::D7, + Hexagon::D8, Hexagon::D9, Hexagon::D10, Hexagon::D11, + Hexagon::D12, Hexagon::D13, Hexagon::D14, Hexagon::D15 + }; + + return (DecodeRegisterClass(Inst, RegNo >> 1, + DoubleRegDecoderTable, + sizeof (DoubleRegDecoderTable))); +} + +static DecodeStatus DecodePredRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t /*Address*/, + void const *Decoder) { + if (RegNo > 3) + return MCDisassembler::Fail; + + unsigned Register = PredRegDecoderTable[RegNo]; + Inst.addOperand(MCOperand::CreateReg(Register)); + return MCDisassembler::Success; +} + +#include "HexagonGenDisassemblerTables.inc" + +static MCDisassembler *createHexagonDisassembler(Target const &T, + MCSubtargetInfo const &STI, + MCContext &Ctx) { + return new HexagonDisassembler(STI, Ctx); +} + +extern "C" void LLVMInitializeHexagonDisassembler() { + TargetRegistry::RegisterMCDisassembler(TheHexagonTarget, + createHexagonDisassembler); +} + +DecodeStatus HexagonDisassembler::getInstruction(MCInst &MI, uint64_t &Size, + ArrayRef<uint8_t> Bytes, + uint64_t Address, + raw_ostream &os, + raw_ostream &cs) const { + Size = 4; + if (Bytes.size() < 4) + return MCDisassembler::Fail; + + uint32_t insn = + llvm::support::endian::read<uint32_t, llvm::support::little, + llvm::support::unaligned>(Bytes.data()); + + // Remove parse bits. + insn &= ~static_cast<uint32_t>(HexagonII::InstParseBits::INST_PARSE_MASK); + DecodeStatus Result = decodeInstruction(DecoderTable32, MI, insn, Address, this, STI); + HexagonMCInst::AppendImplicitOperands(MI); + return Result; +} diff --git a/lib/Target/Hexagon/InstPrinter/LLVMBuild.txt b/lib/Target/Hexagon/Disassembler/LLVMBuild.txt index 59849aa7e1c7..43bace75a852 100644 --- a/lib/Target/Hexagon/InstPrinter/LLVMBuild.txt +++ b/lib/Target/Hexagon/Disassembler/LLVMBuild.txt @@ -1,4 +1,4 @@ -;===- ./lib/Target/Hexagon/InstPrinter/LLVMBuild.txt -----------*- Conf -*--===; +;===-- ./lib/Target/Hexagon/Disassembler/LLVMBuild.txt ---------*- Conf -*--===; ; ; The LLVM Compiler Infrastructure ; @@ -17,7 +17,7 @@ [component_0] type = Library -name = HexagonAsmPrinter +name = HexagonDisassembler parent = Hexagon -required_libraries = HexagonDesc MC Support +required_libraries = HexagonDesc HexagonInfo MCDisassembler Support add_to_library_groups = Hexagon diff --git a/lib/Target/Hexagon/InstPrinter/Makefile b/lib/Target/Hexagon/Disassembler/Makefile index 20331d8807ec..16c305fe4074 100644 --- a/lib/Target/Hexagon/InstPrinter/Makefile +++ b/lib/Target/Hexagon/Disassembler/Makefile @@ -1,4 +1,4 @@ -##===- lib/Target/Hexagon/InstPrinter/Makefile ----------------------------===## +##===-- lib/Target/Hexagon/Disassembler/Makefile -----------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -6,10 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../../.. -LIBRARYNAME = LLVMHexagonAsmPrinter +LIBRARYNAME = LLVMHexagonDisassembler -# Hack: we need to include 'main' Hexagon target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. include $(LEVEL)/Makefile.common diff --git a/lib/Target/Hexagon/Hexagon.h b/lib/Target/Hexagon/Hexagon.h index 5467ee361257..64ae69c60e5d 100644 --- a/lib/Target/Hexagon/Hexagon.h +++ b/lib/Target/Hexagon/Hexagon.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TARGET_Hexagon_H -#define TARGET_Hexagon_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGON_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGON_H #include "MCTargetDesc/HexagonMCTargetDesc.h" #include "llvm/Target/TargetLowering.h" diff --git a/lib/Target/Hexagon/Hexagon.td b/lib/Target/Hexagon/Hexagon.td index 5f4a6c64f703..2068c6da4e48 100644 --- a/lib/Target/Hexagon/Hexagon.td +++ b/lib/Target/Hexagon/Hexagon.td @@ -50,6 +50,8 @@ def IEEERndNearV5T : Predicate<"Subtarget.modeIEEERndNear()">; //===----------------------------------------------------------------------===// // Classes used for relation maps. //===----------------------------------------------------------------------===// + +class ImmRegShl; // PredRel - Filter class used to relate non-predicated instructions with their // predicated forms. class PredRel; @@ -137,7 +139,7 @@ def getPredOldOpcode : InstrMapping { // def getNewValueOpcode : InstrMapping { let FilterClass = "NewValueRel"; - let RowFields = ["BaseOpcode", "PredSense", "PNewValue"]; + let RowFields = ["BaseOpcode", "PredSense", "PNewValue", "addrMode"]; let ColFields = ["NValueST"]; let KeyCol = ["false"]; let ValueCols = [["true"]]; @@ -149,7 +151,7 @@ def getNewValueOpcode : InstrMapping { // def getNonNVStore : InstrMapping { let FilterClass = "NewValueRel"; - let RowFields = ["BaseOpcode", "PredSense", "PNewValue"]; + let RowFields = ["BaseOpcode", "PredSense", "PNewValue", "addrMode"]; let ColFields = ["NValueST"]; let KeyCol = ["true"]; let ValueCols = [["false"]]; @@ -180,6 +182,14 @@ def getRegForm : InstrMapping { let ValueCols = [["reg"]]; } +def getRegShlForm : InstrMapping { + let FilterClass = "ImmRegShl"; + let RowFields = ["CextOpcode", "PredSense", "PNewValue", "isNVStore"]; + let ColFields = ["InputType"]; + let KeyCol = ["imm"]; + let ValueCols = [["reg"]]; +} + //===----------------------------------------------------------------------===// // Register File, Calling Conv, Instruction Descriptions //===----------------------------------------------------------------------===// diff --git a/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/lib/Target/Hexagon/HexagonAsmPrinter.cpp index 2e011bd12741..50f2eca63693 100644 --- a/lib/Target/Hexagon/HexagonAsmPrinter.cpp +++ b/lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -18,7 +18,7 @@ #include "HexagonMachineFunctionInfo.h" #include "HexagonSubtarget.h" #include "HexagonTargetMachine.h" -#include "InstPrinter/HexagonInstPrinter.h" +#include "MCTargetDesc/HexagonInstPrinter.h" #include "MCTargetDesc/HexagonMCInst.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -174,7 +174,7 @@ bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, /// void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { if (MI->isBundle()) { - std::vector<const MachineInstr*> BundleMIs; + std::vector<MachineInstr const *> BundleMIs; const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator MII = MI; @@ -183,33 +183,35 @@ void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { while (MII != MBB->end() && MII->isInsideBundle()) { const MachineInstr *MInst = MII; if (MInst->getOpcode() == TargetOpcode::DBG_VALUE || - MInst->getOpcode() == TargetOpcode::IMPLICIT_DEF) { - IgnoreCount++; - ++MII; - continue; + MInst->getOpcode() == TargetOpcode::IMPLICIT_DEF) { + IgnoreCount++; + ++MII; + continue; } - //BundleMIs.push_back(&*MII); + // BundleMIs.push_back(&*MII); BundleMIs.push_back(MInst); ++MII; } unsigned Size = BundleMIs.size(); - assert((Size+IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!"); + assert((Size + IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!"); for (unsigned Index = 0; Index < Size; Index++) { HexagonMCInst MCI; - MCI.setPacketStart(Index == 0); - MCI.setPacketEnd(Index == (Size-1)); HexagonLowerToMC(BundleMIs[Index], MCI, *this); + HexagonMCInst::AppendImplicitOperands(MCI); + MCI.setPacketBegin(Index == 0); + MCI.setPacketEnd(Index == (Size - 1)); EmitToStreamer(OutStreamer, MCI); } } else { HexagonMCInst MCI; + HexagonLowerToMC(MI, MCI, *this); + HexagonMCInst::AppendImplicitOperands(MCI); if (MI->getOpcode() == Hexagon::ENDLOOP0) { - MCI.setPacketStart(true); + MCI.setPacketBegin(true); MCI.setPacketEnd(true); } - HexagonLowerToMC(MI, MCI, *this); EmitToStreamer(OutStreamer, MCI); } diff --git a/lib/Target/Hexagon/HexagonAsmPrinter.h b/lib/Target/Hexagon/HexagonAsmPrinter.h index 7fe8c5790c6b..5f4c162b0070 100755 --- a/lib/Target/Hexagon/HexagonAsmPrinter.h +++ b/lib/Target/Hexagon/HexagonAsmPrinter.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HEXAGONASMPRINTER_H -#define HEXAGONASMPRINTER_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONASMPRINTER_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONASMPRINTER_H #include "Hexagon.h" #include "HexagonTargetMachine.h" diff --git a/lib/Target/Hexagon/HexagonCFGOptimizer.cpp b/lib/Target/Hexagon/HexagonCFGOptimizer.cpp index de340e0074db..307adad095c8 100644 --- a/lib/Target/Hexagon/HexagonCFGOptimizer.cpp +++ b/lib/Target/Hexagon/HexagonCFGOptimizer.cpp @@ -59,36 +59,36 @@ private: char HexagonCFGOptimizer::ID = 0; static bool IsConditionalBranch(int Opc) { - return (Opc == Hexagon::JMP_t) || (Opc == Hexagon::JMP_f) - || (Opc == Hexagon::JMP_tnew_t) || (Opc == Hexagon::JMP_fnew_t); + return (Opc == Hexagon::J2_jumpt) || (Opc == Hexagon::J2_jumpf) + || (Opc == Hexagon::J2_jumptnewpt) || (Opc == Hexagon::J2_jumpfnewpt); } static bool IsUnconditionalJump(int Opc) { - return (Opc == Hexagon::JMP); + return (Opc == Hexagon::J2_jump); } void HexagonCFGOptimizer::InvertAndChangeJumpTarget(MachineInstr* MI, MachineBasicBlock* NewTarget) { - const HexagonInstrInfo *QII = QTM.getInstrInfo(); + const HexagonInstrInfo *QII = QTM.getSubtargetImpl()->getInstrInfo(); int NewOpcode = 0; switch(MI->getOpcode()) { - case Hexagon::JMP_t: - NewOpcode = Hexagon::JMP_f; + case Hexagon::J2_jumpt: + NewOpcode = Hexagon::J2_jumpf; break; - case Hexagon::JMP_f: - NewOpcode = Hexagon::JMP_t; + case Hexagon::J2_jumpf: + NewOpcode = Hexagon::J2_jumpt; break; - case Hexagon::JMP_tnew_t: - NewOpcode = Hexagon::JMP_fnew_t; + case Hexagon::J2_jumptnewpt: + NewOpcode = Hexagon::J2_jumpfnewpt; break; - case Hexagon::JMP_fnew_t: - NewOpcode = Hexagon::JMP_tnew_t; + case Hexagon::J2_jumpfnewpt: + NewOpcode = Hexagon::J2_jumptnewpt; break; default: @@ -163,8 +163,8 @@ bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) { // The target of the unconditional branch must be JumpAroundTarget. // TODO: If not, we should not invert the unconditional branch. MachineBasicBlock* CondBranchTarget = nullptr; - if ((MI->getOpcode() == Hexagon::JMP_t) || - (MI->getOpcode() == Hexagon::JMP_f)) { + if ((MI->getOpcode() == Hexagon::J2_jumpt) || + (MI->getOpcode() == Hexagon::J2_jumpf)) { CondBranchTarget = MI->getOperand(1).getMBB(); } diff --git a/lib/Target/Hexagon/HexagonCallingConvLower.cpp b/lib/Target/Hexagon/HexagonCallingConvLower.cpp index f5f958c101b1..8d78409aa01d 100644 --- a/lib/Target/Hexagon/HexagonCallingConvLower.cpp +++ b/lib/Target/Hexagon/HexagonCallingConvLower.cpp @@ -21,6 +21,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; Hexagon_CCState::Hexagon_CCState(CallingConv::ID CC, bool isVarArg, @@ -31,7 +32,8 @@ Hexagon_CCState::Hexagon_CCState(CallingConv::ID CC, bool isVarArg, // No stack is used. StackOffset = 0; - UsedRegs.resize((TM.getRegisterInfo()->getNumRegs()+31)/32); + UsedRegs.resize( + (TM.getSubtargetImpl()->getRegisterInfo()->getNumRegs() + 31) / 32); } // HandleByVal - Allocate a stack slot large enough to pass an argument by @@ -55,7 +57,7 @@ void Hexagon_CCState::HandleByVal(unsigned ValNo, EVT ValVT, /// MarkAllocated - Mark a register and all of its aliases as allocated. void Hexagon_CCState::MarkAllocated(unsigned Reg) { - const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); + const TargetRegisterInfo &TRI = *TM.getSubtargetImpl()->getRegisterInfo(); for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI) UsedRegs[*AI/32] |= 1 << (*AI&31); } diff --git a/lib/Target/Hexagon/HexagonCallingConvLower.h b/lib/Target/Hexagon/HexagonCallingConvLower.h index 70b8b643441a..738ed1a52a09 100644 --- a/lib/Target/Hexagon/HexagonCallingConvLower.h +++ b/lib/Target/Hexagon/HexagonCallingConvLower.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_Hexagon_CODEGEN_CALLINGCONVLOWER_H -#define LLVM_Hexagon_CODEGEN_CALLINGCONVLOWER_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONCALLINGCONVLOWER_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONCALLINGCONVLOWER_H #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/CallingConvLower.h" diff --git a/lib/Target/Hexagon/HexagonCopyToCombine.cpp b/lib/Target/Hexagon/HexagonCopyToCombine.cpp index aeff680e6a9e..1883ad8f2e51 100644 --- a/lib/Target/Hexagon/HexagonCopyToCombine.cpp +++ b/lib/Target/Hexagon/HexagonCopyToCombine.cpp @@ -114,7 +114,7 @@ static bool isCombinableInstType(MachineInstr *MI, const HexagonInstrInfo *TII, bool ShouldCombineAggressively) { switch(MI->getOpcode()) { - case Hexagon::TFR: { + case Hexagon::A2_tfr: { // A COPY instruction can be combined if its arguments are IntRegs (32bit). assert(MI->getOperand(0).isReg() && MI->getOperand(1).isReg()); @@ -124,7 +124,7 @@ static bool isCombinableInstType(MachineInstr *MI, Hexagon::IntRegsRegClass.contains(SrcReg); } - case Hexagon::TFRI: { + case Hexagon::A2_tfrsi: { // A transfer-immediate can be combined if its argument is a signed 8bit // value. assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm()); @@ -158,11 +158,11 @@ static bool isCombinableInstType(MachineInstr *MI, } static bool isGreaterThan8BitTFRI(MachineInstr *I) { - return I->getOpcode() == Hexagon::TFRI && + return I->getOpcode() == Hexagon::A2_tfrsi && !isInt<8>(I->getOperand(1).getImm()); } static bool isGreaterThan6BitTFRI(MachineInstr *I) { - return I->getOpcode() == Hexagon::TFRI && + return I->getOpcode() == Hexagon::A2_tfrsi && !isUInt<6>(I->getOperand(1).getImm()); } @@ -171,11 +171,11 @@ static bool isGreaterThan6BitTFRI(MachineInstr *I) { static bool areCombinableOperations(const TargetRegisterInfo *TRI, MachineInstr *HighRegInst, MachineInstr *LowRegInst) { - assert((HighRegInst->getOpcode() == Hexagon::TFR || - HighRegInst->getOpcode() == Hexagon::TFRI || + assert((HighRegInst->getOpcode() == Hexagon::A2_tfr || + HighRegInst->getOpcode() == Hexagon::A2_tfrsi || HighRegInst->getOpcode() == Hexagon::TFRI_V4) && - (LowRegInst->getOpcode() == Hexagon::TFR || - LowRegInst->getOpcode() == Hexagon::TFRI || + (LowRegInst->getOpcode() == Hexagon::A2_tfr || + LowRegInst->getOpcode() == Hexagon::A2_tfrsi || LowRegInst->getOpcode() == Hexagon::TFRI_V4) && "Assume individual instructions are of a combinable type"); @@ -417,8 +417,8 @@ bool HexagonCopyToCombine::runOnMachineFunction(MachineFunction &MF) { bool HasChanged = false; // Get target info. - TRI = MF.getTarget().getRegisterInfo(); - TII = static_cast<const HexagonInstrInfo *>(MF.getTarget().getInstrInfo()); + TRI = MF.getSubtarget().getRegisterInfo(); + TII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); // Combine aggressively (for code size) ShouldCombineAggressively = @@ -563,14 +563,14 @@ void HexagonCopyToCombine::emitCombineII(MachineBasicBlock::iterator &InsertPt, // Handle globals. if (HiOperand.isGlobal()) { - BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::COMBINE_Ii), DoubleDestReg) + BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg) .addGlobalAddress(HiOperand.getGlobal(), HiOperand.getOffset(), HiOperand.getTargetFlags()) .addImm(LoOperand.getImm()); return; } if (LoOperand.isGlobal()) { - BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::COMBINE_iI_V4), DoubleDestReg) + BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg) .addImm(HiOperand.getImm()) .addGlobalAddress(LoOperand.getGlobal(), LoOperand.getOffset(), LoOperand.getTargetFlags()); @@ -580,7 +580,7 @@ void HexagonCopyToCombine::emitCombineII(MachineBasicBlock::iterator &InsertPt, // Handle constant extended immediates. if (!isInt<8>(HiOperand.getImm())) { assert(isInt<8>(LoOperand.getImm())); - BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::COMBINE_Ii), DoubleDestReg) + BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg) .addImm(HiOperand.getImm()) .addImm(LoOperand.getImm()); return; @@ -588,7 +588,7 @@ void HexagonCopyToCombine::emitCombineII(MachineBasicBlock::iterator &InsertPt, if (!isUInt<6>(LoOperand.getImm())) { assert(isInt<8>(HiOperand.getImm())); - BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::COMBINE_iI_V4), DoubleDestReg) + BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg) .addImm(HiOperand.getImm()) .addImm(LoOperand.getImm()); return; @@ -596,7 +596,7 @@ void HexagonCopyToCombine::emitCombineII(MachineBasicBlock::iterator &InsertPt, // Insert new combine instruction. // DoubleRegDest = combine #HiImm, #LoImm - BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::COMBINE_Ii), DoubleDestReg) + BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg) .addImm(HiOperand.getImm()) .addImm(LoOperand.getImm()); } @@ -613,7 +613,7 @@ void HexagonCopyToCombine::emitCombineIR(MachineBasicBlock::iterator &InsertPt, // Handle global. if (HiOperand.isGlobal()) { - BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::COMBINE_Ir_V4), DoubleDestReg) + BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg) .addGlobalAddress(HiOperand.getGlobal(), HiOperand.getOffset(), HiOperand.getTargetFlags()) .addReg(LoReg, LoRegKillFlag); @@ -621,7 +621,7 @@ void HexagonCopyToCombine::emitCombineIR(MachineBasicBlock::iterator &InsertPt, } // Insert new combine instruction. // DoubleRegDest = combine #HiImm, LoReg - BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::COMBINE_Ir_V4), DoubleDestReg) + BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg) .addImm(HiOperand.getImm()) .addReg(LoReg, LoRegKillFlag); } @@ -638,7 +638,7 @@ void HexagonCopyToCombine::emitCombineRI(MachineBasicBlock::iterator &InsertPt, // Handle global. if (LoOperand.isGlobal()) { - BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::COMBINE_rI_V4), DoubleDestReg) + BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg) .addReg(HiReg, HiRegKillFlag) .addGlobalAddress(LoOperand.getGlobal(), LoOperand.getOffset(), LoOperand.getTargetFlags()); @@ -647,7 +647,7 @@ void HexagonCopyToCombine::emitCombineRI(MachineBasicBlock::iterator &InsertPt, // Insert new combine instruction. // DoubleRegDest = combine HiReg, #LoImm - BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::COMBINE_rI_V4), DoubleDestReg) + BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg) .addReg(HiReg, HiRegKillFlag) .addImm(LoOperand.getImm()); } @@ -666,7 +666,7 @@ void HexagonCopyToCombine::emitCombineRR(MachineBasicBlock::iterator &InsertPt, // Insert new combine instruction. // DoubleRegDest = combine HiReg, LoReg - BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::COMBINE_rr), DoubleDestReg) + BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combinew), DoubleDestReg) .addReg(HiReg, HiRegKillFlag) .addReg(LoReg, LoRegKillFlag); } diff --git a/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp b/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp index 3dafe80ffc48..a2a847c47a20 100644 --- a/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp +++ b/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp @@ -72,7 +72,7 @@ char HexagonExpandPredSpillCode::ID = 0; bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { - const HexagonInstrInfo *TII = QTM.getInstrInfo(); + const HexagonInstrInfo *TII = QTM.getSubtargetImpl()->getInstrInfo(); // Loop over all of the basic blocks. for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); @@ -86,43 +86,45 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { if (Opc == Hexagon::STriw_pred) { // STriw_pred [R30], ofst, SrcReg; unsigned FP = MI->getOperand(0).getReg(); - assert(FP == QTM.getRegisterInfo()->getFrameRegister() && - "Not a Frame Pointer, Nor a Spill Slot"); + assert( + FP == + QTM.getSubtargetImpl()->getRegisterInfo()->getFrameRegister() && + "Not a Frame Pointer, Nor a Spill Slot"); assert(MI->getOperand(1).isImm() && "Not an offset"); int Offset = MI->getOperand(1).getImm(); int SrcReg = MI->getOperand(2).getReg(); assert(Hexagon::PredRegsRegClass.contains(SrcReg) && "Not a predicate register"); - if (!TII->isValidOffset(Hexagon::STriw_indexed, Offset)) { + if (!TII->isValidOffset(Hexagon::S2_storeri_io, Offset)) { if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::CONST32_Int_Real), HEXAGON_RESERVED_REG_1).addImm(Offset); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add), HEXAGON_RESERVED_REG_1) .addReg(FP).addReg(HEXAGON_RESERVED_REG_1); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), HEXAGON_RESERVED_REG_2).addReg(SrcReg); BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::STriw_indexed)) + TII->get(Hexagon::S2_storeri_io)) .addReg(HEXAGON_RESERVED_REG_1) .addImm(0).addReg(HEXAGON_RESERVED_REG_2); } else { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), HEXAGON_RESERVED_REG_2).addReg(SrcReg); BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::STriw_indexed)) + TII->get(Hexagon::S2_storeri_io)) .addReg(HEXAGON_RESERVED_REG_1) .addImm(0) .addReg(HEXAGON_RESERVED_REG_2); } } else { - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), HEXAGON_RESERVED_REG_2).addReg(SrcReg); BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::STriw_indexed)). + TII->get(Hexagon::S2_storeri_io)). addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2); } MII = MBB->erase(MI); @@ -133,39 +135,41 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { assert(Hexagon::PredRegsRegClass.contains(DstReg) && "Not a predicate register"); unsigned FP = MI->getOperand(1).getReg(); - assert(FP == QTM.getRegisterInfo()->getFrameRegister() && - "Not a Frame Pointer, Nor a Spill Slot"); + assert( + FP == + QTM.getSubtargetImpl()->getRegisterInfo()->getFrameRegister() && + "Not a Frame Pointer, Nor a Spill Slot"); assert(MI->getOperand(2).isImm() && "Not an offset"); int Offset = MI->getOperand(2).getImm(); - if (!TII->isValidOffset(Hexagon::LDriw, Offset)) { + if (!TII->isValidOffset(Hexagon::L2_loadri_io, Offset)) { if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::CONST32_Int_Real), HEXAGON_RESERVED_REG_1).addImm(Offset); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add), HEXAGON_RESERVED_REG_1) .addReg(FP) .addReg(HEXAGON_RESERVED_REG_1); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), HEXAGON_RESERVED_REG_2) .addReg(HEXAGON_RESERVED_REG_1) .addImm(0); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), DstReg).addReg(HEXAGON_RESERVED_REG_2); } else { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), HEXAGON_RESERVED_REG_2) .addReg(HEXAGON_RESERVED_REG_1) .addImm(0); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), DstReg).addReg(HEXAGON_RESERVED_REG_2); } } else { - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), DstReg).addReg(HEXAGON_RESERVED_REG_2); } MII = MBB->erase(MI); diff --git a/lib/Target/Hexagon/HexagonFixupHwLoops.cpp b/lib/Target/Hexagon/HexagonFixupHwLoops.cpp index d41939a57a45..e8d8f1497bdb 100644 --- a/lib/Target/Hexagon/HexagonFixupHwLoops.cpp +++ b/lib/Target/Hexagon/HexagonFixupHwLoops.cpp @@ -81,8 +81,8 @@ FunctionPass *llvm::createHexagonFixupHwLoops() { /// \brief Returns true if the instruction is a hardware loop instruction. static bool isHardwareLoop(const MachineInstr *MI) { - return MI->getOpcode() == Hexagon::LOOP0_r || - MI->getOpcode() == Hexagon::LOOP0_i; + return MI->getOpcode() == Hexagon::J2_loop0r || + MI->getOpcode() == Hexagon::J2_loop0i; } @@ -160,7 +160,7 @@ bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) { void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF, MachineBasicBlock::iterator &MII, RegScavenger &RS) { - const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); MachineBasicBlock *MBB = MII->getParent(); DebugLoc DL = MII->getDebugLoc(); unsigned Scratch = RS.scavengeRegister(&Hexagon::IntRegsRegClass, MII, 0); @@ -168,18 +168,18 @@ void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF, // First, set the LC0 with the trip count. if (MII->getOperand(1).isReg()) { // Trip count is a register - BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0) + BuildMI(*MBB, MII, DL, TII->get(Hexagon::A2_tfrrcr), Hexagon::LC0) .addReg(MII->getOperand(1).getReg()); } else { // Trip count is an immediate. - BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch) + BuildMI(*MBB, MII, DL, TII->get(Hexagon::A2_tfrsi), Scratch) .addImm(MII->getOperand(1).getImm()); - BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0) + BuildMI(*MBB, MII, DL, TII->get(Hexagon::A2_tfrrcr), Hexagon::LC0) .addReg(Scratch); } // Then, set the SA0 with the loop start address. BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch) .addMBB(MII->getOperand(0).getMBB()); - BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0) + BuildMI(*MBB, MII, DL, TII->get(Hexagon::A2_tfrrcr), Hexagon::SA0) .addReg(Scratch); } diff --git a/lib/Target/Hexagon/HexagonFrameLowering.cpp b/lib/Target/Hexagon/HexagonFrameLowering.cpp index 21df12faefae..9d1a527eddb3 100644 --- a/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -50,7 +50,10 @@ void HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const { unsigned FrameSize = MFI->getStackSize(); // Get the alignments provided by the target. - unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment(); + unsigned TargetAlign = MF.getTarget() + .getSubtargetImpl() + ->getFrameLowering() + ->getStackAlignment(); // Get the maximum call frame size of all the calls. unsigned maxCallFrameSize = MFI->getMaxCallFrameSize(); @@ -77,8 +80,8 @@ void HexagonFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineBasicBlock::iterator MBBI = MBB.begin(); - const HexagonRegisterInfo *QRI = - static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo()); + const HexagonRegisterInfo *QRI = static_cast<const HexagonRegisterInfo *>( + MF.getSubtarget().getRegisterInfo()); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); determineFrameLayout(MF); @@ -115,21 +118,21 @@ void HexagonFrameLowering::emitPrologue(MachineFunction &MF) const { // Check for overflow. // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used? const int ALLOCFRAME_MAX = 16384; - const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); if (NumBytes >= ALLOCFRAME_MAX) { // Emit allocframe(#0). - BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0); + BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::S2_allocframe)).addImm(0); // Subtract offset from frame pointer. BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real), HEXAGON_RESERVED_REG_1).addImm(NumBytes); - BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr), + BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::A2_sub), QRI->getStackRegister()). addReg(QRI->getStackRegister()). addReg(HEXAGON_RESERVED_REG_1); } else { - BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes); + BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::S2_allocframe)).addImm(NumBytes); } } } @@ -154,12 +157,12 @@ void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock::iterator MBBI = std::prev(MBB.end()); MachineBasicBlock::iterator MBBI_end = MBB.end(); - const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); // Handle EH_RETURN. if (MBBI->getOpcode() == Hexagon::EH_RETURN_JMPR) { assert(MBBI->getOperand(0).isReg() && "Offset should be in register!"); - BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)); - BuildMI(MBB, MBBI, dl, TII.get(Hexagon::ADD_rr), + BuildMI(MBB, MBBI, dl, TII.get(Hexagon::L2_deallocframe)); + BuildMI(MBB, MBBI, dl, TII.get(Hexagon::A2_add), Hexagon::R29).addReg(Hexagon::R29).addReg(Hexagon::R28); return; } @@ -180,7 +183,7 @@ void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, // Add dealloc_return. MachineInstrBuilder MIB = - BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)); + BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::L4_return)); // Transfer the function live-out registers. MIB->copyImplicitOps(*MBB.getParent(), &*MBBI); // Remove the JUMPR node. @@ -195,7 +198,7 @@ void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, I->getOpcode() == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4) return; - BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)); + BuildMI(MBB, MBBI, dl, TII.get(Hexagon::L2_deallocframe)); } } } @@ -225,7 +228,7 @@ HexagonFrameLowering::spillCalleeSavedRegisters( const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { MachineFunction *MF = MBB.getParent(); - const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); if (CSI.empty()) { return false; @@ -280,7 +283,7 @@ bool HexagonFrameLowering::restoreCalleeSavedRegisters( const TargetRegisterInfo *TRI) const { MachineFunction *MF = MBB.getParent(); - const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); if (CSI.empty()) { return false; diff --git a/lib/Target/Hexagon/HexagonFrameLowering.h b/lib/Target/Hexagon/HexagonFrameLowering.h index 2d4b0b9d7eb3..2d6b45793809 100644 --- a/lib/Target/Hexagon/HexagonFrameLowering.h +++ b/lib/Target/Hexagon/HexagonFrameLowering.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HEXAGON_FRAMEINFO_H -#define HEXAGON_FRAMEINFO_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONFRAMELOWERING_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONFRAMELOWERING_H #include "Hexagon.h" #include "llvm/Target/TargetFrameLowering.h" diff --git a/lib/Target/Hexagon/HexagonHardwareLoops.cpp b/lib/Target/Hexagon/HexagonHardwareLoops.cpp index 7f76421ac3e0..637b0a0d0bff 100644 --- a/lib/Target/Hexagon/HexagonHardwareLoops.cpp +++ b/lib/Target/Hexagon/HexagonHardwareLoops.cpp @@ -220,7 +220,7 @@ namespace { int HexagonHardwareLoops::Counter = 0; #endif - /// \brief Abstraction for a trip count of a loop. A smaller vesrsion + /// \brief Abstraction for a trip count of a loop. A smaller version /// of the MachineOperand class without the concerns of changing the /// operand representation. class CountValue { @@ -266,7 +266,8 @@ namespace { } void print(raw_ostream &OS, const TargetMachine *TM = nullptr) const { - const TargetRegisterInfo *TRI = TM ? TM->getRegisterInfo() : nullptr; + const TargetRegisterInfo *TRI = + TM ? TM->getSubtargetImpl()->getRegisterInfo() : nullptr; if (isReg()) { OS << PrintReg(Contents.R.Reg, TRI, Contents.R.Sub); } if (isImm()) { OS << Contents.ImmVal; } } @@ -284,8 +285,8 @@ INITIALIZE_PASS_END(HexagonHardwareLoops, "hwloops", /// \brief Returns true if the instruction is a hardware loop instruction. static bool isHardwareLoop(const MachineInstr *MI) { - return MI->getOpcode() == Hexagon::LOOP0_r || - MI->getOpcode() == Hexagon::LOOP0_i; + return MI->getOpcode() == Hexagon::J2_loop0r || + MI->getOpcode() == Hexagon::J2_loop0i; } FunctionPass *llvm::createHexagonHardwareLoops() { @@ -302,8 +303,10 @@ bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) { MRI = &MF.getRegInfo(); MDT = &getAnalysis<MachineDominatorTree>(); TM = static_cast<const HexagonTargetMachine*>(&MF.getTarget()); - TII = static_cast<const HexagonInstrInfo*>(TM->getInstrInfo()); - TRI = static_cast<const HexagonRegisterInfo*>(TM->getRegisterInfo()); + TII = static_cast<const HexagonInstrInfo *>( + TM->getSubtargetImpl()->getInstrInfo()); + TRI = static_cast<const HexagonRegisterInfo *>( + TM->getSubtargetImpl()->getRegisterInfo()); for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); I != E; ++I) { @@ -537,16 +540,16 @@ CountValue *HexagonHardwareLoops::getLoopTripCount(MachineLoop *L, return nullptr; switch (CondOpc) { - case Hexagon::CMPEQri: - case Hexagon::CMPEQrr: + case Hexagon::C2_cmpeqi: + case Hexagon::C2_cmpeq: Cmp = !Negated ? Comparison::EQ : Comparison::NE; break; - case Hexagon::CMPGTUri: - case Hexagon::CMPGTUrr: + case Hexagon::C2_cmpgtui: + case Hexagon::C2_cmpgtu: Cmp = !Negated ? Comparison::GTu : Comparison::LEu; break; - case Hexagon::CMPGTri: - case Hexagon::CMPGTrr: + case Hexagon::C2_cmpgti: + case Hexagon::C2_cmpgt: Cmp = !Negated ? Comparison::GTs : Comparison::LEs; break; // Very limited support for byte/halfword compares. @@ -623,12 +626,12 @@ CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop, // If so, use the immediate value rather than the register. if (Start->isReg()) { const MachineInstr *StartValInstr = MRI->getVRegDef(Start->getReg()); - if (StartValInstr && StartValInstr->getOpcode() == Hexagon::TFRI) + if (StartValInstr && StartValInstr->getOpcode() == Hexagon::A2_tfrsi) Start = &StartValInstr->getOperand(1); } if (End->isReg()) { const MachineInstr *EndValInstr = MRI->getVRegDef(End->getReg()); - if (EndValInstr && EndValInstr->getOpcode() == Hexagon::TFRI) + if (EndValInstr && EndValInstr->getOpcode() == Hexagon::A2_tfrsi) End = &EndValInstr->getOperand(1); } @@ -778,7 +781,7 @@ CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop, DistR = End->getReg(); DistSR = End->getSubReg(); } else { - const MCInstrDesc &SubD = RegToReg ? TII->get(Hexagon::SUB_rr) : + const MCInstrDesc &SubD = RegToReg ? TII->get(Hexagon::A2_sub) : (RegToImm ? TII->get(Hexagon::SUB_ri) : TII->get(Hexagon::ADD_ri)); unsigned SubR = MRI->createVirtualRegister(IntRC); @@ -829,7 +832,7 @@ CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop, // Generate NormR = LSR DistR, Shift. unsigned LsrR = MRI->createVirtualRegister(IntRC); - const MCInstrDesc &LsrD = TII->get(Hexagon::LSR_ri); + const MCInstrDesc &LsrD = TII->get(Hexagon::S2_lsr_i_r); BuildMI(*PH, InsertPos, DL, LsrD, LsrR) .addReg(AdjR, 0, AdjSR) .addImm(Shift); @@ -1083,7 +1086,7 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) { BuildMI(*Preheader, InsertPos, DL, TII->get(TargetOpcode::COPY), CountReg) .addReg(TripCount->getReg(), 0, TripCount->getSubReg()); // Add the Loop instruction to the beginning of the loop. - BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::LOOP0_r)) + BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::J2_loop0r)) .addMBB(LoopStart) .addReg(CountReg); } else { @@ -1092,14 +1095,14 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) { // if the immediate fits in the instructions. Otherwise, we need to // create a new virtual register. int64_t CountImm = TripCount->getImm(); - if (!TII->isValidOffset(Hexagon::LOOP0_i, CountImm)) { + if (!TII->isValidOffset(Hexagon::J2_loop0i, CountImm)) { unsigned CountReg = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass); - BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::TFRI), CountReg) + BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::A2_tfrsi), CountReg) .addImm(CountImm); - BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::LOOP0_r)) + BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::J2_loop0r)) .addMBB(LoopStart).addReg(CountReg); } else - BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::LOOP0_i)) + BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::J2_loop0i)) .addMBB(LoopStart).addImm(CountImm); } @@ -1119,8 +1122,8 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) { // The loop ends with either: // - a conditional branch followed by an unconditional branch, or // - a conditional branch to the loop start. - if (LastI->getOpcode() == Hexagon::JMP_t || - LastI->getOpcode() == Hexagon::JMP_f) { + if (LastI->getOpcode() == Hexagon::J2_jumpt || + LastI->getOpcode() == Hexagon::J2_jumpf) { // Delete one and change/add an uncond. branch to out of the loop. MachineBasicBlock *BranchTarget = LastI->getOperand(1).getMBB(); LastI = LastMBB->erase(LastI); @@ -1191,8 +1194,8 @@ MachineInstr *HexagonHardwareLoops::defWithImmediate(unsigned R) { MachineInstr *DI = MRI->getVRegDef(R); unsigned DOpc = DI->getOpcode(); switch (DOpc) { - case Hexagon::TFRI: - case Hexagon::TFRI64: + case Hexagon::A2_tfrsi: + case Hexagon::A2_tfrpi: case Hexagon::CONST32_Int_Real: case Hexagon::CONST64_Int_Real: return DI; diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index dabe650a5b70..ea3a1770ac31 100644 --- a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -320,38 +320,38 @@ static unsigned doesIntrinsicContainPredicate(unsigned ID) default: return 0; case Intrinsic::hexagon_C2_tfrpr: - return Hexagon::TFR_RsPd; + return Hexagon::C2_tfrpr; case Intrinsic::hexagon_C2_and: - return Hexagon::AND_pp; + return Hexagon::C2_and; case Intrinsic::hexagon_C2_xor: - return Hexagon::XOR_pp; + return Hexagon::C2_xor; case Intrinsic::hexagon_C2_or: - return Hexagon::OR_pp; + return Hexagon::C2_or; case Intrinsic::hexagon_C2_not: - return Hexagon::NOT_p; + return Hexagon::C2_not; case Intrinsic::hexagon_C2_any8: - return Hexagon::ANY_pp; + return Hexagon::C2_any8; case Intrinsic::hexagon_C2_all8: - return Hexagon::ALL_pp; + return Hexagon::C2_all8; case Intrinsic::hexagon_C2_vitpack: - return Hexagon::VITPACK_pp; + return Hexagon::C2_vitpack; case Intrinsic::hexagon_C2_mask: - return Hexagon::MASK_p; + return Hexagon::C2_mask; case Intrinsic::hexagon_C2_mux: - return Hexagon::MUX_rr; + return Hexagon::C2_mux; // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but // that's how it's mapped in q6protos.h. case Intrinsic::hexagon_C2_muxir: - return Hexagon::MUX_ri; + return Hexagon::C2_muxri; // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but // that's how it's mapped in q6protos.h. case Intrinsic::hexagon_C2_muxri: - return Hexagon::MUX_ir; + return Hexagon::C2_muxir; case Intrinsic::hexagon_C2_muxii: - return Hexagon::MUX_ii; + return Hexagon::C2_muxii; case Intrinsic::hexagon_C2_vmux: return Hexagon::VMUX_prr64; case Intrinsic::hexagon_S2_valignrb: @@ -404,10 +404,10 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl) { dl, PointerTy, TargAddr); // Figure out base + offset opcode - if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed; - else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed; - else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed; - else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed; + if (LoadedVT == MVT::i64) Opcode = Hexagon::L2_loadrd_io; + else if (LoadedVT == MVT::i32) Opcode = Hexagon::L2_loadri_io; + else if (LoadedVT == MVT::i16) Opcode = Hexagon::L2_loadrh_io; + else if (LoadedVT == MVT::i8) Opcode = Hexagon::L2_loadrb_io; else llvm_unreachable("unknown memory type"); // Build indexed load. @@ -446,14 +446,14 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && N1.getNode()->getValueType(0) == MVT::i32) { - const HexagonInstrInfo *TII = - static_cast<const HexagonInstrInfo*>(TM.getInstrInfo()); + const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>( + TM.getSubtargetImpl()->getInstrInfo()); if (TII->isValidAutoIncImm(LoadedVT, Val)) { SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32); SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, MVT::Other, Base, TargetConst, Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, MVT::i64, + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64, SDValue(Result_1, 0)); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); MemOp[0] = LD->getMemOperand(); @@ -474,7 +474,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other, Base, TargetConst0, Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64, SDValue(Result_1, 0)); SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, Base, TargetConstVal, @@ -513,17 +513,17 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && N1.getNode()->getValueType(0) == MVT::i32) { - const HexagonInstrInfo *TII = - static_cast<const HexagonInstrInfo*>(TM.getInstrInfo()); + const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>( + TM.getSubtargetImpl()->getInstrInfo()); if (TII->isValidAutoIncImm(LoadedVT, Val)) { SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, MVT::Other, Base, TargetConstVal, Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, TargetConst0); - SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, + SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl, MVT::i64, MVT::Other, SDValue(Result_2,0), SDValue(Result_1,0)); @@ -548,9 +548,9 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other, Base, TargetConst0, Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, TargetConst0); - SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, + SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl, MVT::i64, MVT::Other, SDValue(Result_2,0), SDValue(Result_1,0)); @@ -591,28 +591,28 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) { bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD); // Figure out the opcode. - const HexagonInstrInfo *TII = - static_cast<const HexagonInstrInfo*>(TM.getInstrInfo()); + const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>( + TM.getSubtargetImpl()->getInstrInfo()); if (LoadedVT == MVT::i64) { if (TII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = Hexagon::POST_LDrid; + Opcode = Hexagon::L2_loadrd_pi; else - Opcode = Hexagon::LDrid; + Opcode = Hexagon::L2_loadrd_io; } else if (LoadedVT == MVT::i32) { if (TII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = Hexagon::POST_LDriw; + Opcode = Hexagon::L2_loadri_pi; else - Opcode = Hexagon::LDriw; + Opcode = Hexagon::L2_loadri_io; } else if (LoadedVT == MVT::i16) { if (TII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = zextval ? Hexagon::POST_LDriuh : Hexagon::POST_LDrih; + Opcode = zextval ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi; else - Opcode = zextval ? Hexagon::LDriuh : Hexagon::LDrih; + Opcode = zextval ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io; } else if (LoadedVT == MVT::i8) { if (TII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = zextval ? Hexagon::POST_LDriub : Hexagon::POST_LDrib; + Opcode = zextval ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi; else - Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib; + Opcode = zextval ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io; } else llvm_unreachable("unknown memory type"); @@ -701,18 +701,18 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) { // Offset value must be within representable range // and must have correct alignment properties. - const HexagonInstrInfo *TII = - static_cast<const HexagonInstrInfo*>(TM.getInstrInfo()); + const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>( + TM.getSubtargetImpl()->getInstrInfo()); if (TII->isValidAutoIncImm(StoredVT, Val)) { SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value, Chain}; unsigned Opcode = 0; // Figure out the post inc version of opcode. - if (StoredVT == MVT::i64) Opcode = Hexagon::POST_STdri; - else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri; - else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri; - else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri; + if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi; + else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi; + else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi; + else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi; else llvm_unreachable("unknown memory type"); // Build post increment store. @@ -735,10 +735,10 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) { unsigned Opcode = 0; // Figure out the opcode. - if (StoredVT == MVT::i64) Opcode = Hexagon::STrid; - else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; - else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih; - else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib; + if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io; + else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io; + else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io; + else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io; else llvm_unreachable("unknown memory type"); // Build regular store. @@ -788,10 +788,10 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, TargAddr); // Figure out base + offset opcode - if (StoredVT == MVT::i64) Opcode = Hexagon::STrid_indexed; - else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; - else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed; - else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed; + if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io; + else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io; + else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io; + else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io; else llvm_unreachable("unknown memory type"); SDValue Ops[] = {SDValue(NewBase,0), @@ -865,7 +865,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { SDValue Chain = LD->getChain(); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); - OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32, MVT::Other, LD->getBasePtr(), TargetConst0, Chain), 0); @@ -891,7 +891,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { SDValue Chain = LD->getChain(); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); - OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32, MVT::Other, LD->getBasePtr(), TargetConst0, Chain), 0); @@ -900,7 +900,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { } // Generate a mpy instruction. - SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64, + SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64, OP0, OP1); ReplaceUses(N, Result); return Result; @@ -934,9 +934,9 @@ SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) { if (N000 == N2 && N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { - SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, + SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl, MVT::i32, N000); - SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl, + SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_max, dl, MVT::i32, SDValue(SextNode, 0), N1); @@ -958,9 +958,9 @@ SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) { if (N000 == N2 && N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { - SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, + SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl, MVT::i32, N000); - SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl, + SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_min, dl, MVT::i32, SDValue(SextNode, 0), N1); @@ -1045,7 +1045,7 @@ SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { SDValue Chain = LD->getChain(); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); - OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32, MVT::Other, LD->getBasePtr(), TargetConst0, Chain), 0); @@ -1070,7 +1070,7 @@ SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { SDValue Chain = LD->getChain(); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); - OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32, MVT::Other, LD->getBasePtr(), TargetConst0, Chain), 0); @@ -1079,7 +1079,7 @@ SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { } // Generate a mpy instruction. - SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32, + SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpy_up, dl, MVT::i32, OP0, OP1); ReplaceUses(N, Result); return Result; @@ -1112,7 +1112,7 @@ SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) { if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode())) if (isInt<9>(CN->getSExtValue())) { SDNode* Result = - CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, + CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32, Mul_0, Val); ReplaceUses(N, Result); return Result; @@ -1140,7 +1140,7 @@ SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) { dyn_cast<ConstantSDNode>(Val.getNode())) if (isInt<9>(CN->getSExtValue())) { SDNode* Result = - CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32, + CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32, Shl2_0, Val); ReplaceUses(N, Result); return Result; @@ -1177,13 +1177,13 @@ SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { if (N->getValueType(0) == MVT::i64) { // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs). SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); - SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, + SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl, MVT::i32, SDValue(IsIntrinsic, 0)); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, TargetConst0); - SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, + SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl, MVT::i64, MVT::Other, SDValue(Result_2, 0), SDValue(Result_1, 0)); @@ -1192,7 +1192,7 @@ SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { } if (N->getValueType(0) == MVT::i32) { // Convert the zero_extend to Rs = Pd - SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, + SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl, MVT::i32, SDValue(IsIntrinsic, 0)); ReplaceUses(N, RsPd); @@ -1218,10 +1218,10 @@ SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { // as at least one of the operands. if (IntrinsicWithPred) { SmallVector<SDValue, 8> Ops; - const HexagonInstrInfo *TII = - static_cast<const HexagonInstrInfo*>(TM.getInstrInfo()); + const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>( + TM.getSubtargetImpl()->getInstrInfo()); const MCInstrDesc &MCID = TII->get(IntrinsicWithPred); - const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo(); // Iterate over all the operands of the intrinsics. // For PredRegs, do the transfer. @@ -1236,7 +1236,7 @@ SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { Ops.push_back(SDValue(Arg, 0)); } else if (RC == &Hexagon::PredRegsRegClass) { // Do the transfer. - SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, + SDNode *PdRs = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1, SDValue(Arg, 0)); Ops.push_back(SDValue(PdRs,0)); } else if (!RC && (dyn_cast<ConstantSDNode>(Arg) != nullptr)) { @@ -1289,19 +1289,19 @@ SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) { if (Val == -1) { // Create the IntReg = 1 node. SDNode* IntRegTFR = - CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, + CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, CurDAG->getTargetConstant(0, MVT::i32)); // Pd = IntReg - SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, + SDNode* Pd = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1, SDValue(IntRegTFR, 0)); // not(Pd) - SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1, + SDNode* NotPd = CurDAG->getMachineNode(Hexagon::C2_not, dl, MVT::i1, SDValue(Pd, 0)); // xor(not(Pd)) - Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1, + Result = CurDAG->getMachineNode(Hexagon::C2_xor, dl, MVT::i1, SDValue(Pd, 0), SDValue(NotPd, 0)); // We have just built: @@ -1334,7 +1334,7 @@ SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) { // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that // Rd and Rd' are assigned to the same register - SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_ADD_rr, dl, MVT::i32, + SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32, N->getOperand(1), Src1->getOperand(0), Src1->getOperand(1)); diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp index a460ea4f3420..ef5d6b97fd6f 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -51,9 +51,9 @@ class HexagonCCState : public CCState { public: HexagonCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - const TargetMachine &TM, SmallVectorImpl<CCValAssign> &locs, - LLVMContext &C, int NumNamedVarArgParams) - : CCState(CC, isVarArg, MF, TM, locs, C), + SmallVectorImpl<CCValAssign> &locs, LLVMContext &C, + int NumNamedVarArgParams) + : CCState(CC, isVarArg, MF, locs, C), NumNamedVarArgParams(NumNamedVarArgParams) {} int getNumNamedVarArgParams() const { return NumNamedVarArgParams; } @@ -322,8 +322,8 @@ HexagonTargetLowering::LowerReturn(SDValue Chain, SmallVector<CCValAssign, 16> RVLocs; // CCState - Info about the registers and stack slot. - CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), RVLocs, *DAG.getContext()); + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, + *DAG.getContext()); // Analyze return values of ISD::RET CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon); @@ -372,8 +372,8 @@ HexagonTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, // Assign locations to each value returned by this call. SmallVector<CCValAssign, 16> RVLocs; - CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), RVLocs, *DAG.getContext()); + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, + *DAG.getContext()); CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon); @@ -427,9 +427,8 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; - HexagonCCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), ArgLocs, *DAG.getContext(), - NumNamedVarArgParams); + HexagonCCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, + *DAG.getContext(), NumNamedVarArgParams); if (NumNamedVarArgParams > 0) CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_VarArg); @@ -464,7 +463,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVector<SDValue, 8> MemOpChains; const HexagonRegisterInfo *QRI = static_cast<const HexagonRegisterInfo *>( - DAG.getTarget().getRegisterInfo()); + DAG.getSubtarget().getRegisterInfo()); SDValue StackPtr = DAG.getCopyFromReg(Chain, dl, QRI->getStackRegister(), getPointerTy()); @@ -723,7 +722,7 @@ SDValue HexagonTargetLowering::LowerINLINEASM(SDValue Op, // Check it to be lr const HexagonRegisterInfo *QRI = static_cast<const HexagonRegisterInfo *>( - DAG.getTarget().getRegisterInfo()); + DAG.getSubtarget().getRegisterInfo()); if (Reg == QRI->getRARegister()) { FuncInfo->setHasClobberLR(true); break; @@ -817,7 +816,7 @@ HexagonTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, // The Sub result contains the new stack start address, so it // must be placed in the stack pointer register. const HexagonRegisterInfo *QRI = static_cast<const HexagonRegisterInfo *>( - DAG.getTarget().getRegisterInfo()); + DAG.getSubtarget().getRegisterInfo()); SDValue CopyChain = DAG.getCopyToReg(Chain, dl, QRI->getStackRegister(), Sub); SDValue Ops[2] = { ArgAdjust, CopyChain }; @@ -843,8 +842,8 @@ const { // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; - CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), ArgLocs, *DAG.getContext()); + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, + *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon); @@ -964,7 +963,7 @@ HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const { SDValue HexagonTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { - const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo(); + const TargetRegisterInfo *TRI = DAG.getSubtarget().getRegisterInfo(); MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MFI->setReturnAddressIsTaken(true); @@ -990,8 +989,8 @@ HexagonTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { SDValue HexagonTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { - const HexagonRegisterInfo *TRI = - static_cast<const HexagonRegisterInfo *>(DAG.getTarget().getRegisterInfo()); + const HexagonRegisterInfo *TRI = static_cast<const HexagonRegisterInfo *>( + DAG.getSubtarget().getRegisterInfo()); MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); MFI->setFrameAddressIsTaken(true); @@ -1044,7 +1043,7 @@ HexagonTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const { //===----------------------------------------------------------------------===// HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &targetmachine) - : TargetLowering(targetmachine, new HexagonTargetObjectFile()), + : TargetLowering(targetmachine), TM(targetmachine) { const HexagonSubtarget &Subtarget = TM.getSubtarget<HexagonSubtarget>(); @@ -1302,9 +1301,11 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &targetmachine) setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand); // Turn FP extload into load/fextend. - setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + for (MVT VT : MVT::fp_valuetypes()) + setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); // Hexagon has a i1 sign extending load. - setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Expand); + for (MVT VT : MVT::integer_valuetypes()) + setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Expand); // Turn FP truncstore into trunc + store. setTruncStoreAction(MVT::f64, MVT::f32, Expand); @@ -1453,8 +1454,8 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &targetmachine) setMinFunctionAlignment(2); // Needed for DYNAMIC_STACKALLOC expansion. - const HexagonRegisterInfo *QRI = - static_cast<const HexagonRegisterInfo *>(TM.getRegisterInfo()); + const HexagonRegisterInfo *QRI = static_cast<const HexagonRegisterInfo *>( + TM.getSubtargetImpl()->getRegisterInfo()); setStackPointerRegisterToSaveRestore(QRI->getStackRegister()); setSchedulingPreference(Sched::VLIW); } @@ -1706,3 +1707,17 @@ bool HexagonTargetLowering::IsEligibleForTailCallOptimization( // information is not available. return true; } + +// Return true when the given node fits in a positive half word. +bool llvm::isPositiveHalfWord(SDNode *N) { + ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N); + if (CN && CN->getSExtValue() > 0 && isInt<16>(CN->getSExtValue())) + return true; + + switch (N->getOpcode()) { + default: + return false; + case ISD::SIGN_EXTEND_INREG: + return true; + } +} diff --git a/lib/Target/Hexagon/HexagonISelLowering.h b/lib/Target/Hexagon/HexagonISelLowering.h index ec16cc8f894b..d03b1b8d9f4a 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.h +++ b/lib/Target/Hexagon/HexagonISelLowering.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef Hexagon_ISELLOWERING_H -#define Hexagon_ISELLOWERING_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONISELLOWERING_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONISELLOWERING_H #include "Hexagon.h" #include "llvm/CodeGen/CallingConvLower.h" @@ -21,6 +21,10 @@ #include "llvm/Target/TargetLowering.h" namespace llvm { + +// Return true when the given node fits in a positive half word. +bool isPositiveHalfWord(SDNode *N); + namespace HexagonISD { enum { FIRST_NUMBER = ISD::BUILTIN_OP_END, @@ -48,7 +52,9 @@ namespace llvm { CALL, // A call instruction. RET_FLAG, // Return with a flag operand. BR_JT, // Jump table. - BARRIER, // Memory barrier. + BARRIER, // Memory barrier + POPCOUNT, + COMBINE, WrapperJT, WrapperCP, WrapperCombineII, @@ -63,7 +69,8 @@ namespace llvm { WrapperShuffOB, WrapperShuffOH, TC_RETURN, - EH_RETURN + EH_RETURN, + DCFETCH }; } diff --git a/lib/Target/Hexagon/HexagonInstrFormats.td b/lib/Target/Hexagon/HexagonInstrFormats.td index 105734349321..8373652c8f64 100644 --- a/lib/Target/Hexagon/HexagonInstrFormats.td +++ b/lib/Target/Hexagon/HexagonInstrFormats.td @@ -92,12 +92,18 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern, let AsmString = asmstr; let Pattern = pattern; let Constraints = cstr; - let Itinerary = itin; - let Size = 4; - - // *** Must match MCTargetDesc/HexagonBaseInfo.h *** - - // Instruction type according to the ISA. + let Itinerary = itin;
+ let Size = 4;
+
+ // SoftFail is a field the disassembler can use to provide a way for
+ // instructions to not match without killing the whole decode process. It is
+ // mainly used for ARM, but Tablegen expects this field to exist or it fails
+ // to build the decode table.
+ field bits<32> SoftFail = 0;
+
+ // *** Must match MCTargetDesc/HexagonBaseInfo.h ***
+
+ // Instruction type according to the ISA.
IType Type = type; let TSFlags{4-0} = Type.Value; @@ -180,12 +186,13 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern, string InputType = ""; // Input is "imm" or "reg" type. string isMEMri = "false"; // Set to "true" for load/store with MEMri operand. string isFloat = "false"; // Set to "true" for the floating-point load/store. - string isBrTaken = ""; // Set to "true"/"false" for jump instructions + string isBrTaken = !if(isTaken, "true", "false"); // Set to "true"/"false" for jump instructions let PredSense = !if(isPredicated, !if(isPredicatedFalse, "false", "true"), ""); let PNewValue = !if(isPredicatedNew, "new", ""); let NValueST = !if(isNVStore, "true", "false"); + let isCodeGenOnly = 1; // *** Must match MCTargetDesc/HexagonBaseInfo.h *** } @@ -196,6 +203,7 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern, // LD Instruction Class in V2/V3/V4. // Definition of the instruction class NOT CHANGED. +let mayLoad = 1 in class LDInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], string cstr = "", InstrItinClass itin = LD_tc_ld_SLOT01> : InstHexagon<outs, ins, asmstr, pattern, cstr, itin, TypeLD>; diff --git a/lib/Target/Hexagon/HexagonInstrFormatsV4.td b/lib/Target/Hexagon/HexagonInstrFormatsV4.td index d92f97b0dd2d..5fec80bb570a 100644 --- a/lib/Target/Hexagon/HexagonInstrFormatsV4.td +++ b/lib/Target/Hexagon/HexagonInstrFormatsV4.td @@ -19,6 +19,7 @@ def TypeMEMOP : IType<9>; def TypeNV : IType<10>; +def TypeCOMPOUND : IType<12>; def TypePREFIX : IType<30>; //----------------------------------------------------------------------------// @@ -65,3 +66,7 @@ let isCodeGenOnly = 1 in class EXTENDERInst<dag outs, dag ins, string asmstr, list<dag> pattern = []> : InstHexagon<outs, ins, asmstr, pattern, "", EXTENDER_tc_1_SLOT0123, TypePREFIX>; + +class CJInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, COMPOUND, TypeCOMPOUND>; diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp index 1c95e06c8923..5d962590a705 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -78,11 +78,11 @@ unsigned HexagonInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, switch (MI->getOpcode()) { default: break; - case Hexagon::LDriw: - case Hexagon::LDrid: - case Hexagon::LDrih: - case Hexagon::LDrib: - case Hexagon::LDriub: + case Hexagon::L2_loadri_io: + case Hexagon::L2_loadrd_io: + case Hexagon::L2_loadrh_io: + case Hexagon::L2_loadrb_io: + case Hexagon::L2_loadrub_io: if (MI->getOperand(2).isFI() && MI->getOperand(1).isImm() && (MI->getOperand(1).getImm() == 0)) { FrameIndex = MI->getOperand(2).getIndex(); @@ -103,10 +103,10 @@ unsigned HexagonInstrInfo::isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const { switch (MI->getOpcode()) { default: break; - case Hexagon::STriw: - case Hexagon::STrid: - case Hexagon::STrih: - case Hexagon::STrib: + case Hexagon::S2_storeri_io: + case Hexagon::S2_storerd_io: + case Hexagon::S2_storerh_io: + case Hexagon::S2_storerb_io: if (MI->getOperand(2).isFI() && MI->getOperand(1).isImm() && (MI->getOperand(1).getImm() == 0)) { FrameIndex = MI->getOperand(0).getIndex(); @@ -124,8 +124,8 @@ HexagonInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB, const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const{ - int BOpc = Hexagon::JMP; - int BccOpc = Hexagon::JMP_t; + int BOpc = Hexagon::J2_jump; + int BccOpc = Hexagon::J2_jumpt; assert(TBB && "InsertBranch must not be told to insert a fallthrough"); @@ -134,7 +134,7 @@ HexagonInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB, // If we want to reverse the branch an odd number of times, we want // JMP_f. if (!Cond.empty() && Cond[0].isImm() && Cond[0].getImm() == 0) { - BccOpc = Hexagon::JMP_f; + BccOpc = Hexagon::J2_jumpf; regPos = 1; } @@ -213,7 +213,7 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, } // Delete the JMP if it's equivalent to a fall-through. - if (AllowModify && I->getOpcode() == Hexagon::JMP && + if (AllowModify && I->getOpcode() == Hexagon::J2_jump && MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { DEBUG(dbgs()<< "\nErasing the jump to successor block\n";); I->eraseFromParent(); @@ -249,7 +249,7 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, // If there is only one terminator instruction, process it. if (LastInst && !SecondLastInst) { - if (LastOpcode == Hexagon::JMP) { + if (LastOpcode == Hexagon::J2_jump) { TBB = LastInst->getOperand(0).getMBB(); return false; } @@ -274,7 +274,7 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, bool SecLastOpcodeHasJMP_c = PredOpcodeHasJMP_c(SecLastOpcode); bool SecLastOpcodeHasNot = PredOpcodeHasNot(SecLastOpcode); - if (SecLastOpcodeHasJMP_c && (LastOpcode == Hexagon::JMP)) { + if (SecLastOpcodeHasJMP_c && (LastOpcode == Hexagon::J2_jump)) { TBB = SecondLastInst->getOperand(1).getMBB(); if (SecLastOpcodeHasNot) Cond.push_back(MachineOperand::CreateImm(0)); @@ -285,7 +285,7 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, // If the block ends with two Hexagon:JMPs, handle it. The second one is not // executed, so remove it. - if (SecLastOpcode == Hexagon::JMP && LastOpcode == Hexagon::JMP) { + if (SecLastOpcode == Hexagon::J2_jump && LastOpcode == Hexagon::J2_jump) { TBB = SecondLastInst->getOperand(0).getMBB(); I = LastInst; if (AllowModify) @@ -295,7 +295,7 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, // If the block ends with an ENDLOOP, and JMP, handle it. if (SecLastOpcode == Hexagon::ENDLOOP0 && - LastOpcode == Hexagon::JMP) { + LastOpcode == Hexagon::J2_jump) { TBB = SecondLastInst->getOperand(0).getMBB(); Cond.push_back(SecondLastInst->getOperand(0)); FBB = LastInst->getOperand(0).getMBB(); @@ -308,9 +308,9 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, unsigned HexagonInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { - int BOpc = Hexagon::JMP; - int BccOpc = Hexagon::JMP_t; - int BccOpcNot = Hexagon::JMP_f; + int BOpc = Hexagon::J2_jump; + int BccOpc = Hexagon::J2_jumpt; + int BccOpcNot = Hexagon::J2_jumpf; MachineBasicBlock::iterator I = MBB.end(); if (I == MBB.begin()) return 0; @@ -346,15 +346,15 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI, // Set mask and the first source register. switch (Opc) { - case Hexagon::CMPEHexagon4rr: - case Hexagon::CMPEQri: - case Hexagon::CMPEQrr: - case Hexagon::CMPGT64rr: - case Hexagon::CMPGTU64rr: - case Hexagon::CMPGTUri: - case Hexagon::CMPGTUrr: - case Hexagon::CMPGTri: - case Hexagon::CMPGTrr: + case Hexagon::C2_cmpeqp: + case Hexagon::C2_cmpeqi: + case Hexagon::C2_cmpeq: + case Hexagon::C2_cmpgtp: + case Hexagon::C2_cmpgtup: + case Hexagon::C2_cmpgtui: + case Hexagon::C2_cmpgtu: + case Hexagon::C2_cmpgti: + case Hexagon::C2_cmpgt: SrcReg = MI->getOperand(1).getReg(); Mask = ~0; break; @@ -380,12 +380,12 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI, // Set the value/second source register. switch (Opc) { - case Hexagon::CMPEHexagon4rr: - case Hexagon::CMPEQrr: - case Hexagon::CMPGT64rr: - case Hexagon::CMPGTU64rr: - case Hexagon::CMPGTUrr: - case Hexagon::CMPGTrr: + case Hexagon::C2_cmpeqp: + case Hexagon::C2_cmpeq: + case Hexagon::C2_cmpgtp: + case Hexagon::C2_cmpgtup: + case Hexagon::C2_cmpgtu: + case Hexagon::C2_cmpgt: case Hexagon::CMPbEQrr_sbsb_V4: case Hexagon::CMPbEQrr_ubub_V4: case Hexagon::CMPbGTUrr_V4: @@ -397,9 +397,9 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI, SrcReg2 = MI->getOperand(2).getReg(); return true; - case Hexagon::CMPEQri: - case Hexagon::CMPGTUri: - case Hexagon::CMPGTri: + case Hexagon::C2_cmpeqi: + case Hexagon::C2_cmpgtui: + case Hexagon::C2_cmpgti: case Hexagon::CMPbEQri_V4: case Hexagon::CMPbGTUri_V4: case Hexagon::CMPhEQri_V4: @@ -418,16 +418,16 @@ void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, unsigned DestReg, unsigned SrcReg, bool KillSrc) const { if (Hexagon::IntRegsRegClass.contains(SrcReg, DestReg)) { - BuildMI(MBB, I, DL, get(Hexagon::TFR), DestReg).addReg(SrcReg); + BuildMI(MBB, I, DL, get(Hexagon::A2_tfr), DestReg).addReg(SrcReg); return; } if (Hexagon::DoubleRegsRegClass.contains(SrcReg, DestReg)) { - BuildMI(MBB, I, DL, get(Hexagon::TFR64), DestReg).addReg(SrcReg); + BuildMI(MBB, I, DL, get(Hexagon::A2_tfrp), DestReg).addReg(SrcReg); return; } if (Hexagon::PredRegsRegClass.contains(SrcReg, DestReg)) { // Map Pd = Ps to Pd = or(Ps, Ps). - BuildMI(MBB, I, DL, get(Hexagon::OR_pp), + BuildMI(MBB, I, DL, get(Hexagon::C2_or), DestReg).addReg(SrcReg).addReg(SrcReg); return; } @@ -436,31 +436,31 @@ void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, // We can have an overlap between single and double reg: r1:0 = r0. if(SrcReg == RI.getSubReg(DestReg, Hexagon::subreg_loreg)) { // r1:0 = r0 - BuildMI(MBB, I, DL, get(Hexagon::TFRI), (RI.getSubReg(DestReg, + BuildMI(MBB, I, DL, get(Hexagon::A2_tfrsi), (RI.getSubReg(DestReg, Hexagon::subreg_hireg))).addImm(0); } else { // r1:0 = r1 or no overlap. - BuildMI(MBB, I, DL, get(Hexagon::TFR), (RI.getSubReg(DestReg, + BuildMI(MBB, I, DL, get(Hexagon::A2_tfr), (RI.getSubReg(DestReg, Hexagon::subreg_loreg))).addReg(SrcReg); - BuildMI(MBB, I, DL, get(Hexagon::TFRI), (RI.getSubReg(DestReg, + BuildMI(MBB, I, DL, get(Hexagon::A2_tfrsi), (RI.getSubReg(DestReg, Hexagon::subreg_hireg))).addImm(0); } return; } - if (Hexagon::CRRegsRegClass.contains(DestReg) && + if (Hexagon::CtrRegsRegClass.contains(DestReg) && Hexagon::IntRegsRegClass.contains(SrcReg)) { - BuildMI(MBB, I, DL, get(Hexagon::TFCR), DestReg).addReg(SrcReg); + BuildMI(MBB, I, DL, get(Hexagon::A2_tfrrcr), DestReg).addReg(SrcReg); return; } if (Hexagon::PredRegsRegClass.contains(SrcReg) && Hexagon::IntRegsRegClass.contains(DestReg)) { - BuildMI(MBB, I, DL, get(Hexagon::TFR_RsPd), DestReg). + BuildMI(MBB, I, DL, get(Hexagon::C2_tfrpr), DestReg). addReg(SrcReg, getKillRegState(KillSrc)); return; } if (Hexagon::IntRegsRegClass.contains(SrcReg) && Hexagon::PredRegsRegClass.contains(DestReg)) { - BuildMI(MBB, I, DL, get(Hexagon::TFR_PdRs), DestReg). + BuildMI(MBB, I, DL, get(Hexagon::C2_tfrrp), DestReg). addReg(SrcReg, getKillRegState(KillSrc)); return; } @@ -488,11 +488,11 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Align); if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) { - BuildMI(MBB, I, DL, get(Hexagon::STriw)) + BuildMI(MBB, I, DL, get(Hexagon::S2_storeri_io)) .addFrameIndex(FI).addImm(0) .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); } else if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC)) { - BuildMI(MBB, I, DL, get(Hexagon::STrid)) + BuildMI(MBB, I, DL, get(Hexagon::S2_storerd_io)) .addFrameIndex(FI).addImm(0) .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); } else if (Hexagon::PredRegsRegClass.hasSubClassEq(RC)) { @@ -533,10 +533,10 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MFI.getObjectSize(FI), Align); if (RC == &Hexagon::IntRegsRegClass) { - BuildMI(MBB, I, DL, get(Hexagon::LDriw), DestReg) + BuildMI(MBB, I, DL, get(Hexagon::L2_loadri_io), DestReg) .addFrameIndex(FI).addImm(0).addMemOperand(MMO); } else if (RC == &Hexagon::DoubleRegsRegClass) { - BuildMI(MBB, I, DL, get(Hexagon::LDrid), DestReg) + BuildMI(MBB, I, DL, get(Hexagon::L2_loadrd_io), DestReg) .addFrameIndex(FI).addImm(0).addMemOperand(MMO); } else if (RC == &Hexagon::PredRegsRegClass) { BuildMI(MBB, I, DL, get(Hexagon::LDriw_pred), DestReg) @@ -648,77 +648,67 @@ bool HexagonInstrInfo::isPredicable(MachineInstr *MI) const { const int Opc = MI->getOpcode(); switch(Opc) { - case Hexagon::TFRI: + case Hexagon::A2_tfrsi: return isInt<12>(MI->getOperand(1).getImm()); - case Hexagon::STrid: - case Hexagon::STrid_indexed: + case Hexagon::S2_storerd_io: return isShiftedUInt<6,3>(MI->getOperand(1).getImm()); - case Hexagon::STriw: - case Hexagon::STriw_indexed: - case Hexagon::STriw_nv_V4: + case Hexagon::S2_storeri_io: + case Hexagon::S2_storerinew_io: return isShiftedUInt<6,2>(MI->getOperand(1).getImm()); - case Hexagon::STrih: - case Hexagon::STrih_indexed: - case Hexagon::STrih_nv_V4: + case Hexagon::S2_storerh_io: + case Hexagon::S2_storerhnew_io: return isShiftedUInt<6,1>(MI->getOperand(1).getImm()); - case Hexagon::STrib: - case Hexagon::STrib_indexed: - case Hexagon::STrib_nv_V4: + case Hexagon::S2_storerb_io: + case Hexagon::S2_storerbnew_io: return isUInt<6>(MI->getOperand(1).getImm()); - case Hexagon::LDrid: - case Hexagon::LDrid_indexed: + case Hexagon::L2_loadrd_io: return isShiftedUInt<6,3>(MI->getOperand(2).getImm()); - case Hexagon::LDriw: - case Hexagon::LDriw_indexed: + case Hexagon::L2_loadri_io: return isShiftedUInt<6,2>(MI->getOperand(2).getImm()); - case Hexagon::LDrih: - case Hexagon::LDriuh: - case Hexagon::LDrih_indexed: - case Hexagon::LDriuh_indexed: + case Hexagon::L2_loadrh_io: + case Hexagon::L2_loadruh_io: return isShiftedUInt<6,1>(MI->getOperand(2).getImm()); - case Hexagon::LDrib: - case Hexagon::LDriub: - case Hexagon::LDrib_indexed: - case Hexagon::LDriub_indexed: + case Hexagon::L2_loadrb_io: + case Hexagon::L2_loadrub_io: return isUInt<6>(MI->getOperand(2).getImm()); - case Hexagon::POST_LDrid: + case Hexagon::L2_loadrd_pi: return isShiftedInt<4,3>(MI->getOperand(3).getImm()); - case Hexagon::POST_LDriw: + case Hexagon::L2_loadri_pi: return isShiftedInt<4,2>(MI->getOperand(3).getImm()); - case Hexagon::POST_LDrih: - case Hexagon::POST_LDriuh: + case Hexagon::L2_loadrh_pi: + case Hexagon::L2_loadruh_pi: return isShiftedInt<4,1>(MI->getOperand(3).getImm()); - case Hexagon::POST_LDrib: - case Hexagon::POST_LDriub: + case Hexagon::L2_loadrb_pi: + case Hexagon::L2_loadrub_pi: return isInt<4>(MI->getOperand(3).getImm()); - case Hexagon::STrib_imm_V4: - case Hexagon::STrih_imm_V4: - case Hexagon::STriw_imm_V4: + case Hexagon::S4_storeirb_io: + case Hexagon::S4_storeirh_io: + case Hexagon::S4_storeiri_io: return (isUInt<6>(MI->getOperand(1).getImm()) && isInt<6>(MI->getOperand(2).getImm())); case Hexagon::ADD_ri: return isInt<8>(MI->getOperand(2).getImm()); - case Hexagon::ASLH: - case Hexagon::ASRH: - case Hexagon::SXTB: - case Hexagon::SXTH: - case Hexagon::ZXTB: - case Hexagon::ZXTH: + case Hexagon::A2_aslh: + case Hexagon::A2_asrh: + case Hexagon::A2_sxtb: + case Hexagon::A2_sxth: + case Hexagon::A2_zxtb: + case Hexagon::A2_zxth: return Subtarget.hasV4TOps(); } @@ -739,16 +729,16 @@ unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { switch(Opc) { default: llvm_unreachable("Unexpected predicated instruction"); - case Hexagon::COMBINE_rr_cPt: - return Hexagon::COMBINE_rr_cNotPt; - case Hexagon::COMBINE_rr_cNotPt: - return Hexagon::COMBINE_rr_cPt; + case Hexagon::C2_ccombinewt: + return Hexagon::C2_ccombinewf; + case Hexagon::C2_ccombinewf: + return Hexagon::C2_ccombinewt; // Dealloc_return. - case Hexagon::DEALLOC_RET_cPt_V4: - return Hexagon::DEALLOC_RET_cNotPt_V4; - case Hexagon::DEALLOC_RET_cNotPt_V4: - return Hexagon::DEALLOC_RET_cPt_V4; + case Hexagon::L4_return_t: + return Hexagon::L4_return_f; + case Hexagon::L4_return_f: + return Hexagon::L4_return_t; } } @@ -780,22 +770,22 @@ getMatchingCondBranchOpcode(int Opc, bool invertPredicate) const { case Hexagon::TFRI_f: return !invertPredicate ? Hexagon::TFRI_cPt_f : Hexagon::TFRI_cNotPt_f; - case Hexagon::COMBINE_rr: - return !invertPredicate ? Hexagon::COMBINE_rr_cPt : - Hexagon::COMBINE_rr_cNotPt; + case Hexagon::A2_combinew: + return !invertPredicate ? Hexagon::C2_ccombinewt : + Hexagon::C2_ccombinewf; // Word. case Hexagon::STriw_f: - return !invertPredicate ? Hexagon::STriw_cPt : - Hexagon::STriw_cNotPt; + return !invertPredicate ? Hexagon::S2_pstorerit_io: + Hexagon::S2_pstorerif_io; case Hexagon::STriw_indexed_f: - return !invertPredicate ? Hexagon::STriw_indexed_cPt : - Hexagon::STriw_indexed_cNotPt; + return !invertPredicate ? Hexagon::S2_pstorerit_io: + Hexagon::S2_pstorerif_io; // DEALLOC_RETURN. - case Hexagon::DEALLOC_RET_V4: - return !invertPredicate ? Hexagon::DEALLOC_RET_cPt_V4 : - Hexagon::DEALLOC_RET_cNotPt_V4; + case Hexagon::L4_return: + return !invertPredicate ? Hexagon::L4_return_t: + Hexagon::L4_return_f; } llvm_unreachable("Unexpected predicable instruction"); } @@ -901,7 +891,7 @@ PredicateInstruction(MachineInstr *MI, continue; } else { - assert(false && "Unexpected operand type"); + llvm_unreachable("Unexpected operand type"); } } } @@ -1082,13 +1072,13 @@ isProfitableToDupForIfCvt(MachineBasicBlock &MBB,unsigned NumInstrs, bool HexagonInstrInfo::isDeallocRet(const MachineInstr *MI) const { switch (MI->getOpcode()) { default: return false; - case Hexagon::DEALLOC_RET_V4 : - case Hexagon::DEALLOC_RET_cPt_V4 : - case Hexagon::DEALLOC_RET_cNotPt_V4 : - case Hexagon::DEALLOC_RET_cdnPnt_V4 : - case Hexagon::DEALLOC_RET_cNotdnPnt_V4 : - case Hexagon::DEALLOC_RET_cdnPt_V4 : - case Hexagon::DEALLOC_RET_cNotdnPt_V4 : + case Hexagon::L4_return: + case Hexagon::L4_return_t: + case Hexagon::L4_return_f: + case Hexagon::L4_return_tnew_pnt: + case Hexagon::L4_return_fnew_pnt: + case Hexagon::L4_return_tnew_pt: + case Hexagon::L4_return_fnew_pt: return true; } } @@ -1107,33 +1097,29 @@ isValidOffset(const int Opcode, const int Offset) const { switch(Opcode) { - case Hexagon::LDriw: - case Hexagon::LDriw_indexed: + case Hexagon::L2_loadri_io: case Hexagon::LDriw_f: - case Hexagon::STriw_indexed: - case Hexagon::STriw: + case Hexagon::S2_storeri_io: case Hexagon::STriw_f: return (Offset >= Hexagon_MEMW_OFFSET_MIN) && (Offset <= Hexagon_MEMW_OFFSET_MAX); - case Hexagon::LDrid: - case Hexagon::LDrid_indexed: + case Hexagon::L2_loadrd_io: case Hexagon::LDrid_f: - case Hexagon::STrid: - case Hexagon::STrid_indexed: + case Hexagon::S2_storerd_io: case Hexagon::STrid_f: return (Offset >= Hexagon_MEMD_OFFSET_MIN) && (Offset <= Hexagon_MEMD_OFFSET_MAX); - case Hexagon::LDrih: - case Hexagon::LDriuh: - case Hexagon::STrih: + case Hexagon::L2_loadrh_io: + case Hexagon::L2_loadruh_io: + case Hexagon::S2_storerh_io: return (Offset >= Hexagon_MEMH_OFFSET_MIN) && (Offset <= Hexagon_MEMH_OFFSET_MAX); - case Hexagon::LDrib: - case Hexagon::STrib: - case Hexagon::LDriub: + case Hexagon::L2_loadrb_io: + case Hexagon::S2_storerb_io: + case Hexagon::L2_loadrub_io: return (Offset >= Hexagon_MEMB_OFFSET_MIN) && (Offset <= Hexagon_MEMB_OFFSET_MAX); @@ -1142,28 +1128,28 @@ isValidOffset(const int Opcode, const int Offset) const { return (Offset >= Hexagon_ADDI_OFFSET_MIN) && (Offset <= Hexagon_ADDI_OFFSET_MAX); - case Hexagon::MemOPw_ADDi_V4 : - case Hexagon::MemOPw_SUBi_V4 : - case Hexagon::MemOPw_ADDr_V4 : - case Hexagon::MemOPw_SUBr_V4 : - case Hexagon::MemOPw_ANDr_V4 : - case Hexagon::MemOPw_ORr_V4 : + case Hexagon::L4_iadd_memopw_io: + case Hexagon::L4_isub_memopw_io: + case Hexagon::L4_add_memopw_io: + case Hexagon::L4_sub_memopw_io: + case Hexagon::L4_and_memopw_io: + case Hexagon::L4_or_memopw_io: return (0 <= Offset && Offset <= 255); - case Hexagon::MemOPh_ADDi_V4 : - case Hexagon::MemOPh_SUBi_V4 : - case Hexagon::MemOPh_ADDr_V4 : - case Hexagon::MemOPh_SUBr_V4 : - case Hexagon::MemOPh_ANDr_V4 : - case Hexagon::MemOPh_ORr_V4 : + case Hexagon::L4_iadd_memoph_io: + case Hexagon::L4_isub_memoph_io: + case Hexagon::L4_add_memoph_io: + case Hexagon::L4_sub_memoph_io: + case Hexagon::L4_and_memoph_io: + case Hexagon::L4_or_memoph_io: return (0 <= Offset && Offset <= 127); - case Hexagon::MemOPb_ADDi_V4 : - case Hexagon::MemOPb_SUBi_V4 : - case Hexagon::MemOPb_ADDr_V4 : - case Hexagon::MemOPb_SUBr_V4 : - case Hexagon::MemOPb_ANDr_V4 : - case Hexagon::MemOPb_ORr_V4 : + case Hexagon::L4_iadd_memopb_io: + case Hexagon::L4_isub_memopb_io: + case Hexagon::L4_add_memopb_io: + case Hexagon::L4_sub_memopb_io: + case Hexagon::L4_and_memopb_io: + case Hexagon::L4_or_memopb_io: return (0 <= Offset && Offset <= 63); // LDri_pred and STriw_pred are pseudo operations, so it has to take offset of @@ -1172,7 +1158,7 @@ isValidOffset(const int Opcode, const int Offset) const { case Hexagon::LDriw_pred: return true; - case Hexagon::LOOP0_i: + case Hexagon::J2_loop0i: return isUInt<10>(Offset); // INLINEASM is very special. @@ -1220,31 +1206,31 @@ isMemOp(const MachineInstr *MI) const { switch (MI->getOpcode()) { - default: return false; - case Hexagon::MemOPw_ADDi_V4 : - case Hexagon::MemOPw_SUBi_V4 : - case Hexagon::MemOPw_ADDr_V4 : - case Hexagon::MemOPw_SUBr_V4 : - case Hexagon::MemOPw_ANDr_V4 : - case Hexagon::MemOPw_ORr_V4 : - case Hexagon::MemOPh_ADDi_V4 : - case Hexagon::MemOPh_SUBi_V4 : - case Hexagon::MemOPh_ADDr_V4 : - case Hexagon::MemOPh_SUBr_V4 : - case Hexagon::MemOPh_ANDr_V4 : - case Hexagon::MemOPh_ORr_V4 : - case Hexagon::MemOPb_ADDi_V4 : - case Hexagon::MemOPb_SUBi_V4 : - case Hexagon::MemOPb_ADDr_V4 : - case Hexagon::MemOPb_SUBr_V4 : - case Hexagon::MemOPb_ANDr_V4 : - case Hexagon::MemOPb_ORr_V4 : - case Hexagon::MemOPb_SETBITi_V4: - case Hexagon::MemOPh_SETBITi_V4: - case Hexagon::MemOPw_SETBITi_V4: - case Hexagon::MemOPb_CLRBITi_V4: - case Hexagon::MemOPh_CLRBITi_V4: - case Hexagon::MemOPw_CLRBITi_V4: + default: return false; + case Hexagon::L4_iadd_memopw_io: + case Hexagon::L4_isub_memopw_io: + case Hexagon::L4_add_memopw_io: + case Hexagon::L4_sub_memopw_io: + case Hexagon::L4_and_memopw_io: + case Hexagon::L4_or_memopw_io: + case Hexagon::L4_iadd_memoph_io: + case Hexagon::L4_isub_memoph_io: + case Hexagon::L4_add_memoph_io: + case Hexagon::L4_sub_memoph_io: + case Hexagon::L4_and_memoph_io: + case Hexagon::L4_or_memoph_io: + case Hexagon::L4_iadd_memopb_io: + case Hexagon::L4_isub_memopb_io: + case Hexagon::L4_add_memopb_io: + case Hexagon::L4_sub_memopb_io: + case Hexagon::L4_and_memopb_io: + case Hexagon::L4_or_memopb_io: + case Hexagon::L4_ior_memopb_io: + case Hexagon::L4_ior_memoph_io: + case Hexagon::L4_ior_memopw_io: + case Hexagon::L4_iand_memopb_io: + case Hexagon::L4_iand_memoph_io: + case Hexagon::L4_iand_memopw_io: return true; } return false; @@ -1264,12 +1250,12 @@ isSpillPredRegOp(const MachineInstr *MI) const { bool HexagonInstrInfo::isNewValueJumpCandidate(const MachineInstr *MI) const { switch (MI->getOpcode()) { default: return false; - case Hexagon::CMPEQrr: - case Hexagon::CMPEQri: - case Hexagon::CMPGTrr: - case Hexagon::CMPGTri: - case Hexagon::CMPGTUrr: - case Hexagon::CMPGTUri: + case Hexagon::C2_cmpeq: + case Hexagon::C2_cmpeqi: + case Hexagon::C2_cmpgt: + case Hexagon::C2_cmpgti: + case Hexagon::C2_cmpgtu: + case Hexagon::C2_cmpgtui: return true; } } @@ -1278,51 +1264,71 @@ bool HexagonInstrInfo:: isConditionalTransfer (const MachineInstr *MI) const { switch (MI->getOpcode()) { default: return false; - case Hexagon::TFR_cPt: - case Hexagon::TFR_cNotPt: - case Hexagon::TFRI_cPt: - case Hexagon::TFRI_cNotPt: - case Hexagon::TFR_cdnPt: - case Hexagon::TFR_cdnNotPt: - case Hexagon::TFRI_cdnPt: - case Hexagon::TFRI_cdnNotPt: + case Hexagon::A2_tfrt: + case Hexagon::A2_tfrf: + case Hexagon::C2_cmoveit: + case Hexagon::C2_cmoveif: + case Hexagon::A2_tfrtnew: + case Hexagon::A2_tfrfnew: + case Hexagon::C2_cmovenewit: + case Hexagon::C2_cmovenewif: return true; } } bool HexagonInstrInfo::isConditionalALU32 (const MachineInstr* MI) const { - const HexagonRegisterInfo& QRI = getRegisterInfo(); switch (MI->getOpcode()) { default: return false; + case Hexagon::A2_paddf: + case Hexagon::A2_paddfnew: + case Hexagon::A2_paddt: + case Hexagon::A2_paddtnew: + case Hexagon::A2_pandf: + case Hexagon::A2_pandfnew: + case Hexagon::A2_pandt: + case Hexagon::A2_pandtnew: + case Hexagon::A4_paslhf: + case Hexagon::A4_paslhfnew: + case Hexagon::A4_paslht: + case Hexagon::A4_paslhtnew: + case Hexagon::A4_pasrhf: + case Hexagon::A4_pasrhfnew: + case Hexagon::A4_pasrht: + case Hexagon::A4_pasrhtnew: + case Hexagon::A2_porf: + case Hexagon::A2_porfnew: + case Hexagon::A2_port: + case Hexagon::A2_portnew: + case Hexagon::A2_psubf: + case Hexagon::A2_psubfnew: + case Hexagon::A2_psubt: + case Hexagon::A2_psubtnew: + case Hexagon::A2_pxorf: + case Hexagon::A2_pxorfnew: + case Hexagon::A2_pxort: + case Hexagon::A2_pxortnew: + case Hexagon::A4_psxthf: + case Hexagon::A4_psxthfnew: + case Hexagon::A4_psxtht: + case Hexagon::A4_psxthtnew: + case Hexagon::A4_psxtbf: + case Hexagon::A4_psxtbfnew: + case Hexagon::A4_psxtbt: + case Hexagon::A4_psxtbtnew: + case Hexagon::A4_pzxtbf: + case Hexagon::A4_pzxtbfnew: + case Hexagon::A4_pzxtbt: + case Hexagon::A4_pzxtbtnew: + case Hexagon::A4_pzxthf: + case Hexagon::A4_pzxthfnew: + case Hexagon::A4_pzxtht: + case Hexagon::A4_pzxthtnew: case Hexagon::ADD_ri_cPt: case Hexagon::ADD_ri_cNotPt: - case Hexagon::ADD_rr_cPt: - case Hexagon::ADD_rr_cNotPt: - case Hexagon::XOR_rr_cPt: - case Hexagon::XOR_rr_cNotPt: - case Hexagon::AND_rr_cPt: - case Hexagon::AND_rr_cNotPt: - case Hexagon::OR_rr_cPt: - case Hexagon::OR_rr_cNotPt: - case Hexagon::SUB_rr_cPt: - case Hexagon::SUB_rr_cNotPt: - case Hexagon::COMBINE_rr_cPt: - case Hexagon::COMBINE_rr_cNotPt: + case Hexagon::C2_ccombinewt: + case Hexagon::C2_ccombinewf: return true; - case Hexagon::ASLH_cPt_V4: - case Hexagon::ASLH_cNotPt_V4: - case Hexagon::ASRH_cPt_V4: - case Hexagon::ASRH_cNotPt_V4: - case Hexagon::SXTB_cPt_V4: - case Hexagon::SXTB_cNotPt_V4: - case Hexagon::SXTH_cPt_V4: - case Hexagon::SXTH_cNotPt_V4: - case Hexagon::ZXTB_cPt_V4: - case Hexagon::ZXTB_cNotPt_V4: - case Hexagon::ZXTH_cPt_V4: - case Hexagon::ZXTH_cNotPt_V4: - return QRI.Subtarget.hasV4TOps(); } } @@ -1332,56 +1338,44 @@ isConditionalLoad (const MachineInstr* MI) const { switch (MI->getOpcode()) { default: return false; - case Hexagon::LDrid_cPt : - case Hexagon::LDrid_cNotPt : - case Hexagon::LDrid_indexed_cPt : - case Hexagon::LDrid_indexed_cNotPt : - case Hexagon::LDriw_cPt : - case Hexagon::LDriw_cNotPt : - case Hexagon::LDriw_indexed_cPt : - case Hexagon::LDriw_indexed_cNotPt : - case Hexagon::LDrih_cPt : - case Hexagon::LDrih_cNotPt : - case Hexagon::LDrih_indexed_cPt : - case Hexagon::LDrih_indexed_cNotPt : - case Hexagon::LDrib_cPt : - case Hexagon::LDrib_cNotPt : - case Hexagon::LDrib_indexed_cPt : - case Hexagon::LDrib_indexed_cNotPt : - case Hexagon::LDriuh_cPt : - case Hexagon::LDriuh_cNotPt : - case Hexagon::LDriuh_indexed_cPt : - case Hexagon::LDriuh_indexed_cNotPt : - case Hexagon::LDriub_cPt : - case Hexagon::LDriub_cNotPt : - case Hexagon::LDriub_indexed_cPt : - case Hexagon::LDriub_indexed_cNotPt : + case Hexagon::L2_ploadrdt_io : + case Hexagon::L2_ploadrdf_io: + case Hexagon::L2_ploadrit_io: + case Hexagon::L2_ploadrif_io: + case Hexagon::L2_ploadrht_io: + case Hexagon::L2_ploadrhf_io: + case Hexagon::L2_ploadrbt_io: + case Hexagon::L2_ploadrbf_io: + case Hexagon::L2_ploadruht_io: + case Hexagon::L2_ploadruhf_io: + case Hexagon::L2_ploadrubt_io: + case Hexagon::L2_ploadrubf_io: return true; - case Hexagon::POST_LDrid_cPt : - case Hexagon::POST_LDrid_cNotPt : - case Hexagon::POST_LDriw_cPt : - case Hexagon::POST_LDriw_cNotPt : - case Hexagon::POST_LDrih_cPt : - case Hexagon::POST_LDrih_cNotPt : - case Hexagon::POST_LDrib_cPt : - case Hexagon::POST_LDrib_cNotPt : - case Hexagon::POST_LDriuh_cPt : - case Hexagon::POST_LDriuh_cNotPt : - case Hexagon::POST_LDriub_cPt : - case Hexagon::POST_LDriub_cNotPt : + case Hexagon::L2_ploadrdt_pi: + case Hexagon::L2_ploadrdf_pi: + case Hexagon::L2_ploadrit_pi: + case Hexagon::L2_ploadrif_pi: + case Hexagon::L2_ploadrht_pi: + case Hexagon::L2_ploadrhf_pi: + case Hexagon::L2_ploadrbt_pi: + case Hexagon::L2_ploadrbf_pi: + case Hexagon::L2_ploadruht_pi: + case Hexagon::L2_ploadruhf_pi: + case Hexagon::L2_ploadrubt_pi: + case Hexagon::L2_ploadrubf_pi: return QRI.Subtarget.hasV4TOps(); - case Hexagon::LDrid_indexed_shl_cPt_V4 : - case Hexagon::LDrid_indexed_shl_cNotPt_V4 : - case Hexagon::LDrib_indexed_shl_cPt_V4 : - case Hexagon::LDrib_indexed_shl_cNotPt_V4 : - case Hexagon::LDriub_indexed_shl_cPt_V4 : - case Hexagon::LDriub_indexed_shl_cNotPt_V4 : - case Hexagon::LDrih_indexed_shl_cPt_V4 : - case Hexagon::LDrih_indexed_shl_cNotPt_V4 : - case Hexagon::LDriuh_indexed_shl_cPt_V4 : - case Hexagon::LDriuh_indexed_shl_cNotPt_V4 : - case Hexagon::LDriw_indexed_shl_cPt_V4 : - case Hexagon::LDriw_indexed_shl_cNotPt_V4 : + case Hexagon::L4_ploadrdt_rr: + case Hexagon::L4_ploadrdf_rr: + case Hexagon::L4_ploadrbt_rr: + case Hexagon::L4_ploadrbf_rr: + case Hexagon::L4_ploadrubt_rr: + case Hexagon::L4_ploadrubf_rr: + case Hexagon::L4_ploadrht_rr: + case Hexagon::L4_ploadrhf_rr: + case Hexagon::L4_ploadruht_rr: + case Hexagon::L4_ploadruhf_rr: + case Hexagon::L4_ploadrit_rr: + case Hexagon::L4_ploadrif_rr: return QRI.Subtarget.hasV4TOps(); } } @@ -1426,50 +1420,47 @@ isConditionalStore (const MachineInstr* MI) const { switch (MI->getOpcode()) { default: return false; - case Hexagon::STrib_imm_cPt_V4 : - case Hexagon::STrib_imm_cNotPt_V4 : - case Hexagon::STrib_indexed_shl_cPt_V4 : - case Hexagon::STrib_indexed_shl_cNotPt_V4 : - case Hexagon::STrib_cPt : - case Hexagon::STrib_cNotPt : - case Hexagon::POST_STbri_cPt : - case Hexagon::POST_STbri_cNotPt : - case Hexagon::STrid_indexed_cPt : - case Hexagon::STrid_indexed_cNotPt : - case Hexagon::STrid_indexed_shl_cPt_V4 : - case Hexagon::POST_STdri_cPt : - case Hexagon::POST_STdri_cNotPt : - case Hexagon::STrih_cPt : - case Hexagon::STrih_cNotPt : - case Hexagon::STrih_indexed_cPt : - case Hexagon::STrih_indexed_cNotPt : - case Hexagon::STrih_imm_cPt_V4 : - case Hexagon::STrih_imm_cNotPt_V4 : - case Hexagon::STrih_indexed_shl_cPt_V4 : - case Hexagon::STrih_indexed_shl_cNotPt_V4 : - case Hexagon::POST_SThri_cPt : - case Hexagon::POST_SThri_cNotPt : - case Hexagon::STriw_cPt : - case Hexagon::STriw_cNotPt : - case Hexagon::STriw_indexed_cPt : - case Hexagon::STriw_indexed_cNotPt : - case Hexagon::STriw_imm_cPt_V4 : - case Hexagon::STriw_imm_cNotPt_V4 : - case Hexagon::STriw_indexed_shl_cPt_V4 : - case Hexagon::STriw_indexed_shl_cNotPt_V4 : - case Hexagon::POST_STwri_cPt : - case Hexagon::POST_STwri_cNotPt : + case Hexagon::S4_storeirbt_io: + case Hexagon::S4_storeirbf_io: + case Hexagon::S4_pstorerbt_rr: + case Hexagon::S4_pstorerbf_rr: + case Hexagon::S2_pstorerbt_io: + case Hexagon::S2_pstorerbf_io: + case Hexagon::S2_pstorerbt_pi: + case Hexagon::S2_pstorerbf_pi: + case Hexagon::S2_pstorerdt_io: + case Hexagon::S2_pstorerdf_io: + case Hexagon::S4_pstorerdt_rr: + case Hexagon::S4_pstorerdf_rr: + case Hexagon::S2_pstorerdt_pi: + case Hexagon::S2_pstorerdf_pi: + case Hexagon::S2_pstorerht_io: + case Hexagon::S2_pstorerhf_io: + case Hexagon::S4_storeirht_io: + case Hexagon::S4_storeirhf_io: + case Hexagon::S4_pstorerht_rr: + case Hexagon::S4_pstorerhf_rr: + case Hexagon::S2_pstorerht_pi: + case Hexagon::S2_pstorerhf_pi: + case Hexagon::S2_pstorerit_io: + case Hexagon::S2_pstorerif_io: + case Hexagon::S4_storeirit_io: + case Hexagon::S4_storeirif_io: + case Hexagon::S4_pstorerit_rr: + case Hexagon::S4_pstorerif_rr: + case Hexagon::S2_pstorerit_pi: + case Hexagon::S2_pstorerif_pi: return QRI.Subtarget.hasV4TOps(); // V4 global address store before promoting to dot new. - case Hexagon::STd_GP_cPt_V4 : - case Hexagon::STd_GP_cNotPt_V4 : - case Hexagon::STb_GP_cPt_V4 : - case Hexagon::STb_GP_cNotPt_V4 : - case Hexagon::STh_GP_cPt_V4 : - case Hexagon::STh_GP_cNotPt_V4 : - case Hexagon::STw_GP_cPt_V4 : - case Hexagon::STw_GP_cNotPt_V4 : + case Hexagon::S4_pstorerdt_abs: + case Hexagon::S4_pstorerdf_abs: + case Hexagon::S4_pstorerbt_abs: + case Hexagon::S4_pstorerbf_abs: + case Hexagon::S4_pstorerht_abs: + case Hexagon::S4_pstorerhf_abs: + case Hexagon::S4_pstorerit_abs: + case Hexagon::S4_pstorerif_abs: return QRI.Subtarget.hasV4TOps(); // Predicated new value stores (i.e. if (p0) memw(..)=r0.new) are excluded @@ -1565,10 +1556,10 @@ int HexagonInstrInfo::GetDotNewOp(const MachineInstr* MI) const { return Hexagon::STrih_shl_nv_V4; case Hexagon::STriw_f: - return Hexagon::STriw_nv_V4; + return Hexagon::S2_storerinew_io; case Hexagon::STriw_indexed_f: - return Hexagon::STriw_indexed_nv_V4; + return Hexagon::S4_storerinew_rr; case Hexagon::STriw_shl_V4: return Hexagon::STriw_shl_nv_V4; @@ -1589,28 +1580,28 @@ int HexagonInstrInfo::GetDotNewPredOp(MachineInstr *MI, switch (MI->getOpcode()) { default: llvm_unreachable("Unknown .new type"); // Condtional Jumps - case Hexagon::JMP_t: - case Hexagon::JMP_f: + case Hexagon::J2_jumpt: + case Hexagon::J2_jumpf: return getDotNewPredJumpOp(MI, MBPI); - case Hexagon::JMPR_t: - return Hexagon::JMPR_tnew_tV3; + case Hexagon::J2_jumprt: + return Hexagon::J2_jumptnewpt; - case Hexagon::JMPR_f: - return Hexagon::JMPR_fnew_tV3; + case Hexagon::J2_jumprf: + return Hexagon::J2_jumprfnewpt; - case Hexagon::JMPret_t: - return Hexagon::JMPret_tnew_tV3; + case Hexagon::JMPrett: + return Hexagon::J2_jumprtnewpt; - case Hexagon::JMPret_f: - return Hexagon::JMPret_fnew_tV3; + case Hexagon::JMPretf: + return Hexagon::J2_jumprfnewpt; // Conditional combine - case Hexagon::COMBINE_rr_cPt : - return Hexagon::COMBINE_rr_cdnPt; - case Hexagon::COMBINE_rr_cNotPt : - return Hexagon::COMBINE_rr_cdnNotPt; + case Hexagon::C2_ccombinewt: + return Hexagon::C2_ccombinewnewt; + case Hexagon::C2_ccombinewf: + return Hexagon::C2_ccombinewnewf; } } @@ -1636,11 +1627,10 @@ void HexagonInstrInfo::immediateExtend(MachineInstr *MI) const { MO.addTargetFlag(HexagonII::HMOTF_ConstExtended); } -DFAPacketizer *HexagonInstrInfo:: -CreateTargetScheduleState(const TargetMachine *TM, - const ScheduleDAG *DAG) const { - const InstrItineraryData *II = TM->getInstrItineraryData(); - return TM->getSubtarget<HexagonGenSubtargetInfo>().createDFAPacketizer(II); +DFAPacketizer *HexagonInstrInfo::CreateTargetScheduleState( + const TargetSubtargetInfo &STI) const { + const InstrItineraryData *II = STI.getInstrItineraryData(); + return static_cast<const HexagonSubtarget &>(STI).createDFAPacketizer(II); } bool HexagonInstrInfo::isSchedulingBoundary(const MachineInstr *MI, @@ -1728,10 +1718,10 @@ HexagonInstrInfo::getDotNewPredJumpOp(MachineInstr *MI, taken = true; switch (MI->getOpcode()) { - case Hexagon::JMP_t: - return taken ? Hexagon::JMP_tnew_t : Hexagon::JMP_tnew_nt; - case Hexagon::JMP_f: - return taken ? Hexagon::JMP_fnew_t : Hexagon::JMP_fnew_nt; + case Hexagon::J2_jumpt: + return taken ? Hexagon::J2_jumptnewpt : Hexagon::J2_jumptnew; + case Hexagon::J2_jumpf: + return taken ? Hexagon::J2_jumpfnewpt : Hexagon::J2_jumpfnew; default: llvm_unreachable("Unexpected jump instruction."); @@ -1765,7 +1755,7 @@ int HexagonInstrInfo::getMinValue(const MachineInstr *MI) const { & HexagonII::ExtentBitsMask; if (isSigned) // if value is signed - return -1 << (bits - 1); + return -1U << (bits - 1); else return 0; } @@ -1779,9 +1769,9 @@ int HexagonInstrInfo::getMaxValue(const MachineInstr *MI) const { & HexagonII::ExtentBitsMask; if (isSigned) // if value is signed - return ~(-1 << (bits - 1)); + return ~(-1U << (bits - 1)); else - return ~(-1 << bits); + return ~(-1U << bits); } // Returns true if an instruction can be converted into a non-extended @@ -1843,16 +1833,16 @@ short HexagonInstrInfo::getNonExtOpcode (const MachineInstr *MI) const { } bool HexagonInstrInfo::PredOpcodeHasJMP_c(Opcode_t Opcode) const { - return (Opcode == Hexagon::JMP_t) || - (Opcode == Hexagon::JMP_f) || - (Opcode == Hexagon::JMP_tnew_t) || - (Opcode == Hexagon::JMP_fnew_t) || - (Opcode == Hexagon::JMP_tnew_nt) || - (Opcode == Hexagon::JMP_fnew_nt); + return (Opcode == Hexagon::J2_jumpt) || + (Opcode == Hexagon::J2_jumpf) || + (Opcode == Hexagon::J2_jumptnewpt) || + (Opcode == Hexagon::J2_jumpfnewpt) || + (Opcode == Hexagon::J2_jumpt) || + (Opcode == Hexagon::J2_jumpf); } bool HexagonInstrInfo::PredOpcodeHasNot(Opcode_t Opcode) const { - return (Opcode == Hexagon::JMP_f) || - (Opcode == Hexagon::JMP_fnew_t) || - (Opcode == Hexagon::JMP_fnew_nt); + return (Opcode == Hexagon::J2_jumpf) || + (Opcode == Hexagon::J2_jumpfnewpt) || + (Opcode == Hexagon::J2_jumpfnew); } diff --git a/lib/Target/Hexagon/HexagonInstrInfo.h b/lib/Target/Hexagon/HexagonInstrInfo.h index 6b032c95e74a..6acfbec24709 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.h +++ b/lib/Target/Hexagon/HexagonInstrInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HexagonINSTRUCTIONINFO_H -#define HexagonINSTRUCTIONINFO_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONINSTRINFO_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONINSTRINFO_H #include "HexagonRegisterInfo.h" #include "MCTargetDesc/HexagonBaseInfo.h" @@ -148,9 +148,8 @@ public: bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, const BranchProbability &Probability) const override; - DFAPacketizer* - CreateTargetScheduleState(const TargetMachine *TM, - const ScheduleDAG *DAG) const override; + DFAPacketizer * + CreateTargetScheduleState(const TargetSubtargetInfo &STI) const override; bool isSchedulingBoundary(const MachineInstr *MI, const MachineBasicBlock *MBB, diff --git a/lib/Target/Hexagon/HexagonInstrInfo.td b/lib/Target/Hexagon/HexagonInstrInfo.td index 4dcf101ea3ad..7ce65f345cab 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.td +++ b/lib/Target/Hexagon/HexagonInstrInfo.td @@ -14,367 +14,606 @@ include "HexagonInstrFormats.td" include "HexagonOperands.td" +// Pattern fragment that combines the value type and the register class +// into a single parameter. +// The pat frags in the definitions below need to have a named register, +// otherwise i32 will be assumed regardless of the register class. The +// name of the register does not matter. +def I1 : PatLeaf<(i1 PredRegs:$R)>; +def I32 : PatLeaf<(i32 IntRegs:$R)>; +def I64 : PatLeaf<(i64 DoubleRegs:$R)>; +def F32 : PatLeaf<(f32 IntRegs:$R)>; +def F64 : PatLeaf<(f64 DoubleRegs:$R)>; + +// Pattern fragments to extract the low and high subregisters from a +// 64-bit value. +def LoReg: OutPatFrag<(ops node:$Rs), + (EXTRACT_SUBREG (i64 $Rs), subreg_loreg)>; + //===----------------------------------------------------------------------===// -// Multi-class for logical operators. -multiclass ALU32_rr_ri<string OpcStr, SDNode OpNode> { - def rr : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), - [(set (i32 IntRegs:$dst), (OpNode (i32 IntRegs:$b), - (i32 IntRegs:$c)))]>; - def ri : ALU32_ri<(outs IntRegs:$dst), (ins s10Imm:$b, IntRegs:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "(#$b, $c)")), - [(set (i32 IntRegs:$dst), (OpNode s10Imm:$b, - (i32 IntRegs:$c)))]>; -} +//===----------------------------------------------------------------------===// +// Compare +//===----------------------------------------------------------------------===// +let hasSideEffects = 0, isCompare = 1, InputType = "imm", isExtendable = 1, + opExtendable = 2 in +class T_CMP <string mnemonic, bits<2> MajOp, bit isNot, Operand ImmOp> + : ALU32Inst <(outs PredRegs:$dst), + (ins IntRegs:$src1, ImmOp:$src2), + "$dst = "#!if(isNot, "!","")#mnemonic#"($src1, #$src2)", + [], "",ALU32_2op_tc_2early_SLOT0123 >, ImmRegRel { + bits<2> dst; + bits<5> src1; + bits<10> src2; + let CextOpcode = mnemonic; + let opExtentBits = !if(!eq(mnemonic, "cmp.gtu"), 9, 10); + let isExtentSigned = !if(!eq(mnemonic, "cmp.gtu"), 0, 1); + + let IClass = 0b0111; + + let Inst{27-24} = 0b0101; + let Inst{23-22} = MajOp; + let Inst{21} = !if(!eq(mnemonic, "cmp.gtu"), 0, src2{9}); + let Inst{20-16} = src1; + let Inst{13-5} = src2{8-0}; + let Inst{4} = isNot; + let Inst{3-2} = 0b00; + let Inst{1-0} = dst; + } -// Multi-class for compare ops. -let isCompare = 1 in { -multiclass CMP64_rr<string OpcStr, PatFrag OpNode> { - def rr : ALU64_rr<(outs PredRegs:$dst), (ins DoubleRegs:$b, DoubleRegs:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), - [(set (i1 PredRegs:$dst), - (OpNode (i64 DoubleRegs:$b), (i64 DoubleRegs:$c)))]>; -} +def C2_cmpeqi : T_CMP <"cmp.eq", 0b00, 0, s10Ext>; +def C2_cmpgti : T_CMP <"cmp.gt", 0b01, 0, s10Ext>; +def C2_cmpgtui : T_CMP <"cmp.gtu", 0b10, 0, u9Ext>; -multiclass CMP32_rr_ri_s10<string OpcStr, string CextOp, PatFrag OpNode> { - let CextOpcode = CextOp in { - let InputType = "reg" in - def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), - [(set (i1 PredRegs:$dst), - (OpNode (i32 IntRegs:$b), (i32 IntRegs:$c)))]>; +class T_CMP_pat <InstHexagon MI, PatFrag OpNode, PatLeaf ImmPred> + : Pat<(i1 (OpNode (i32 IntRegs:$src1), ImmPred:$src2)), + (MI IntRegs:$src1, ImmPred:$src2)>; - let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, - opExtentBits = 10, InputType = "imm" in - def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s10Ext:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), - [(set (i1 PredRegs:$dst), - (OpNode (i32 IntRegs:$b), s10ExtPred:$c))]>; - } -} +def : T_CMP_pat <C2_cmpeqi, seteq, s10ImmPred>; +def : T_CMP_pat <C2_cmpgti, setgt, s10ImmPred>; +def : T_CMP_pat <C2_cmpgtui, setugt, u9ImmPred>; -multiclass CMP32_rr_ri_u9<string OpcStr, string CextOp, PatFrag OpNode> { - let CextOpcode = CextOp in { - let InputType = "reg" in - def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), - [(set (i1 PredRegs:$dst), - (OpNode (i32 IntRegs:$b), (i32 IntRegs:$c)))]>; +//===----------------------------------------------------------------------===// +// ALU32/ALU + +//===----------------------------------------------------------------------===// +def SDTHexagonI64I32I32 : SDTypeProfile<1, 2, + [SDTCisVT<0, i64>, SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>; - let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, - opExtentBits = 9, InputType = "imm" in - def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, u9Ext:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), - [(set (i1 PredRegs:$dst), - (OpNode (i32 IntRegs:$b), u9ExtPred:$c))]>; - } +def HexagonCOMBINE : SDNode<"HexagonISD::COMBINE", SDTHexagonI64I32I32>; + +let hasSideEffects = 0, hasNewValue = 1, InputType = "reg" in +class T_ALU32_3op<string mnemonic, bits<3> MajOp, bits<3> MinOp, bit OpsRev, + bit IsComm> + : ALU32_rr<(outs IntRegs:$Rd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = "#mnemonic#"($Rs, $Rt)", + [], "", ALU32_3op_tc_1_SLOT0123>, ImmRegRel, PredRel { + let isCommutable = IsComm; + let BaseOpcode = mnemonic#_rr; + let CextOpcode = mnemonic; + + bits<5> Rs; + bits<5> Rt; + bits<5> Rd; + + let IClass = 0b1111; + let Inst{27} = 0b0; + let Inst{26-24} = MajOp; + let Inst{23-21} = MinOp; + let Inst{20-16} = !if(OpsRev,Rt,Rs); + let Inst{12-8} = !if(OpsRev,Rs,Rt); + let Inst{4-0} = Rd; } -multiclass CMP32_ri_s8<string OpcStr, PatFrag OpNode> { -let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8 in - def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s8Ext:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), - [(set (i1 PredRegs:$dst), (OpNode (i32 IntRegs:$b), - s8ExtPred:$c))]>; +let hasSideEffects = 0, hasNewValue = 1 in +class T_ALU32_3op_pred<string mnemonic, bits<3> MajOp, bits<3> MinOp, + bit OpsRev, bit PredNot, bit PredNew> + : ALU32_rr<(outs IntRegs:$Rd), (ins PredRegs:$Pu, IntRegs:$Rs, IntRegs:$Rt), + "if ("#!if(PredNot,"!","")#"$Pu"#!if(PredNew,".new","")#") "# + "$Rd = "#mnemonic#"($Rs, $Rt)", + [], "", ALU32_3op_tc_1_SLOT0123>, ImmRegRel, PredNewRel { + let isPredicated = 1; + let isPredicatedFalse = PredNot; + let isPredicatedNew = PredNew; + let BaseOpcode = mnemonic#_rr; + let CextOpcode = mnemonic; + + bits<2> Pu; + bits<5> Rs; + bits<5> Rt; + bits<5> Rd; + + let IClass = 0b1111; + let Inst{27} = 0b1; + let Inst{26-24} = MajOp; + let Inst{23-21} = MinOp; + let Inst{20-16} = !if(OpsRev,Rt,Rs); + let Inst{13} = PredNew; + let Inst{12-8} = !if(OpsRev,Rs,Rt); + let Inst{7} = PredNot; + let Inst{6-5} = Pu; + let Inst{4-0} = Rd; } + +class T_ALU32_combineh<string Op1, string Op2, bits<3> MajOp, bits<3> MinOp, + bit OpsRev> + : T_ALU32_3op<"", MajOp, MinOp, OpsRev, 0> { + let AsmString = "$Rd = combine($Rs"#Op1#", $Rt"#Op2#")"; } -//===----------------------------------------------------------------------===// -// ALU32/ALU (Instructions with register-register form) -//===----------------------------------------------------------------------===// -def SDTHexagonI64I32I32 : SDTypeProfile<1, 2, - [SDTCisVT<0, i64>, SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>; +let isCodeGenOnly = 0 in { +def A2_combine_hh : T_ALU32_combineh<".h", ".h", 0b011, 0b100, 1>; +def A2_combine_hl : T_ALU32_combineh<".h", ".l", 0b011, 0b101, 1>; +def A2_combine_lh : T_ALU32_combineh<".l", ".h", 0b011, 0b110, 1>; +def A2_combine_ll : T_ALU32_combineh<".l", ".l", 0b011, 0b111, 1>; +} -def HexagonWrapperCombineII : - SDNode<"HexagonISD::WrapperCombineII", SDTHexagonI64I32I32>; +class T_ALU32_3op_sfx<string mnemonic, string suffix, bits<3> MajOp, + bits<3> MinOp, bit OpsRev, bit IsComm> + : T_ALU32_3op<"", MajOp, MinOp, OpsRev, IsComm> { + let AsmString = "$Rd = "#mnemonic#"($Rs, $Rt)"#suffix; +} -def HexagonWrapperCombineRR : - SDNode<"HexagonISD::WrapperCombineRR", SDTHexagonI64I32I32>; +let Defs = [USR_OVF], Itinerary = ALU32_3op_tc_2_SLOT0123, + isCodeGenOnly = 0 in { + def A2_addsat : T_ALU32_3op_sfx<"add", ":sat", 0b110, 0b010, 0, 1>; + def A2_subsat : T_ALU32_3op_sfx<"sub", ":sat", 0b110, 0b110, 1, 0>; +} -multiclass ALU32_Pbase<string mnemonic, RegisterClass RC, bit isNot, - bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : ALU32_rr<(outs RC:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs: $src3), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ", - ") $dst = ")#mnemonic#"($src2, $src3)", - []>; +multiclass T_ALU32_3op_p<string mnemonic, bits<3> MajOp, bits<3> MinOp, + bit OpsRev> { + def t : T_ALU32_3op_pred<mnemonic, MajOp, MinOp, OpsRev, 0, 0>; + def f : T_ALU32_3op_pred<mnemonic, MajOp, MinOp, OpsRev, 1, 0>; + def tnew : T_ALU32_3op_pred<mnemonic, MajOp, MinOp, OpsRev, 0, 1>; + def fnew : T_ALU32_3op_pred<mnemonic, MajOp, MinOp, OpsRev, 1, 1>; } -multiclass ALU32_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ALU32_Pbase<mnemonic, RC, PredNot, 0>; - // Predicate new - defm _cdn#NAME : ALU32_Pbase<mnemonic, RC, PredNot, 1>; - } +multiclass T_ALU32_3op_A2<string mnemonic, bits<3> MajOp, bits<3> MinOp, + bit OpsRev, bit IsComm> { + let isPredicable = 1 in + def A2_#NAME : T_ALU32_3op <mnemonic, MajOp, MinOp, OpsRev, IsComm>; + defm A2_p#NAME : T_ALU32_3op_p<mnemonic, MajOp, MinOp, OpsRev>; } -let InputType = "reg" in -multiclass ALU32_base<string mnemonic, string CextOp, SDNode OpNode> { - let CextOpcode = CextOp, BaseOpcode = CextOp#_rr in { - let isPredicable = 1 in - def NAME : ALU32_rr<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst = "#mnemonic#"($src1, $src2)", - [(set (i32 IntRegs:$dst), (OpNode (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))]>; - - let neverHasSideEffects = 1, isPredicated = 1 in { - defm Pt : ALU32_Pred<mnemonic, IntRegs, 0>; - defm NotPt : ALU32_Pred<mnemonic, IntRegs, 1>; - } - } +let isCodeGenOnly = 0 in { +defm add : T_ALU32_3op_A2<"add", 0b011, 0b000, 0, 1>; +defm and : T_ALU32_3op_A2<"and", 0b001, 0b000, 0, 1>; +defm or : T_ALU32_3op_A2<"or", 0b001, 0b001, 0, 1>; +defm sub : T_ALU32_3op_A2<"sub", 0b011, 0b001, 1, 0>; +defm xor : T_ALU32_3op_A2<"xor", 0b001, 0b011, 0, 1>; } -let isCommutable = 1 in { - defm ADD_rr : ALU32_base<"add", "ADD", add>, ImmRegRel, PredNewRel; - defm AND_rr : ALU32_base<"and", "AND", and>, ImmRegRel, PredNewRel; - defm XOR_rr : ALU32_base<"xor", "XOR", xor>, ImmRegRel, PredNewRel; - defm OR_rr : ALU32_base<"or", "OR", or>, ImmRegRel, PredNewRel; +// Pats for instruction selection. +class BinOp32_pat<SDNode Op, InstHexagon MI, ValueType ResT> + : Pat<(ResT (Op (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))), + (ResT (MI IntRegs:$Rs, IntRegs:$Rt))>; + +def: BinOp32_pat<add, A2_add, i32>; +def: BinOp32_pat<and, A2_and, i32>; +def: BinOp32_pat<or, A2_or, i32>; +def: BinOp32_pat<sub, A2_sub, i32>; +def: BinOp32_pat<xor, A2_xor, i32>; + +// A few special cases producing register pairs: +let OutOperandList = (outs DoubleRegs:$Rd), hasNewValue = 0, + isCodeGenOnly = 0 in { + def S2_packhl : T_ALU32_3op <"packhl", 0b101, 0b100, 0, 0>; + + let isPredicable = 1 in + def A2_combinew : T_ALU32_3op <"combine", 0b101, 0b000, 0, 0>; + + // Conditional combinew uses "newt/f" instead of "t/fnew". + def C2_ccombinewt : T_ALU32_3op_pred<"combine", 0b101, 0b000, 0, 0, 0>; + def C2_ccombinewf : T_ALU32_3op_pred<"combine", 0b101, 0b000, 0, 1, 0>; + def C2_ccombinewnewt : T_ALU32_3op_pred<"combine", 0b101, 0b000, 0, 0, 1>; + def C2_ccombinewnewf : T_ALU32_3op_pred<"combine", 0b101, 0b000, 0, 1, 1>; } -defm SUB_rr : ALU32_base<"sub", "SUB", sub>, ImmRegRel, PredNewRel; +let hasSideEffects = 0, hasNewValue = 1, isCompare = 1, InputType = "reg" in +class T_ALU32_3op_cmp<string mnemonic, bits<2> MinOp, bit IsNeg, bit IsComm> + : ALU32_rr<(outs PredRegs:$Pd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Pd = "#mnemonic#"($Rs, $Rt)", + [], "", ALU32_3op_tc_1_SLOT0123>, ImmRegRel { + let CextOpcode = mnemonic; + let isCommutable = IsComm; + bits<5> Rs; + bits<5> Rt; + bits<2> Pd; + + let IClass = 0b1111; + let Inst{27-24} = 0b0010; + let Inst{22-21} = MinOp; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{4} = IsNeg; + let Inst{3-2} = 0b00; + let Inst{1-0} = Pd; +} -// Combines the two integer registers SRC1 and SRC2 into a double register. -let isPredicable = 1 in -class T_Combine : ALU32_rr<(outs DoubleRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst = combine($src1, $src2)", - [(set (i64 DoubleRegs:$dst), - (i64 (HexagonWrapperCombineRR (i32 IntRegs:$src1), - (i32 IntRegs:$src2))))]>; - -multiclass Combine_base { - let BaseOpcode = "combine" in { - def NAME : T_Combine; - let neverHasSideEffects = 1, isPredicated = 1 in { - defm Pt : ALU32_Pred<"combine", DoubleRegs, 0>; - defm NotPt : ALU32_Pred<"combine", DoubleRegs, 1>; - } - } +let Itinerary = ALU32_3op_tc_2early_SLOT0123, isCodeGenOnly = 0 in { + def C2_cmpeq : T_ALU32_3op_cmp< "cmp.eq", 0b00, 0, 1>; + def C2_cmpgt : T_ALU32_3op_cmp< "cmp.gt", 0b10, 0, 0>; + def C2_cmpgtu : T_ALU32_3op_cmp< "cmp.gtu", 0b11, 0, 0>; } -defm COMBINE_rr : Combine_base, PredNewRel; +// Patfrag to convert the usual comparison patfrags (e.g. setlt) to ones +// that reverse the order of the operands. +class RevCmp<PatFrag F> : PatFrag<(ops node:$rhs, node:$lhs), F.Fragment>; + +// Pats for compares. They use PatFrags as operands, not SDNodes, +// since seteq/setgt/etc. are defined as ParFrags. +class T_cmp32_rr_pat<InstHexagon MI, PatFrag Op, ValueType VT> + : Pat<(VT (Op (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))), + (VT (MI IntRegs:$Rs, IntRegs:$Rt))>; + +def: T_cmp32_rr_pat<C2_cmpeq, seteq, i1>; +def: T_cmp32_rr_pat<C2_cmpgt, setgt, i1>; +def: T_cmp32_rr_pat<C2_cmpgtu, setugt, i1>; + +def: T_cmp32_rr_pat<C2_cmpgt, RevCmp<setlt>, i1>; +def: T_cmp32_rr_pat<C2_cmpgtu, RevCmp<setult>, i1>; + +let CextOpcode = "MUX", InputType = "reg", hasNewValue = 1, + isCodeGenOnly = 0 in +def C2_mux: ALU32_rr<(outs IntRegs:$Rd), + (ins PredRegs:$Pu, IntRegs:$Rs, IntRegs:$Rt), + "$Rd = mux($Pu, $Rs, $Rt)", [], "", ALU32_3op_tc_1_SLOT0123>, ImmRegRel { + bits<5> Rd; + bits<2> Pu; + bits<5> Rs; + bits<5> Rt; + + let CextOpcode = "mux"; + let InputType = "reg"; + let hasSideEffects = 0; + let IClass = 0b1111; + + let Inst{27-24} = 0b0100; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{6-5} = Pu; + let Inst{4-0} = Rd; +} -// Combines the two immediates SRC1 and SRC2 into a double register. -class COMBINE_imm<Operand imm1, Operand imm2, PatLeaf pat1, PatLeaf pat2> : - ALU32_ii<(outs DoubleRegs:$dst), (ins imm1:$src1, imm2:$src2), - "$dst = combine(#$src1, #$src2)", - [(set (i64 DoubleRegs:$dst), - (i64 (HexagonWrapperCombineII (i32 pat1:$src1), (i32 pat2:$src2))))]>; +def: Pat<(i32 (select (i1 PredRegs:$Pu), (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))), + (C2_mux PredRegs:$Pu, IntRegs:$Rs, IntRegs:$Rt)>; + +// Combines the two immediates into a double register. +// Increase complexity to make it greater than any complexity of a combine +// that involves a register. + +let isReMaterializable = 1, isMoveImm = 1, isAsCheapAsAMove = 1, + isExtentSigned = 1, isExtendable = 1, opExtentBits = 8, opExtendable = 1, + AddedComplexity = 75, isCodeGenOnly = 0 in +def A2_combineii: ALU32Inst <(outs DoubleRegs:$Rdd), (ins s8Ext:$s8, s8Imm:$S8), + "$Rdd = combine(#$s8, #$S8)", + [(set (i64 DoubleRegs:$Rdd), + (i64 (HexagonCOMBINE(i32 s8ExtPred:$s8), (i32 s8ImmPred:$S8))))]> { + bits<5> Rdd; + bits<8> s8; + bits<8> S8; + + let IClass = 0b0111; + let Inst{27-23} = 0b11000; + let Inst{22-16} = S8{7-1}; + let Inst{13} = S8{0}; + let Inst{12-5} = s8; + let Inst{4-0} = Rdd; + } -let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 8 in -def COMBINE_Ii : COMBINE_imm<s8Ext, s8Imm, s8ExtPred, s8ImmPred>; +//===----------------------------------------------------------------------===// +// Template class for predicated ADD of a reg and an Immediate value. +//===----------------------------------------------------------------------===// +let hasNewValue = 1 in +class T_Addri_Pred <bit PredNot, bit PredNew> + : ALU32_ri <(outs IntRegs:$Rd), + (ins PredRegs:$Pu, IntRegs:$Rs, s8Ext:$s8), + !if(PredNot, "if (!$Pu", "if ($Pu")#!if(PredNew,".new) $Rd = ", + ") $Rd = ")#"add($Rs, #$s8)"> { + bits<5> Rd; + bits<2> Pu; + bits<5> Rs; + bits<8> s8; + + let isPredicatedNew = PredNew; + let IClass = 0b0111; + + let Inst{27-24} = 0b0100; + let Inst{23} = PredNot; + let Inst{22-21} = Pu; + let Inst{20-16} = Rs; + let Inst{13} = PredNew; + let Inst{12-5} = s8; + let Inst{4-0} = Rd; + } //===----------------------------------------------------------------------===// -// ALU32/ALU (ADD with register-immediate form) +// A2_addi: Add a signed immediate to a register. //===----------------------------------------------------------------------===// -multiclass ALU32ri_Pbase<string mnemonic, bit isNot, bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : ALU32_ri<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, s8Ext: $src3), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ", - ") $dst = ")#mnemonic#"($src2, #$src3)", - []>; -} +let hasNewValue = 1 in +class T_Addri <Operand immOp, list<dag> pattern = [] > + : ALU32_ri <(outs IntRegs:$Rd), + (ins IntRegs:$Rs, immOp:$s16), + "$Rd = add($Rs, #$s16)", pattern, + //[(set (i32 IntRegs:$Rd), (add (i32 IntRegs:$Rs), (s16ExtPred:$s16)))], + "", ALU32_ADDI_tc_1_SLOT0123> { + bits<5> Rd; + bits<5> Rs; + bits<16> s16; + + let IClass = 0b1011; + + let Inst{27-21} = s16{15-9}; + let Inst{20-16} = Rs; + let Inst{13-5} = s16{8-0}; + let Inst{4-0} = Rd; + } -multiclass ALU32ri_Pred<string mnemonic, bit PredNot> { +//===----------------------------------------------------------------------===// +// Multiclass for ADD of a register and an immediate value. +//===----------------------------------------------------------------------===// +multiclass Addri_Pred<string mnemonic, bit PredNot> { let isPredicatedFalse = PredNot in { - defm _c#NAME : ALU32ri_Pbase<mnemonic, PredNot, 0>; + def _c#NAME : T_Addri_Pred<PredNot, 0>; // Predicate new - defm _cdn#NAME : ALU32ri_Pbase<mnemonic, PredNot, 1>; + def _cdn#NAME : T_Addri_Pred<PredNot, 1>; } } let isExtendable = 1, InputType = "imm" in -multiclass ALU32ri_base<string mnemonic, string CextOp, SDNode OpNode> { - let CextOpcode = CextOp, BaseOpcode = CextOp#_ri in { +multiclass Addri_base<string mnemonic, SDNode OpNode> { + let CextOpcode = mnemonic, BaseOpcode = mnemonic#_ri in { let opExtendable = 2, isExtentSigned = 1, opExtentBits = 16, isPredicable = 1 in - def NAME : ALU32_ri<(outs IntRegs:$dst), - (ins IntRegs:$src1, s16Ext:$src2), - "$dst = "#mnemonic#"($src1, #$src2)", - [(set (i32 IntRegs:$dst), (OpNode (i32 IntRegs:$src1), - (s16ExtPred:$src2)))]>; + def NAME : T_Addri< s16Ext, // Rd=add(Rs,#s16) + [(set (i32 IntRegs:$Rd), + (add IntRegs:$Rs, s16ExtPred:$s16))]>; let opExtendable = 3, isExtentSigned = 1, opExtentBits = 8, - neverHasSideEffects = 1, isPredicated = 1 in { - defm Pt : ALU32ri_Pred<mnemonic, 0>; - defm NotPt : ALU32ri_Pred<mnemonic, 1>; + hasSideEffects = 0, isPredicated = 1 in { + defm Pt : Addri_Pred<mnemonic, 0>; + defm NotPt : Addri_Pred<mnemonic, 1>; } } } -defm ADD_ri : ALU32ri_base<"add", "ADD", add>, ImmRegRel, PredNewRel; - -let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 10, -CextOpcode = "OR", InputType = "imm" in -def OR_ri : ALU32_ri<(outs IntRegs:$dst), - (ins IntRegs:$src1, s10Ext:$src2), - "$dst = or($src1, #$src2)", - [(set (i32 IntRegs:$dst), (or (i32 IntRegs:$src1), - s10ExtPred:$src2))]>, ImmRegRel; +let isCodeGenOnly = 0 in +defm ADD_ri : Addri_base<"add", add>, ImmRegRel, PredNewRel; +//===----------------------------------------------------------------------===// +// Template class used for the following ALU32 instructions. +// Rd=and(Rs,#s10) +// Rd=or(Rs,#s10) +//===----------------------------------------------------------------------===// let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 10, -InputType = "imm", CextOpcode = "AND" in -def AND_ri : ALU32_ri<(outs IntRegs:$dst), - (ins IntRegs:$src1, s10Ext:$src2), - "$dst = and($src1, #$src2)", - [(set (i32 IntRegs:$dst), (and (i32 IntRegs:$src1), - s10ExtPred:$src2))]>, ImmRegRel; +InputType = "imm", hasNewValue = 1 in +class T_ALU32ri_logical <string mnemonic, SDNode OpNode, bits<2> MinOp> + : ALU32_ri <(outs IntRegs:$Rd), + (ins IntRegs:$Rs, s10Ext:$s10), + "$Rd = "#mnemonic#"($Rs, #$s10)" , + [(set (i32 IntRegs:$Rd), (OpNode (i32 IntRegs:$Rs), s10ExtPred:$s10))]> { + bits<5> Rd; + bits<5> Rs; + bits<10> s10; + let CextOpcode = mnemonic; + + let IClass = 0b0111; + + let Inst{27-24} = 0b0110; + let Inst{23-22} = MinOp; + let Inst{21} = s10{9}; + let Inst{20-16} = Rs; + let Inst{13-5} = s10{8-0}; + let Inst{4-0} = Rd; + } -// Nop. -let neverHasSideEffects = 1 in -def NOP : ALU32_rr<(outs), (ins), - "nop", - []>; +let isCodeGenOnly = 0 in { +def OR_ri : T_ALU32ri_logical<"or", or, 0b10>, ImmRegRel; +def AND_ri : T_ALU32ri_logical<"and", and, 0b00>, ImmRegRel; +} +// Subtract register from immediate // Rd32=sub(#s10,Rs32) let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 10, -CextOpcode = "SUB", InputType = "imm" in -def SUB_ri : ALU32_ri<(outs IntRegs:$dst), - (ins s10Ext:$src1, IntRegs:$src2), - "$dst = sub(#$src1, $src2)", - [(set IntRegs:$dst, (sub s10ExtPred:$src1, IntRegs:$src2))]>, - ImmRegRel; +CextOpcode = "sub", InputType = "imm", hasNewValue = 1, isCodeGenOnly = 0 in +def SUB_ri: ALU32_ri <(outs IntRegs:$Rd), (ins s10Ext:$s10, IntRegs:$Rs), + "$Rd = sub(#$s10, $Rs)" , + [(set IntRegs:$Rd, (sub s10ExtPred:$s10, IntRegs:$Rs))] > , + ImmRegRel { + bits<5> Rd; + bits<10> s10; + bits<5> Rs; + + let IClass = 0b0111; + + let Inst{27-22} = 0b011001; + let Inst{21} = s10{9}; + let Inst{20-16} = Rs; + let Inst{13-5} = s10{8-0}; + let Inst{4-0} = Rd; + } +// Nop. +let hasSideEffects = 0, isCodeGenOnly = 0 in +def A2_nop: ALU32Inst <(outs), (ins), "nop" > { + let IClass = 0b0111; + let Inst{27-24} = 0b1111; +} // Rd = not(Rs) gets mapped to Rd=sub(#-1, Rs). def : Pat<(not (i32 IntRegs:$src1)), (SUB_ri -1, (i32 IntRegs:$src1))>; -// Rd = neg(Rs) gets mapped to Rd=sub(#0, Rs). -// Pattern definition for 'neg' was not necessary. - -multiclass TFR_Pred<bit PredNot> { - let isPredicatedFalse = PredNot in { - def _c#NAME : ALU32_rr<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2), - !if(PredNot, "if (!$src1", "if ($src1")#") $dst = $src2", - []>; - // Predicate new - let isPredicatedNew = 1 in - def _cdn#NAME : ALU32_rr<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2), - !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = $src2", - []>; +let hasSideEffects = 0, hasNewValue = 1 in +class T_tfr16<bit isHi> + : ALU32Inst <(outs IntRegs:$Rx), (ins IntRegs:$src1, u16Imm:$u16), + "$Rx"#!if(isHi, ".h", ".l")#" = #$u16", + [], "$src1 = $Rx" > { + bits<5> Rx; + bits<16> u16; + + let IClass = 0b0111; + let Inst{27-26} = 0b00; + let Inst{25-24} = !if(isHi, 0b10, 0b01); + let Inst{23-22} = u16{15-14}; + let Inst{21} = 0b1; + let Inst{20-16} = Rx; + let Inst{13-0} = u16{13-0}; } -} - -let InputType = "reg", neverHasSideEffects = 1 in -multiclass TFR_base<string CextOp> { - let CextOpcode = CextOp, BaseOpcode = CextOp in { - let isPredicable = 1 in - def NAME : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = $src1", - []>; - let isPredicated = 1 in { - defm Pt : TFR_Pred<0>; - defm NotPt : TFR_Pred<1>; - } - } +let isCodeGenOnly = 0 in { +def A2_tfril: T_tfr16<0>; +def A2_tfrih: T_tfr16<1>; } -class T_TFR64_Pred<bit PredNot, bit isPredNew> - : ALU32_rr<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, DoubleRegs:$src2), - !if(PredNot, "if (!$src1", "if ($src1")# - !if(isPredNew, ".new) ", ") ")#"$dst = $src2", []> -{ +// Conditional transfer is an alias to conditional "Rd = add(Rs, #0)". +let isPredicated = 1, hasNewValue = 1, opNewValue = 0 in +class T_tfr_pred<bit isPredNot, bit isPredNew> + : ALU32Inst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ("#!if(isPredNot, "!", "")# + "$src1"#!if(isPredNew, ".new", "")# + ") $dst = $src2"> { bits<5> dst; bits<2> src1; bits<5> src2; - let IClass = 0b1111; - let Inst{27-24} = 0b1101; + let isPredicatedFalse = isPredNot; + let isPredicatedNew = isPredNew; + let IClass = 0b0111; + + let Inst{27-24} = 0b0100; + let Inst{23} = isPredNot; let Inst{13} = isPredNew; - let Inst{7} = PredNot; + let Inst{12-5} = 0; let Inst{4-0} = dst; - let Inst{6-5} = src1; - let Inst{20-17} = src2{4-1}; - let Inst{16} = 0b1; - let Inst{12-9} = src2{4-1}; - let Inst{8} = 0b0; -} + let Inst{22-21} = src1; + let Inst{20-16} = src2; + } -multiclass TFR64_Pred<bit PredNot> { - let isPredicatedFalse = PredNot in { - def _c#NAME : T_TFR64_Pred<PredNot, 0>; +let isPredicable = 1 in +class T_tfr : ALU32Inst<(outs IntRegs:$dst), (ins IntRegs:$src), + "$dst = $src"> { + bits<5> dst; + bits<5> src; - let isPredicatedNew = 1 in - def _cdn#NAME : T_TFR64_Pred<PredNot, 1>; // Predicate new + let IClass = 0b0111; + + let Inst{27-21} = 0b0000011; + let Inst{20-16} = src; + let Inst{13} = 0b0; + let Inst{4-0} = dst; } -} -let neverHasSideEffects = 1 in -multiclass TFR64_base<string BaseName> { - let BaseOpcode = BaseName in { - let isPredicable = 1 in - def NAME : ALU32Inst <(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1), - "$dst = $src1" > { - bits<5> dst; - bits<5> src1; - - let IClass = 0b1111; - let Inst{27-23} = 0b01010; - let Inst{4-0} = dst; - let Inst{20-17} = src1{4-1}; - let Inst{16} = 0b1; - let Inst{12-9} = src1{4-1}; - let Inst{8} = 0b0; - } +let InputType = "reg", hasNewValue = 1, hasSideEffects = 0 in +multiclass tfr_base<string CextOp> { + let CextOpcode = CextOp, BaseOpcode = CextOp in { + def NAME : T_tfr; - let isPredicated = 1 in { - defm Pt : TFR64_Pred<0>; - defm NotPt : TFR64_Pred<1>; - } + // Predicate + def t : T_tfr_pred<0, 0>; + def f : T_tfr_pred<1, 0>; + // Predicate new + def tnew : T_tfr_pred<0, 1>; + def fnew : T_tfr_pred<1, 1>; } } -multiclass TFRI_Pred<bit PredNot> { - let isMoveImm = 1, isPredicatedFalse = PredNot in { - def _c#NAME : ALU32_ri<(outs IntRegs:$dst), - (ins PredRegs:$src1, s12Ext:$src2), - !if(PredNot, "if (!$src1", "if ($src1")#") $dst = #$src2", - []>; +// Assembler mapped to C2_ccombinew[t|f|newt|newf]. +// Please don't add bits to this instruction as it'll be converted into +// 'combine' before object code emission. +let isPredicated = 1 in +class T_tfrp_pred<bit PredNot, bit PredNew> + : ALU32_rr <(outs DoubleRegs:$dst), + (ins PredRegs:$src1, DoubleRegs:$src2), + "if ("#!if(PredNot, "!", "")#"$src1" + #!if(PredNew, ".new", "")#") $dst = $src2" > { + let isPredicatedFalse = PredNot; + let isPredicatedNew = PredNew; + } +// Assembler mapped to A2_combinew. +// Please don't add bits to this instruction as it'll be converted into +// 'combine' before object code emission. +class T_tfrp : ALU32Inst <(outs DoubleRegs:$dst), + (ins DoubleRegs:$src), + "$dst = $src">; + +let hasSideEffects = 0 in +multiclass TFR64_base<string BaseName> { + let BaseOpcode = BaseName in { + let isPredicable = 1 in + def NAME : T_tfrp; + // Predicate + def t : T_tfrp_pred <0, 0>; + def f : T_tfrp_pred <1, 0>; // Predicate new - let isPredicatedNew = 1 in - def _cdn#NAME : ALU32_rr<(outs IntRegs:$dst), - (ins PredRegs:$src1, s12Ext:$src2), - !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = #$src2", - []>; + def tnew : T_tfrp_pred <0, 1>; + def fnew : T_tfrp_pred <1, 1>; } } -let InputType = "imm", isExtendable = 1, isExtentSigned = 1 in -multiclass TFRI_base<string CextOp> { - let CextOpcode = CextOp, BaseOpcode = CextOp#I in { - let isAsCheapAsAMove = 1 , opExtendable = 1, opExtentBits = 16, - isMoveImm = 1, isPredicable = 1, isReMaterializable = 1 in - def NAME : ALU32_ri<(outs IntRegs:$dst), (ins s16Ext:$src1), - "$dst = #$src1", - [(set (i32 IntRegs:$dst), s16ExtPred:$src1)]>; +let InputType = "imm", isExtendable = 1, isExtentSigned = 1, opExtentBits = 12, + isMoveImm = 1, opExtendable = 2, BaseOpcode = "TFRI", CextOpcode = "TFR", + hasSideEffects = 0, isPredicated = 1, hasNewValue = 1 in +class T_TFRI_Pred<bit PredNot, bit PredNew> + : ALU32_ri<(outs IntRegs:$Rd), (ins PredRegs:$Pu, s12Ext:$s12), + "if ("#!if(PredNot,"!","")#"$Pu"#!if(PredNew,".new","")#") $Rd = #$s12", + [], "", ALU32_2op_tc_1_SLOT0123>, ImmRegRel, PredNewRel { + let isPredicatedFalse = PredNot; + let isPredicatedNew = PredNew; + + bits<5> Rd; + bits<2> Pu; + bits<12> s12; + + let IClass = 0b0111; + let Inst{27-24} = 0b1110; + let Inst{23} = PredNot; + let Inst{22-21} = Pu; + let Inst{20} = 0b0; + let Inst{19-16,12-5} = s12; + let Inst{13} = PredNew; + let Inst{4-0} = Rd; +} - let opExtendable = 2, opExtentBits = 12, neverHasSideEffects = 1, - isPredicated = 1 in { - defm Pt : TFRI_Pred<0>; - defm NotPt : TFRI_Pred<1>; - } - } +let isCodeGenOnly = 0 in { +def C2_cmoveit : T_TFRI_Pred<0, 0>; +def C2_cmoveif : T_TFRI_Pred<1, 0>; +def C2_cmovenewit : T_TFRI_Pred<0, 1>; +def C2_cmovenewif : T_TFRI_Pred<1, 1>; } -defm TFRI : TFRI_base<"TFR">, ImmRegRel, PredNewRel; -defm TFR : TFR_base<"TFR">, ImmRegRel, PredNewRel; -defm TFR64 : TFR64_base<"TFR64">, PredNewRel; +let InputType = "imm", isExtendable = 1, isExtentSigned = 1, + CextOpcode = "TFR", BaseOpcode = "TFRI", hasNewValue = 1, opNewValue = 0, + isAsCheapAsAMove = 1 , opExtendable = 1, opExtentBits = 16, isMoveImm = 1, + isPredicated = 0, isPredicable = 1, isReMaterializable = 1, + isCodeGenOnly = 0 in +def A2_tfrsi : ALU32Inst<(outs IntRegs:$Rd), (ins s16Ext:$s16), "$Rd = #$s16", + [(set (i32 IntRegs:$Rd), s16ExtPred:$s16)], "", ALU32_2op_tc_1_SLOT0123>, + ImmRegRel, PredRel { + bits<5> Rd; + bits<16> s16; + + let IClass = 0b0111; + let Inst{27-24} = 0b1000; + let Inst{23-22,20-16,13-5} = s16; + let Inst{4-0} = Rd; +} + +let isCodeGenOnly = 0 in +defm A2_tfr : tfr_base<"TFR">, ImmRegRel, PredNewRel; +defm A2_tfrp : TFR64_base<"TFR64">, PredNewRel; + +// Assembler mapped +let isReMaterializable = 1, isMoveImm = 1, isAsCheapAsAMove = 1 in +def A2_tfrpi : ALU64_rr<(outs DoubleRegs:$dst), (ins s8Imm64:$src1), + "$dst = #$src1", + [(set (i64 DoubleRegs:$dst), s8Imm64Pred:$src1)]>; + +// TODO: see if this instruction can be deleted.. +let isExtendable = 1, opExtendable = 1, opExtentBits = 6 in +def TFRI64_V4 : ALU64_rr<(outs DoubleRegs:$dst), (ins u6Ext:$src1), + "$dst = #$src1">; -// Transfer control register. -let neverHasSideEffects = 1 in -def TFCR : CRInst<(outs CRRegs:$dst), (ins IntRegs:$src1), - "$dst = $src1", - []>; //===----------------------------------------------------------------------===// // ALU32/ALU - //===----------------------------------------------------------------------===// @@ -383,105 +622,190 @@ def TFCR : CRInst<(outs CRRegs:$dst), (ins IntRegs:$src1), //===----------------------------------------------------------------------===// // ALU32/PERM + //===----------------------------------------------------------------------===// +// Scalar mux register immediate. +let hasSideEffects = 0, isExtentSigned = 1, CextOpcode = "MUX", + InputType = "imm", hasNewValue = 1, isExtendable = 1, opExtentBits = 8 in +class T_MUX1 <bit MajOp, dag ins, string AsmStr> + : ALU32Inst <(outs IntRegs:$Rd), ins, AsmStr>, ImmRegRel { + bits<5> Rd; + bits<2> Pu; + bits<8> s8; + bits<5> Rs; + + let IClass = 0b0111; + let Inst{27-24} = 0b0011; + let Inst{23} = MajOp; + let Inst{22-21} = Pu; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-5} = s8; + let Inst{4-0} = Rd; +} -let neverHasSideEffects = 1 in -def COMBINE_ii : ALU32_ii<(outs DoubleRegs:$dst), - (ins s8Imm:$src1, s8Imm:$src2), - "$dst = combine(#$src1, #$src2)", - []>; +let opExtendable = 2, isCodeGenOnly = 0 in +def C2_muxri : T_MUX1<0b1, (ins PredRegs:$Pu, s8Ext:$s8, IntRegs:$Rs), + "$Rd = mux($Pu, #$s8, $Rs)">; + +let opExtendable = 3, isCodeGenOnly = 0 in +def C2_muxir : T_MUX1<0b0, (ins PredRegs:$Pu, IntRegs:$Rs, s8Ext:$s8), + "$Rd = mux($Pu, $Rs, #$s8)">; + +def : Pat<(i32 (select I1:$Pu, s8ExtPred:$s8, I32:$Rs)), + (C2_muxri I1:$Pu, s8ExtPred:$s8, I32:$Rs)>; + +def : Pat<(i32 (select I1:$Pu, I32:$Rs, s8ExtPred:$s8)), + (C2_muxir I1:$Pu, I32:$Rs, s8ExtPred:$s8)>; + +// C2_muxii: Scalar mux immediates. +let isExtentSigned = 1, hasNewValue = 1, isExtendable = 1, + opExtentBits = 8, opExtendable = 2, isCodeGenOnly = 0 in +def C2_muxii: ALU32Inst <(outs IntRegs:$Rd), + (ins PredRegs:$Pu, s8Ext:$s8, s8Imm:$S8), + "$Rd = mux($Pu, #$s8, #$S8)" , + [(set (i32 IntRegs:$Rd), + (i32 (select I1:$Pu, s8ExtPred:$s8, s8ImmPred:$S8)))] > { + bits<5> Rd; + bits<2> Pu; + bits<8> s8; + bits<8> S8; + + let IClass = 0b0111; + + let Inst{27-25} = 0b101; + let Inst{24-23} = Pu; + let Inst{22-16} = S8{7-1}; + let Inst{13} = S8{0}; + let Inst{12-5} = s8; + let Inst{4-0} = Rd; + } -// Mux. -def VMUX_prr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, - DoubleRegs:$src2, - DoubleRegs:$src3), - "$dst = vmux($src1, $src2, $src3)", - []>; +//===----------------------------------------------------------------------===// +// template class for non-predicated alu32_2op instructions +// - aslh, asrh, sxtb, sxth, zxth +//===----------------------------------------------------------------------===// +let hasNewValue = 1, opNewValue = 0 in +class T_ALU32_2op <string mnemonic, bits<3> minOp> : + ALU32Inst < (outs IntRegs:$Rd), (ins IntRegs:$Rs), + "$Rd = "#mnemonic#"($Rs)", [] > { + bits<5> Rd; + bits<5> Rs; + + let IClass = 0b0111; + + let Inst{27-24} = 0b0000; + let Inst{23-21} = minOp; + let Inst{13} = 0b0; + let Inst{4-0} = Rd; + let Inst{20-16} = Rs; +} + +//===----------------------------------------------------------------------===// +// template class for predicated alu32_2op instructions +// - aslh, asrh, sxtb, sxth, zxtb, zxth +//===----------------------------------------------------------------------===// +let hasSideEffects = 0, validSubTargets = HasV4SubT, + hasNewValue = 1, opNewValue = 0 in +class T_ALU32_2op_Pred <string mnemonic, bits<3> minOp, bit isPredNot, + bit isPredNew > : + ALU32Inst <(outs IntRegs:$Rd), (ins PredRegs:$Pu, IntRegs:$Rs), + !if(isPredNot, "if (!$Pu", "if ($Pu") + #!if(isPredNew, ".new) ",") ")#"$Rd = "#mnemonic#"($Rs)"> { + bits<5> Rd; + bits<2> Pu; + bits<5> Rs; + + let IClass = 0b0111; + + let Inst{27-24} = 0b0000; + let Inst{23-21} = minOp; + let Inst{13} = 0b1; + let Inst{11} = isPredNot; + let Inst{10} = isPredNew; + let Inst{4-0} = Rd; + let Inst{9-8} = Pu; + let Inst{20-16} = Rs; +} -let CextOpcode = "MUX", InputType = "reg" in -def MUX_rr : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, - IntRegs:$src2, IntRegs:$src3), - "$dst = mux($src1, $src2, $src3)", - [(set (i32 IntRegs:$dst), - (i32 (select (i1 PredRegs:$src1), (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))]>, ImmRegRel; - -let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8, -CextOpcode = "MUX", InputType = "imm" in -def MUX_ir : ALU32_ir<(outs IntRegs:$dst), (ins PredRegs:$src1, s8Ext:$src2, - IntRegs:$src3), - "$dst = mux($src1, #$src2, $src3)", - [(set (i32 IntRegs:$dst), - (i32 (select (i1 PredRegs:$src1), s8ExtPred:$src2, - (i32 IntRegs:$src3))))]>, ImmRegRel; - -let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 8, -CextOpcode = "MUX", InputType = "imm" in -def MUX_ri : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, - s8Ext:$src3), - "$dst = mux($src1, $src2, #$src3)", - [(set (i32 IntRegs:$dst), - (i32 (select (i1 PredRegs:$src1), (i32 IntRegs:$src2), - s8ExtPred:$src3)))]>, ImmRegRel; - -let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8 in -def MUX_ii : ALU32_ii<(outs IntRegs:$dst), (ins PredRegs:$src1, s8Ext:$src2, - s8Imm:$src3), - "$dst = mux($src1, #$src2, #$src3)", - [(set (i32 IntRegs:$dst), (i32 (select (i1 PredRegs:$src1), - s8ExtPred:$src2, - s8ImmPred:$src3)))]>; - -// ALU32 - aslh, asrh, sxtb, sxth, zxtb, zxth -multiclass ALU32_2op_Pbase<string mnemonic, bit isNot, bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : ALU32Inst<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ", - ") $dst = ")#mnemonic#"($src2)">, - Requires<[HasV4T]>; -} - -multiclass ALU32_2op_Pred<string mnemonic, bit PredNot> { +multiclass ALU32_2op_Pred<string mnemonic, bits<3> minOp, bit PredNot> { let isPredicatedFalse = PredNot in { - defm _c#NAME : ALU32_2op_Pbase<mnemonic, PredNot, 0>; + def NAME : T_ALU32_2op_Pred<mnemonic, minOp, PredNot, 0>; + // Predicate new - defm _cdn#NAME : ALU32_2op_Pbase<mnemonic, PredNot, 1>; + let isPredicatedNew = 1 in + def NAME#new : T_ALU32_2op_Pred<mnemonic, minOp, PredNot, 1>; } } -multiclass ALU32_2op_base<string mnemonic> { +multiclass ALU32_2op_base<string mnemonic, bits<3> minOp> { let BaseOpcode = mnemonic in { - let isPredicable = 1, neverHasSideEffects = 1 in - def NAME : ALU32Inst<(outs IntRegs:$dst), - (ins IntRegs:$src1), - "$dst = "#mnemonic#"($src1)">; - - let Predicates = [HasV4T], validSubTargets = HasV4SubT, isPredicated = 1, - neverHasSideEffects = 1 in { - defm Pt_V4 : ALU32_2op_Pred<mnemonic, 0>; - defm NotPt_V4 : ALU32_2op_Pred<mnemonic, 1>; + let isPredicable = 1, hasSideEffects = 0 in + def A2_#NAME : T_ALU32_2op<mnemonic, minOp>; + + let validSubTargets = HasV4SubT, isPredicated = 1, hasSideEffects = 0 in { + defm A4_p#NAME#t : ALU32_2op_Pred<mnemonic, minOp, 0>; + defm A4_p#NAME#f : ALU32_2op_Pred<mnemonic, minOp, 1>; } } } -defm ASLH : ALU32_2op_base<"aslh">, PredNewRel; -defm ASRH : ALU32_2op_base<"asrh">, PredNewRel; -defm SXTB : ALU32_2op_base<"sxtb">, PredNewRel; -defm SXTH : ALU32_2op_base<"sxth">, PredNewRel; -defm ZXTB : ALU32_2op_base<"zxtb">, PredNewRel; -defm ZXTH : ALU32_2op_base<"zxth">, PredNewRel; +let isCodeGenOnly = 0 in { +defm aslh : ALU32_2op_base<"aslh", 0b000>, PredNewRel; +defm asrh : ALU32_2op_base<"asrh", 0b001>, PredNewRel; +defm sxtb : ALU32_2op_base<"sxtb", 0b101>, PredNewRel; +defm sxth : ALU32_2op_base<"sxth", 0b111>, PredNewRel; +defm zxth : ALU32_2op_base<"zxth", 0b110>, PredNewRel; +} -def : Pat <(shl (i32 IntRegs:$src1), (i32 16)), - (ASLH IntRegs:$src1)>; +// Rd=zxtb(Rs): assembler mapped to Rd=and(Rs,#255). +// Compiler would want to generate 'zxtb' instead of 'and' becuase 'zxtb' has +// predicated forms while 'and' doesn't. Since integrated assembler can't +// handle 'mapped' instructions, we need to encode 'zxtb' same as 'and' where +// immediate operand is set to '255'. + +let hasNewValue = 1, opNewValue = 0 in +class T_ZXTB: ALU32Inst < (outs IntRegs:$Rd), (ins IntRegs:$Rs), + "$Rd = zxtb($Rs)", [] > { // Rd = and(Rs,255) + bits<5> Rd; + bits<5> Rs; + bits<10> s10 = 255; + + let IClass = 0b0111; + + let Inst{27-22} = 0b011000; + let Inst{4-0} = Rd; + let Inst{20-16} = Rs; + let Inst{21} = s10{9}; + let Inst{13-5} = s10{8-0}; +} -def : Pat <(sra (i32 IntRegs:$src1), (i32 16)), - (ASRH IntRegs:$src1)>; +//Rd=zxtb(Rs): assembler mapped to "Rd=and(Rs,#255) +multiclass ZXTB_base <string mnemonic, bits<3> minOp> { + let BaseOpcode = mnemonic in { + let isPredicable = 1, hasSideEffects = 0 in + def A2_#NAME : T_ZXTB; -def : Pat <(sext_inreg (i32 IntRegs:$src1), i8), - (SXTB IntRegs:$src1)>; + let validSubTargets = HasV4SubT, isPredicated = 1, hasSideEffects = 0 in { + defm A4_p#NAME#t : ALU32_2op_Pred<mnemonic, minOp, 0>; + defm A4_p#NAME#f : ALU32_2op_Pred<mnemonic, minOp, 1>; + } + } +} + +let isCodeGenOnly=0 in +defm zxtb : ZXTB_base<"zxtb",0b100>, PredNewRel; + +def: Pat<(shl I32:$src1, (i32 16)), (A2_aslh I32:$src1)>; +def: Pat<(sra I32:$src1, (i32 16)), (A2_asrh I32:$src1)>; +def: Pat<(sext_inreg I32:$src1, i8), (A2_sxtb I32:$src1)>; +def: Pat<(sext_inreg I32:$src1, i16), (A2_sxth I32:$src1)>; + +// Mux. +def VMUX_prr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, + DoubleRegs:$src2, + DoubleRegs:$src3), + "$dst = vmux($src1, $src2, $src3)", + []>; -def : Pat <(sext_inreg (i32 IntRegs:$src1), i16), - (SXTH IntRegs:$src1)>; //===----------------------------------------------------------------------===// // ALU32/PERM - @@ -492,11 +816,6 @@ def : Pat <(sext_inreg (i32 IntRegs:$src1), i16), // ALU32/PRED + //===----------------------------------------------------------------------===// -// Compare. -defm CMPGTU : CMP32_rr_ri_u9<"cmp.gtu", "CMPGTU", setugt>, ImmRegRel; -defm CMPGT : CMP32_rr_ri_s10<"cmp.gt", "CMPGT", setgt>, ImmRegRel; -defm CMPEQ : CMP32_rr_ri_s10<"cmp.eq", "CMPEQ", seteq>, ImmRegRel; - // SDNode for converting immediate C to C-1. def DEC_CONST_SIGNED : SDNodeXForm<imm, [{ // Return the byte immediate const-1 as an SDNode. @@ -511,14 +830,6 @@ def DEC_CONST_UNSIGNED : SDNodeXForm<imm, [{ return XformUToUM1Imm(imm); }]>; -def CTLZ_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = cl0($src1)", - [(set (i32 IntRegs:$dst), (ctlz (i32 IntRegs:$src1)))]>; - -def CTTZ_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = ct0($src1)", - [(set (i32 IntRegs:$dst), (cttz (i32 IntRegs:$src1)))]>; - def CTLZ64_rr : SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1), "$dst = cl0($src1)", [(set (i32 IntRegs:$dst), (i32 (trunc (ctlz (i64 DoubleRegs:$src1)))))]>; @@ -527,16 +838,6 @@ def CTTZ64_rr : SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1), "$dst = ct0($src1)", [(set (i32 IntRegs:$dst), (i32 (trunc (cttz (i64 DoubleRegs:$src1)))))]>; -def TSTBIT_rr : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = tstbit($src1, $src2)", - [(set (i1 PredRegs:$dst), - (setne (and (shl 1, (i32 IntRegs:$src2)), (i32 IntRegs:$src1)), 0))]>; - -def TSTBIT_ri : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), - "$dst = tstbit($src1, $src2)", - [(set (i1 PredRegs:$dst), - (setne (and (shl 1, (u5ImmPred:$src2)), (i32 IntRegs:$src1)), 0))]>; - //===----------------------------------------------------------------------===// // ALU32/PRED - //===----------------------------------------------------------------------===// @@ -544,114 +845,279 @@ def TSTBIT_ri : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), //===----------------------------------------------------------------------===// // ALU64/ALU + +//===----------------------------------------------------------------------===//// Add. +//===----------------------------------------------------------------------===// +// Template Class +// Add/Subtract halfword +// Rd=add(Rt.L,Rs.[HL])[:sat] +// Rd=sub(Rt.L,Rs.[HL])[:sat] +// Rd=add(Rt.[LH],Rs.[HL])[:sat][:<16] +// Rd=sub(Rt.[LH],Rs.[HL])[:sat][:<16] //===----------------------------------------------------------------------===// -// Add. -def ADD64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = add($src1, $src2)", - [(set (i64 DoubleRegs:$dst), (add (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2)))]>; -// Add halfword. +let hasNewValue = 1, opNewValue = 0 in +class T_XTYPE_ADD_SUB <bits<2> LHbits, bit isSat, bit hasShift, bit isSub> + : ALU64Inst <(outs IntRegs:$Rd), (ins IntRegs:$Rt, IntRegs:$Rs), + "$Rd = "#!if(isSub,"sub","add")#"($Rt." + #!if(hasShift, !if(LHbits{1},"h","l"),"l") #", $Rs." + #!if(hasShift, !if(LHbits{0},"h)","l)"), !if(LHbits{1},"h)","l)")) + #!if(isSat,":sat","") + #!if(hasShift,":<<16",""), [], "", ALU64_tc_1_SLOT23> { + bits<5> Rd; + bits<5> Rt; + bits<5> Rs; + let IClass = 0b1101; + + let Inst{27-23} = 0b01010; + let Inst{22} = hasShift; + let Inst{21} = isSub; + let Inst{7} = isSat; + let Inst{6-5} = LHbits; + let Inst{4-0} = Rd; + let Inst{12-8} = Rt; + let Inst{20-16} = Rs; + } -// Compare. -defm CMPEHexagon4 : CMP64_rr<"cmp.eq", seteq>; -defm CMPGT64 : CMP64_rr<"cmp.gt", setgt>; -defm CMPGTU64 : CMP64_rr<"cmp.gtu", setugt>; - -// Logical operations. -def AND_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = and($src1, $src2)", - [(set (i64 DoubleRegs:$dst), (and (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2)))]>; - -def OR_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = or($src1, $src2)", - [(set (i64 DoubleRegs:$dst), (or (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2)))]>; - -def XOR_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = xor($src1, $src2)", - [(set (i64 DoubleRegs:$dst), (xor (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2)))]>; - -// Maximum. -def MAXw_rr : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = max($src2, $src1)", - [(set (i32 IntRegs:$dst), - (i32 (select (i1 (setlt (i32 IntRegs:$src2), - (i32 IntRegs:$src1))), - (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>; +//Rd=sub(Rt.L,Rs.[LH]) +let isCodeGenOnly = 0 in { +def A2_subh_l16_ll : T_XTYPE_ADD_SUB <0b00, 0, 0, 1>; +def A2_subh_l16_hl : T_XTYPE_ADD_SUB <0b10, 0, 0, 1>; +} -def MAXUw_rr : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = maxu($src2, $src1)", - [(set (i32 IntRegs:$dst), - (i32 (select (i1 (setult (i32 IntRegs:$src2), - (i32 IntRegs:$src1))), - (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>; - -def MAXd_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = max($src2, $src1)", - [(set (i64 DoubleRegs:$dst), - (i64 (select (i1 (setlt (i64 DoubleRegs:$src2), - (i64 DoubleRegs:$src1))), - (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2))))]>; - -def MAXUd_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = maxu($src2, $src1)", - [(set (i64 DoubleRegs:$dst), - (i64 (select (i1 (setult (i64 DoubleRegs:$src2), - (i64 DoubleRegs:$src1))), - (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2))))]>; - -// Minimum. -def MINw_rr : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = min($src2, $src1)", - [(set (i32 IntRegs:$dst), - (i32 (select (i1 (setgt (i32 IntRegs:$src2), - (i32 IntRegs:$src1))), - (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>; +let isCodeGenOnly = 0 in { +//Rd=add(Rt.L,Rs.[LH]) +def A2_addh_l16_ll : T_XTYPE_ADD_SUB <0b00, 0, 0, 0>; +def A2_addh_l16_hl : T_XTYPE_ADD_SUB <0b10, 0, 0, 0>; +} -def MINUw_rr : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = minu($src2, $src1)", - [(set (i32 IntRegs:$dst), - (i32 (select (i1 (setugt (i32 IntRegs:$src2), - (i32 IntRegs:$src1))), - (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>; - -def MINd_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = min($src2, $src1)", - [(set (i64 DoubleRegs:$dst), - (i64 (select (i1 (setgt (i64 DoubleRegs:$src2), - (i64 DoubleRegs:$src1))), - (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2))))]>; - -def MINUd_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = minu($src2, $src1)", - [(set (i64 DoubleRegs:$dst), - (i64 (select (i1 (setugt (i64 DoubleRegs:$src2), - (i64 DoubleRegs:$src1))), - (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2))))]>; - -// Subtract. -def SUB64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = sub($src1, $src2)", - [(set (i64 DoubleRegs:$dst), (sub (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2)))]>; +let Itinerary = ALU64_tc_2_SLOT23, Defs = [USR_OVF], isCodeGenOnly = 0 in { + //Rd=sub(Rt.L,Rs.[LH]):sat + def A2_subh_l16_sat_ll : T_XTYPE_ADD_SUB <0b00, 1, 0, 1>; + def A2_subh_l16_sat_hl : T_XTYPE_ADD_SUB <0b10, 1, 0, 1>; + + //Rd=add(Rt.L,Rs.[LH]):sat + def A2_addh_l16_sat_ll : T_XTYPE_ADD_SUB <0b00, 1, 0, 0>; + def A2_addh_l16_sat_hl : T_XTYPE_ADD_SUB <0b10, 1, 0, 0>; +} + +//Rd=sub(Rt.[LH],Rs.[LH]):<<16 +let isCodeGenOnly = 0 in { +def A2_subh_h16_ll : T_XTYPE_ADD_SUB <0b00, 0, 1, 1>; +def A2_subh_h16_lh : T_XTYPE_ADD_SUB <0b01, 0, 1, 1>; +def A2_subh_h16_hl : T_XTYPE_ADD_SUB <0b10, 0, 1, 1>; +def A2_subh_h16_hh : T_XTYPE_ADD_SUB <0b11, 0, 1, 1>; +} + +//Rd=add(Rt.[LH],Rs.[LH]):<<16 +let isCodeGenOnly = 0 in { +def A2_addh_h16_ll : T_XTYPE_ADD_SUB <0b00, 0, 1, 0>; +def A2_addh_h16_lh : T_XTYPE_ADD_SUB <0b01, 0, 1, 0>; +def A2_addh_h16_hl : T_XTYPE_ADD_SUB <0b10, 0, 1, 0>; +def A2_addh_h16_hh : T_XTYPE_ADD_SUB <0b11, 0, 1, 0>; +} + +let Itinerary = ALU64_tc_2_SLOT23, Defs = [USR_OVF], isCodeGenOnly = 0 in { + //Rd=sub(Rt.[LH],Rs.[LH]):sat:<<16 + def A2_subh_h16_sat_ll : T_XTYPE_ADD_SUB <0b00, 1, 1, 1>; + def A2_subh_h16_sat_lh : T_XTYPE_ADD_SUB <0b01, 1, 1, 1>; + def A2_subh_h16_sat_hl : T_XTYPE_ADD_SUB <0b10, 1, 1, 1>; + def A2_subh_h16_sat_hh : T_XTYPE_ADD_SUB <0b11, 1, 1, 1>; + + //Rd=add(Rt.[LH],Rs.[LH]):sat:<<16 + def A2_addh_h16_sat_ll : T_XTYPE_ADD_SUB <0b00, 1, 1, 0>; + def A2_addh_h16_sat_lh : T_XTYPE_ADD_SUB <0b01, 1, 1, 0>; + def A2_addh_h16_sat_hl : T_XTYPE_ADD_SUB <0b10, 1, 1, 0>; + def A2_addh_h16_sat_hh : T_XTYPE_ADD_SUB <0b11, 1, 1, 0>; +} + +// Add halfword. +def: Pat<(sext_inreg (add I32:$src1, I32:$src2), i16), + (A2_addh_l16_ll I32:$src1, I32:$src2)>; + +def: Pat<(sra (add (shl I32:$src1, (i32 16)), I32:$src2), (i32 16)), + (A2_addh_l16_hl I32:$src1, I32:$src2)>; + +def: Pat<(shl (add I32:$src1, I32:$src2), (i32 16)), + (A2_addh_h16_ll I32:$src1, I32:$src2)>; // Subtract halfword. +def: Pat<(sext_inreg (sub I32:$src1, I32:$src2), i16), + (A2_subh_l16_ll I32:$src1, I32:$src2)>; + +def: Pat<(shl (sub I32:$src1, I32:$src2), (i32 16)), + (A2_subh_h16_ll I32:$src1, I32:$src2)>; + +let hasSideEffects = 0, hasNewValue = 1, isCodeGenOnly = 0 in +def S2_parityp: ALU64Inst<(outs IntRegs:$Rd), + (ins DoubleRegs:$Rs, DoubleRegs:$Rt), + "$Rd = parity($Rs, $Rt)", [], "", ALU64_tc_2_SLOT23> { + bits<5> Rd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1101; + let Inst{27-24} = 0b0000; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{4-0} = Rd; +} + +let hasNewValue = 1, opNewValue = 0, hasSideEffects = 0 in +class T_XTYPE_MIN_MAX < bit isMax, bit isUnsigned > + : ALU64Inst < (outs IntRegs:$Rd), (ins IntRegs:$Rt, IntRegs:$Rs), + "$Rd = "#!if(isMax,"max","min")#!if(isUnsigned,"u","") + #"($Rt, $Rs)", [], "", ALU64_tc_2_SLOT23> { + bits<5> Rd; + bits<5> Rt; + bits<5> Rs; + + let IClass = 0b1101; + + let Inst{27-23} = 0b01011; + let Inst{22-21} = !if(isMax, 0b10, 0b01); + let Inst{7} = isUnsigned; + let Inst{4-0} = Rd; + let Inst{12-8} = !if(isMax, Rs, Rt); + let Inst{20-16} = !if(isMax, Rt, Rs); + } + +let isCodeGenOnly = 0 in { +def A2_min : T_XTYPE_MIN_MAX < 0, 0 >; +def A2_minu : T_XTYPE_MIN_MAX < 0, 1 >; +def A2_max : T_XTYPE_MIN_MAX < 1, 0 >; +def A2_maxu : T_XTYPE_MIN_MAX < 1, 1 >; +} + +// Here, depending on the operand being selected, we'll either generate a +// min or max instruction. +// Ex: +// (a>b)?a:b --> max(a,b) => Here check performed is '>' and the value selected +// is the larger of two. So, the corresponding HexagonInst is passed in 'Inst'. +// (a>b)?b:a --> min(a,b) => Here check performed is '>' but the smaller value +// is selected and the corresponding HexagonInst is passed in 'SwapInst'. + +multiclass T_MinMax_pats <PatFrag Op, RegisterClass RC, ValueType VT, + InstHexagon Inst, InstHexagon SwapInst> { + def: Pat<(select (i1 (Op (VT RC:$src1), (VT RC:$src2))), + (VT RC:$src1), (VT RC:$src2)), + (Inst RC:$src1, RC:$src2)>; + def: Pat<(select (i1 (Op (VT RC:$src1), (VT RC:$src2))), + (VT RC:$src2), (VT RC:$src1)), + (SwapInst RC:$src1, RC:$src2)>; +} + + +multiclass MinMax_pats <PatFrag Op, InstHexagon Inst, InstHexagon SwapInst> { + defm: T_MinMax_pats<Op, IntRegs, i32, Inst, SwapInst>; + + def: Pat<(sext_inreg (i32 (select (i1 (Op (i32 PositiveHalfWord:$src1), + (i32 PositiveHalfWord:$src2))), + (i32 PositiveHalfWord:$src1), + (i32 PositiveHalfWord:$src2))), i16), + (Inst IntRegs:$src1, IntRegs:$src2)>; + + def: Pat<(sext_inreg (i32 (select (i1 (Op (i32 PositiveHalfWord:$src1), + (i32 PositiveHalfWord:$src2))), + (i32 PositiveHalfWord:$src2), + (i32 PositiveHalfWord:$src1))), i16), + (SwapInst IntRegs:$src1, IntRegs:$src2)>; +} + +let AddedComplexity = 200 in { + defm: MinMax_pats<setge, A2_max, A2_min>; + defm: MinMax_pats<setgt, A2_max, A2_min>; + defm: MinMax_pats<setle, A2_min, A2_max>; + defm: MinMax_pats<setlt, A2_min, A2_max>; + defm: MinMax_pats<setuge, A2_maxu, A2_minu>; + defm: MinMax_pats<setugt, A2_maxu, A2_minu>; + defm: MinMax_pats<setule, A2_minu, A2_maxu>; + defm: MinMax_pats<setult, A2_minu, A2_maxu>; +} + +class T_cmp64_rr<string mnemonic, bits<3> MinOp, bit IsComm> + : ALU64_rr<(outs PredRegs:$Pd), (ins DoubleRegs:$Rs, DoubleRegs:$Rt), + "$Pd = "#mnemonic#"($Rs, $Rt)", [], "", ALU64_tc_2early_SLOT23> { + let isCompare = 1; + let isCommutable = IsComm; + let hasSideEffects = 0; + + bits<2> Pd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1101; + let Inst{27-21} = 0b0010100; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{7-5} = MinOp; + let Inst{1-0} = Pd; +} + +let isCodeGenOnly = 0 in { +def C2_cmpeqp : T_cmp64_rr<"cmp.eq", 0b000, 1>; +def C2_cmpgtp : T_cmp64_rr<"cmp.gt", 0b010, 0>; +def C2_cmpgtup : T_cmp64_rr<"cmp.gtu", 0b100, 0>; +} + +class T_cmp64_rr_pat<InstHexagon MI, PatFrag CmpOp> + : Pat<(i1 (CmpOp (i64 DoubleRegs:$Rs), (i64 DoubleRegs:$Rt))), + (i1 (MI DoubleRegs:$Rs, DoubleRegs:$Rt))>; + +def: T_cmp64_rr_pat<C2_cmpeqp, seteq>; +def: T_cmp64_rr_pat<C2_cmpgtp, setgt>; +def: T_cmp64_rr_pat<C2_cmpgtup, setugt>; +def: T_cmp64_rr_pat<C2_cmpgtp, RevCmp<setlt>>; +def: T_cmp64_rr_pat<C2_cmpgtup, RevCmp<setult>>; + +class T_ALU64_rr<string mnemonic, string suffix, bits<4> RegType, + bits<3> MajOp, bits<3> MinOp, bit OpsRev, bit IsComm, + string Op2Pfx> + : ALU64_rr<(outs DoubleRegs:$Rd), (ins DoubleRegs:$Rs, DoubleRegs:$Rt), + "$Rd = " #mnemonic# "($Rs, " #Op2Pfx# "$Rt)" #suffix, [], + "", ALU64_tc_1_SLOT23> { + let hasSideEffects = 0; + let isCommutable = IsComm; + + bits<5> Rs; + bits<5> Rt; + bits<5> Rd; + + let IClass = 0b1101; + let Inst{27-24} = RegType; + let Inst{23-21} = MajOp; + let Inst{20-16} = !if (OpsRev,Rt,Rs); + let Inst{12-8} = !if (OpsRev,Rs,Rt); + let Inst{7-5} = MinOp; + let Inst{4-0} = Rd; +} + +class T_ALU64_arith<string mnemonic, bits<3> MajOp, bits<3> MinOp, bit IsSat, + bit OpsRev, bit IsComm> + : T_ALU64_rr<mnemonic, !if(IsSat,":sat",""), 0b0011, MajOp, MinOp, OpsRev, + IsComm, "">; + +let isCodeGenOnly = 0 in { +def A2_addp : T_ALU64_arith<"add", 0b000, 0b111, 0, 0, 1>; +def A2_subp : T_ALU64_arith<"sub", 0b001, 0b111, 0, 1, 0>; +} + +def: Pat<(i64 (add I64:$Rs, I64:$Rt)), (A2_addp I64:$Rs, I64:$Rt)>; +def: Pat<(i64 (sub I64:$Rs, I64:$Rt)), (A2_subp I64:$Rs, I64:$Rt)>; + +class T_ALU64_logical<string mnemonic, bits<3> MinOp, bit OpsRev, bit IsComm, + bit IsNeg> + : T_ALU64_rr<mnemonic, "", 0b0011, 0b111, MinOp, OpsRev, IsComm, + !if(IsNeg,"~","")>; + +let isCodeGenOnly = 0 in { +def A2_andp : T_ALU64_logical<"and", 0b000, 0, 1, 0>; +def A2_orp : T_ALU64_logical<"or", 0b010, 0, 1, 0>; +def A2_xorp : T_ALU64_logical<"xor", 0b100, 0, 1, 0>; +} + +def: Pat<(i64 (and I64:$Rs, I64:$Rt)), (A2_andp I64:$Rs, I64:$Rt)>; +def: Pat<(i64 (or I64:$Rs, I64:$Rt)), (A2_orp I64:$Rs, I64:$Rt)>; +def: Pat<(i64 (xor I64:$Rs, I64:$Rt)), (A2_xorp I64:$Rs, I64:$Rt)>; //===----------------------------------------------------------------------===// // ALU64/ALU - @@ -683,29 +1149,90 @@ def SUB64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, // Pipelined looping instructions. // Logical operations on predicates. -def AND_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, PredRegs:$src2), - "$dst = and($src1, $src2)", - [(set (i1 PredRegs:$dst), (and (i1 PredRegs:$src1), - (i1 PredRegs:$src2)))]>; - -let neverHasSideEffects = 1 in -def AND_pnotp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, - PredRegs:$src2), - "$dst = and($src1, !$src2)", - []>; - -def ANY_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1), - "$dst = any8($src1)", - []>; +let hasSideEffects = 0 in +class T_LOGICAL_1OP<string MnOp, bits<2> OpBits> + : CRInst<(outs PredRegs:$Pd), (ins PredRegs:$Ps), + "$Pd = " # MnOp # "($Ps)", [], "", CR_tc_2early_SLOT23> { + bits<2> Pd; + bits<2> Ps; + + let IClass = 0b0110; + let Inst{27-23} = 0b10111; + let Inst{22-21} = OpBits; + let Inst{20} = 0b0; + let Inst{17-16} = Ps; + let Inst{13} = 0b0; + let Inst{1-0} = Pd; +} -def ALL_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1), - "$dst = all8($src1)", - []>; +let isCodeGenOnly = 0 in { +def C2_any8 : T_LOGICAL_1OP<"any8", 0b00>; +def C2_all8 : T_LOGICAL_1OP<"all8", 0b01>; +def C2_not : T_LOGICAL_1OP<"not", 0b10>; +} -def VITPACK_pp : SInst<(outs IntRegs:$dst), (ins PredRegs:$src1, - PredRegs:$src2), - "$dst = vitpack($src1, $src2)", - []>; +def: Pat<(i1 (not (i1 PredRegs:$Ps))), + (C2_not PredRegs:$Ps)>; + +let hasSideEffects = 0 in +class T_LOGICAL_2OP<string MnOp, bits<3> OpBits, bit IsNeg, bit Rev> + : CRInst<(outs PredRegs:$Pd), (ins PredRegs:$Ps, PredRegs:$Pt), + "$Pd = " # MnOp # "($Ps, " # !if (IsNeg,"!","") # "$Pt)", + [], "", CR_tc_2early_SLOT23> { + bits<2> Pd; + bits<2> Ps; + bits<2> Pt; + + let IClass = 0b0110; + let Inst{27-24} = 0b1011; + let Inst{23-21} = OpBits; + let Inst{20} = 0b0; + let Inst{17-16} = !if(Rev,Pt,Ps); // Rs and Rt are reversed for some + let Inst{13} = 0b0; // instructions. + let Inst{9-8} = !if(Rev,Ps,Pt); + let Inst{1-0} = Pd; +} + +let isCodeGenOnly = 0 in { +def C2_and : T_LOGICAL_2OP<"and", 0b000, 0, 1>; +def C2_or : T_LOGICAL_2OP<"or", 0b001, 0, 1>; +def C2_xor : T_LOGICAL_2OP<"xor", 0b010, 0, 0>; +def C2_andn : T_LOGICAL_2OP<"and", 0b011, 1, 1>; +def C2_orn : T_LOGICAL_2OP<"or", 0b111, 1, 1>; +} + +def: Pat<(i1 (and I1:$Ps, I1:$Pt)), (C2_and I1:$Ps, I1:$Pt)>; +def: Pat<(i1 (or I1:$Ps, I1:$Pt)), (C2_or I1:$Ps, I1:$Pt)>; +def: Pat<(i1 (xor I1:$Ps, I1:$Pt)), (C2_xor I1:$Ps, I1:$Pt)>; +def: Pat<(i1 (and I1:$Ps, (not I1:$Pt))), (C2_andn I1:$Ps, I1:$Pt)>; +def: Pat<(i1 (or I1:$Ps, (not I1:$Pt))), (C2_orn I1:$Ps, I1:$Pt)>; + +let hasSideEffects = 0, hasNewValue = 1, isCodeGenOnly = 0 in +def C2_vitpack : SInst<(outs IntRegs:$Rd), (ins PredRegs:$Ps, PredRegs:$Pt), + "$Rd = vitpack($Ps, $Pt)", [], "", S_2op_tc_1_SLOT23> { + bits<5> Rd; + bits<2> Ps; + bits<2> Pt; + + let IClass = 0b1000; + let Inst{27-24} = 0b1001; + let Inst{22-21} = 0b00; + let Inst{17-16} = Ps; + let Inst{9-8} = Pt; + let Inst{4-0} = Rd; +} + +let hasSideEffects = 0, isCodeGenOnly = 0 in +def C2_mask : SInst<(outs DoubleRegs:$Rd), (ins PredRegs:$Pt), + "$Rd = mask($Pt)", [], "", S_2op_tc_1_SLOT23> { + bits<5> Rd; + bits<2> Pt; + + let IClass = 0b1000; + let Inst{27-24} = 0b0110; + let Inst{9-8} = Pt; + let Inst{4-0} = Rd; +} def VALIGN_rrp : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2, @@ -719,46 +1246,38 @@ def VSPLICE_rrp : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, "$dst = vspliceb($src1, $src2, $src3)", []>; -def MASK_p : SInst<(outs DoubleRegs:$dst), (ins PredRegs:$src1), - "$dst = mask($src1)", - []>; - -def NOT_p : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1), - "$dst = not($src1)", - [(set (i1 PredRegs:$dst), (not (i1 PredRegs:$src1)))]>; - -def OR_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, PredRegs:$src2), - "$dst = or($src1, $src2)", - [(set (i1 PredRegs:$dst), (or (i1 PredRegs:$src1), - (i1 PredRegs:$src2)))]>; - -def XOR_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, PredRegs:$src2), - "$dst = xor($src1, $src2)", - [(set (i1 PredRegs:$dst), (xor (i1 PredRegs:$src1), - (i1 PredRegs:$src2)))]>; - - // User control register transfer. //===----------------------------------------------------------------------===// // CR - //===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// JR + +//===----------------------------------------------------------------------===// + def retflag : SDNode<"HexagonISD::RET_FLAG", SDTNone, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -def eh_return: SDNode<"HexagonISD::EH_RETURN", SDTNone, - [SDNPHasChain]>; +def eh_return: SDNode<"HexagonISD::EH_RETURN", SDTNone, [SDNPHasChain]>; def SDHexagonBR_JT: SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; def HexagonBR_JT: SDNode<"HexagonISD::BR_JT", SDHexagonBR_JT, [SDNPHasChain]>; -let InputType = "imm", isBarrier = 1, isPredicable = 1, -Defs = [PC], isExtendable = 1, opExtendable = 0, isExtentSigned = 1, -opExtentBits = 24 in -class T_JMP <dag InsDag, list<dag> JumpList = []> - : JInst<(outs), InsDag, - "jump $dst" , JumpList> { - bits<24> dst; +class CondStr<string CReg, bit True, bit New> { + string S = "if (" # !if(True,"","!") # CReg # !if(New,".new","") # ") "; +} +class JumpOpcStr<string Mnemonic, bit New, bit Taken> { + string S = Mnemonic # !if(New, !if(Taken,":t",":nt"), ""); +} +let isBranch = 1, isBarrier = 1, Defs = [PC], hasSideEffects = 0, + isPredicable = 1, + isExtendable = 1, opExtendable = 0, isExtentSigned = 1, + opExtentBits = 24, opExtentAlign = 2, InputType = "imm" in +class T_JMP<string ExtStr> + : JInst<(outs), (ins brtarget:$dst), + "jump " # ExtStr # "$dst", + [], "", J_tc_2early_SLOT23> { + bits<24> dst; let IClass = 0b0101; let Inst{27-25} = 0b100; @@ -766,16 +1285,16 @@ class T_JMP <dag InsDag, list<dag> JumpList = []> let Inst{13-1} = dst{14-2}; } -let InputType = "imm", isExtendable = 1, opExtendable = 1, isExtentSigned = 1, -Defs = [PC], isPredicated = 1, opExtentBits = 17 in -class T_JMP_c <bit PredNot, bit isPredNew, bit isTak>: - JInst<(outs ), (ins PredRegs:$src, brtarget:$dst), - !if(PredNot, "if (!$src", "if ($src")# - !if(isPredNew, ".new) ", ") ")#"jump"# - !if(isPredNew, !if(isTak, ":t ", ":nt "), " ")#"$dst"> { - +let isBranch = 1, Defs = [PC], hasSideEffects = 0, isPredicated = 1, + isExtendable = 1, opExtendable = 1, isExtentSigned = 1, + opExtentBits = 17, opExtentAlign = 2, InputType = "imm" in +class T_JMP_c<bit PredNot, bit isPredNew, bit isTak, string ExtStr> + : JInst<(outs), (ins PredRegs:$src, brtarget:$dst), + CondStr<"$src", !if(PredNot,0,1), isPredNew>.S # + JumpOpcStr<"jump", isPredNew, isTak>.S # " " # + ExtStr # "$dst", + [], "", J_tc_2early_SLOT23>, ImmRegRel { let isTaken = isTak; - let isBrTaken = !if(isPredNew, !if(isTaken, "true", "false"), ""); let isPredicatedFalse = PredNot; let isPredicatedNew = isPredNew; bits<2> src; @@ -794,11 +1313,28 @@ class T_JMP_c <bit PredNot, bit isPredNew, bit isTak>: let Inst{7-1} = dst{8-2}; } -let isBarrier = 1, Defs = [PC], isPredicable = 1, InputType = "reg" in -class T_JMPr<dag InsDag = (ins IntRegs:$dst)> - : JRInst<(outs ), InsDag, - "jumpr $dst" , - []> { +multiclass JMP_Pred<bit PredNot, string ExtStr> { + def NAME : T_JMP_c<PredNot, 0, 0, ExtStr>; + // Predicate new + def NAME#newpt : T_JMP_c<PredNot, 1, 1, ExtStr>; // taken + def NAME#new : T_JMP_c<PredNot, 1, 0, ExtStr>; // not taken +} + +multiclass JMP_base<string BaseOp, string ExtStr> { + let BaseOpcode = BaseOp in { + def NAME : T_JMP<ExtStr>; + defm t : JMP_Pred<0, ExtStr>; + defm f : JMP_Pred<1, ExtStr>; + } +} + +// Jumps to address stored in a register, JUMPR_MISC +// if ([[!]P[.new]]) jumpr[:t/nt] Rs +let isBranch = 1, isIndirectBranch = 1, isBarrier = 1, Defs = [PC], + isPredicable = 1, hasSideEffects = 0, InputType = "reg" in +class T_JMPr + : JRInst<(outs), (ins IntRegs:$dst), + "jumpr $dst", [], "", J_tc_2early_SLOT2> { bits<5> dst; let IClass = 0b0101; @@ -806,15 +1342,15 @@ class T_JMPr<dag InsDag = (ins IntRegs:$dst)> let Inst{20-16} = dst; } -let Defs = [PC], isPredicated = 1, InputType = "reg" in -class T_JMPr_c <bit PredNot, bit isPredNew, bit isTak>: - JRInst <(outs ), (ins PredRegs:$src, IntRegs:$dst), - !if(PredNot, "if (!$src", "if ($src")# - !if(isPredNew, ".new) ", ") ")#"jumpr"# - !if(isPredNew, !if(isTak, ":t ", ":nt "), " ")#"$dst"> { +let isBranch = 1, isIndirectBranch = 1, Defs = [PC], isPredicated = 1, + hasSideEffects = 0, InputType = "reg" in +class T_JMPr_c <bit PredNot, bit isPredNew, bit isTak> + : JRInst <(outs), (ins PredRegs:$src, IntRegs:$dst), + CondStr<"$src", !if(PredNot,0,1), isPredNew>.S # + JumpOpcStr<"jumpr", isPredNew, isTak>.S # " $dst", [], + "", J_tc_2early_SLOT2> { let isTaken = isTak; - let isBrTaken = !if(isPredNew, !if(isTaken, "true", "false"), ""); let isPredicatedFalse = PredNot; let isPredicatedNew = isPredNew; bits<2> src; @@ -828,70 +1364,85 @@ class T_JMPr_c <bit PredNot, bit isPredNew, bit isTak>: let Inst{12} = !if(isPredNew, isTak, zero); let Inst{11} = isPredNew; let Inst{9-8} = src; - let Predicates = !if(isPredNew, [HasV3T], [HasV2T]); - let validSubTargets = !if(isPredNew, HasV3SubT, HasV2SubT); -} - -multiclass JMP_Pred<bit PredNot> { - def _#NAME : T_JMP_c<PredNot, 0, 0>; - // Predicate new - def _#NAME#new_t : T_JMP_c<PredNot, 1, 1>; // taken - def _#NAME#new_nt : T_JMP_c<PredNot, 1, 0>; // not taken -} - -multiclass JMP_base<string BaseOp> { - let BaseOpcode = BaseOp in { - def NAME : T_JMP<(ins brtarget:$dst), [(br bb:$dst)]>; - defm t : JMP_Pred<0>; - defm f : JMP_Pred<1>; - } } multiclass JMPR_Pred<bit PredNot> { def NAME: T_JMPr_c<PredNot, 0, 0>; // Predicate new - def NAME#new_tV3 : T_JMPr_c<PredNot, 1, 1>; // taken - def NAME#new_ntV3 : T_JMPr_c<PredNot, 1, 0>; // not taken + def NAME#newpt : T_JMPr_c<PredNot, 1, 1>; // taken + def NAME#new : T_JMPr_c<PredNot, 1, 0>; // not taken } multiclass JMPR_base<string BaseOp> { let BaseOpcode = BaseOp in { def NAME : T_JMPr; - defm _t : JMPR_Pred<0>; - defm _f : JMPR_Pred<1>; + defm t : JMPR_Pred<0>; + defm f : JMPR_Pred<1>; } } -let isTerminator = 1, neverHasSideEffects = 1 in { -let isBranch = 1 in -defm JMP : JMP_base<"JMP">, PredNewRel; +let isCall = 1, hasSideEffects = 1 in +class JUMPR_MISC_CALLR<bit isPred, bit isPredNot, + dag InputDag = (ins IntRegs:$Rs)> + : JRInst<(outs), InputDag, + !if(isPred, !if(isPredNot, "if (!$Pu) callr $Rs", + "if ($Pu) callr $Rs"), + "callr $Rs"), + [], "", J_tc_2early_SLOT2> { + bits<5> Rs; + bits<2> Pu; + let isPredicated = isPred; + let isPredicatedFalse = isPredNot; -let isBranch = 1, isIndirectBranch = 1 in -defm JMPR : JMPR_base<"JMPr">, PredNewRel; + let IClass = 0b0101; + let Inst{27-25} = 0b000; + let Inst{24-23} = !if (isPred, 0b10, 0b01); + let Inst{22} = 0; + let Inst{21} = isPredNot; + let Inst{9-8} = !if (isPred, Pu, 0b00); + let Inst{20-16} = Rs; -let isReturn = 1, isCodeGenOnly = 1 in -defm JMPret : JMPR_base<"JMPret">, PredNewRel; + } + +let Defs = VolatileV3.Regs, isCodeGenOnly = 0 in { + def J2_callrt : JUMPR_MISC_CALLR<1, 0, (ins PredRegs:$Pu, IntRegs:$Rs)>; + def J2_callrf : JUMPR_MISC_CALLR<1, 1, (ins PredRegs:$Pu, IntRegs:$Rs)>; } -def : Pat<(retflag), - (JMPret (i32 R31))>; +let isTerminator = 1, hasSideEffects = 0, isCodeGenOnly = 0 in { + defm J2_jump : JMP_base<"JMP", "">, PredNewRel; -def : Pat <(brcond (i1 PredRegs:$src1), bb:$offset), - (JMP_t (i1 PredRegs:$src1), bb:$offset)>; + // Deal with explicit assembly + // - never extened a jump #, always extend a jump ## + let isAsmParserOnly = 1 in { + defm J2_jump_ext : JMP_base<"JMP", "##">; + defm J2_jump_noext : JMP_base<"JMP", "#">; + } -// A return through builtin_eh_return. -let isReturn = 1, isTerminator = 1, isBarrier = 1, neverHasSideEffects = 1, -isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in -def EH_RETURN_JMPR : T_JMPr; + defm J2_jumpr : JMPR_base<"JMPr">, PredNewRel; + + let isReturn = 1, isCodeGenOnly = 1 in + defm JMPret : JMPR_base<"JMPret">, PredNewRel; +} -def : Pat<(eh_return), - (EH_RETURN_JMPR (i32 R31))>; +def: Pat<(br bb:$dst), + (J2_jump brtarget:$dst)>; +def: Pat<(retflag), + (JMPret (i32 R31))>; +def: Pat<(brcond (i1 PredRegs:$src1), bb:$offset), + (J2_jumpt PredRegs:$src1, bb:$offset)>; -def : Pat<(HexagonBR_JT (i32 IntRegs:$dst)), - (JMPR (i32 IntRegs:$dst))>; +// A return through builtin_eh_return. +let isReturn = 1, isTerminator = 1, isBarrier = 1, hasSideEffects = 0, + isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in +def EH_RETURN_JMPR : T_JMPr; -def : Pat<(brind (i32 IntRegs:$dst)), - (JMPR (i32 IntRegs:$dst))>; +def: Pat<(eh_return), + (EH_RETURN_JMPR (i32 R31))>; +def: Pat<(HexagonBR_JT (i32 IntRegs:$dst)), + (J2_jumpr IntRegs:$dst)>; +def: Pat<(brind (i32 IntRegs:$dst)), + (J2_jumpr IntRegs:$dst)>; //===----------------------------------------------------------------------===// // JR - @@ -900,265 +1451,502 @@ def : Pat<(brind (i32 IntRegs:$dst)), //===----------------------------------------------------------------------===// // LD + //===----------------------------------------------------------------------===// -/// -// Load -- MEMri operand -multiclass LD_MEMri_Pbase<string mnemonic, RegisterClass RC, - bit isNot, bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : LDInst2<(outs RC:$dst), - (ins PredRegs:$src1, MEMri:$addr), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#"$dst = "#mnemonic#"($addr)", - []>; -} +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, AddedComplexity = 20 in +class T_load_io <string mnemonic, RegisterClass RC, bits<4> MajOp, + Operand ImmOp> + : LDInst<(outs RC:$dst), (ins IntRegs:$src1, ImmOp:$offset), + "$dst = "#mnemonic#"($src1 + #$offset)", []>, AddrModeRel { + bits<4> name; + bits<5> dst; + bits<5> src1; + bits<14> offset; + bits<11> offsetBits; + + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "s11_3Ext"), offset{13-3}, + !if (!eq(ImmOpStr, "s11_2Ext"), offset{12-2}, + !if (!eq(ImmOpStr, "s11_1Ext"), offset{11-1}, + /* s11_0Ext */ offset{10-0}))); + let opExtentBits = !if (!eq(ImmOpStr, "s11_3Ext"), 14, + !if (!eq(ImmOpStr, "s11_2Ext"), 13, + !if (!eq(ImmOpStr, "s11_1Ext"), 12, + /* s11_0Ext */ 11))); + let hasNewValue = !if (!eq(ImmOpStr, "s11_3Ext"), 0, 1); + + let IClass = 0b1001; + + let Inst{27} = 0b0; + let Inst{26-25} = offsetBits{10-9}; + let Inst{24-21} = MajOp; + let Inst{20-16} = src1; + let Inst{13-5} = offsetBits{8-0}; + let Inst{4-0} = dst; + } -multiclass LD_MEMri_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : LD_MEMri_Pbase<mnemonic, RC, PredNot, 0>; - // Predicate new - defm _cdn#NAME : LD_MEMri_Pbase<mnemonic, RC, PredNot, 1>; +let opExtendable = 3, isExtentSigned = 0, isPredicated = 1 in +class T_pload_io <string mnemonic, RegisterClass RC, bits<4>MajOp, + Operand ImmOp, bit isNot, bit isPredNew> + : LDInst<(outs RC:$dst), + (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset), + "if ("#!if(isNot, "!$src1", "$src1") + #!if(isPredNew, ".new", "") + #") $dst = "#mnemonic#"($src2 + #$offset)", + [],"", V2LDST_tc_ld_SLOT01> , AddrModeRel { + bits<5> dst; + bits<2> src1; + bits<5> src2; + bits<9> offset; + bits<6> offsetBits; + string ImmOpStr = !cast<string>(ImmOp); + + let offsetBits = !if (!eq(ImmOpStr, "u6_3Ext"), offset{8-3}, + !if (!eq(ImmOpStr, "u6_2Ext"), offset{7-2}, + !if (!eq(ImmOpStr, "u6_1Ext"), offset{6-1}, + /* u6_0Ext */ offset{5-0}))); + let opExtentBits = !if (!eq(ImmOpStr, "u6_3Ext"), 9, + !if (!eq(ImmOpStr, "u6_2Ext"), 8, + !if (!eq(ImmOpStr, "u6_1Ext"), 7, + /* u6_0Ext */ 6))); + let hasNewValue = !if (!eq(ImmOpStr, "u6_3Ext"), 0, 1); + let isPredicatedNew = isPredNew; + let isPredicatedFalse = isNot; + + let IClass = 0b0100; + + let Inst{27} = 0b0; + let Inst{27} = 0b0; + let Inst{26} = isNot; + let Inst{25} = isPredNew; + let Inst{24-21} = MajOp; + let Inst{20-16} = src2; + let Inst{13} = 0b0; + let Inst{12-11} = src1; + let Inst{10-5} = offsetBits; + let Inst{4-0} = dst; } -} -let isExtendable = 1, neverHasSideEffects = 1 in -multiclass LD_MEMri<string mnemonic, string CextOp, RegisterClass RC, - bits<5> ImmBits, bits<5> PredImmBits> { +let isExtendable = 1, hasSideEffects = 0, addrMode = BaseImmOffset in +multiclass LD_Idxd<string mnemonic, string CextOp, RegisterClass RC, + Operand ImmOp, Operand predImmOp, bits<4>MajOp> { + let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in { + let isPredicable = 1 in + def L2_#NAME#_io : T_load_io <mnemonic, RC, MajOp, ImmOp>; - let CextOpcode = CextOp, BaseOpcode = CextOp in { - let opExtendable = 2, isExtentSigned = 1, opExtentBits = ImmBits, - isPredicable = 1 in - def NAME : LDInst2<(outs RC:$dst), (ins MEMri:$addr), - "$dst = "#mnemonic#"($addr)", - []>; - - let opExtendable = 3, isExtentSigned = 0, opExtentBits = PredImmBits, - isPredicated = 1 in { - defm Pt : LD_MEMri_Pred<mnemonic, RC, 0 >; - defm NotPt : LD_MEMri_Pred<mnemonic, RC, 1 >; - } + // Predicated + def L2_p#NAME#t_io : T_pload_io <mnemonic, RC, MajOp, predImmOp, 0, 0>; + def L2_p#NAME#f_io : T_pload_io <mnemonic, RC, MajOp, predImmOp, 1, 0>; + + // Predicated new + def L2_p#NAME#tnew_io : T_pload_io <mnemonic, RC, MajOp, predImmOp, 0, 1>; + def L2_p#NAME#fnew_io : T_pload_io <mnemonic, RC, MajOp, predImmOp, 1, 1>; } } -let addrMode = BaseImmOffset, isMEMri = "true" in { - let accessSize = ByteAccess in { - defm LDrib: LD_MEMri < "memb", "LDrib", IntRegs, 11, 6>, AddrModeRel; - defm LDriub: LD_MEMri < "memub" , "LDriub", IntRegs, 11, 6>, AddrModeRel; - } +let accessSize = ByteAccess, isCodeGenOnly = 0 in { + defm loadrb: LD_Idxd <"memb", "LDrib", IntRegs, s11_0Ext, u6_0Ext, 0b1000>; + defm loadrub: LD_Idxd <"memub", "LDriub", IntRegs, s11_0Ext, u6_0Ext, 0b1001>; +} - let accessSize = HalfWordAccess in { - defm LDrih: LD_MEMri < "memh", "LDrih", IntRegs, 12, 7>, AddrModeRel; - defm LDriuh: LD_MEMri < "memuh", "LDriuh", IntRegs, 12, 7>, AddrModeRel; - } +let accessSize = HalfWordAccess, opExtentAlign = 1, isCodeGenOnly = 0 in { + defm loadrh: LD_Idxd <"memh", "LDrih", IntRegs, s11_1Ext, u6_1Ext, 0b1010>; + defm loadruh: LD_Idxd <"memuh", "LDriuh", IntRegs, s11_1Ext, u6_1Ext, 0b1011>; +} - let accessSize = WordAccess in - defm LDriw: LD_MEMri < "memw", "LDriw", IntRegs, 13, 8>, AddrModeRel; +let accessSize = WordAccess, opExtentAlign = 2, isCodeGenOnly = 0 in +defm loadri: LD_Idxd <"memw", "LDriw", IntRegs, s11_2Ext, u6_2Ext, 0b1100>; - let accessSize = DoubleWordAccess in - defm LDrid: LD_MEMri < "memd", "LDrid", DoubleRegs, 14, 9>, AddrModeRel; -} +let accessSize = DoubleWordAccess, opExtentAlign = 3, isCodeGenOnly = 0 in +defm loadrd: LD_Idxd <"memd", "LDrid", DoubleRegs, s11_3Ext, u6_3Ext, 0b1110>; def : Pat < (i32 (sextloadi8 ADDRriS11_0:$addr)), - (LDrib ADDRriS11_0:$addr) >; + (L2_loadrb_io AddrFI:$addr, 0) >; def : Pat < (i32 (zextloadi8 ADDRriS11_0:$addr)), - (LDriub ADDRriS11_0:$addr) >; + (L2_loadrub_io AddrFI:$addr, 0) >; def : Pat < (i32 (sextloadi16 ADDRriS11_1:$addr)), - (LDrih ADDRriS11_1:$addr) >; + (L2_loadrh_io AddrFI:$addr, 0) >; def : Pat < (i32 (zextloadi16 ADDRriS11_1:$addr)), - (LDriuh ADDRriS11_1:$addr) >; + (L2_loadruh_io AddrFI:$addr, 0) >; def : Pat < (i32 (load ADDRriS11_2:$addr)), - (LDriw ADDRriS11_2:$addr) >; + (L2_loadri_io AddrFI:$addr, 0) >; def : Pat < (i64 (load ADDRriS11_3:$addr)), - (LDrid ADDRriS11_3:$addr) >; - - -// Load - Base with Immediate offset addressing mode -multiclass LD_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp, - bit isNot, bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : LDInst2<(outs RC:$dst), - (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#"$dst = "#mnemonic#"($src2+#$src3)", - []>; -} - -multiclass LD_Idxd_Pred<string mnemonic, RegisterClass RC, Operand predImmOp, - bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 0>; - // Predicate new - defm _cdn#NAME : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 1>; - } -} - -let isExtendable = 1, neverHasSideEffects = 1 in -multiclass LD_Idxd<string mnemonic, string CextOp, RegisterClass RC, - Operand ImmOp, Operand predImmOp, bits<5> ImmBits, - bits<5> PredImmBits> { - - let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in { - let opExtendable = 2, isExtentSigned = 1, opExtentBits = ImmBits, - isPredicable = 1, AddedComplexity = 20 in - def NAME : LDInst2<(outs RC:$dst), (ins IntRegs:$src1, ImmOp:$offset), - "$dst = "#mnemonic#"($src1+#$offset)", - []>; - - let opExtendable = 3, isExtentSigned = 0, opExtentBits = PredImmBits, - isPredicated = 1 in { - defm Pt : LD_Idxd_Pred<mnemonic, RC, predImmOp, 0 >; - defm NotPt : LD_Idxd_Pred<mnemonic, RC, predImmOp, 1 >; - } - } -} - -let addrMode = BaseImmOffset in { - let accessSize = ByteAccess in { - defm LDrib_indexed: LD_Idxd <"memb", "LDrib", IntRegs, s11_0Ext, u6_0Ext, - 11, 6>, AddrModeRel; - defm LDriub_indexed: LD_Idxd <"memub" , "LDriub", IntRegs, s11_0Ext, u6_0Ext, - 11, 6>, AddrModeRel; - } - let accessSize = HalfWordAccess in { - defm LDrih_indexed: LD_Idxd <"memh", "LDrih", IntRegs, s11_1Ext, u6_1Ext, - 12, 7>, AddrModeRel; - defm LDriuh_indexed: LD_Idxd <"memuh", "LDriuh", IntRegs, s11_1Ext, u6_1Ext, - 12, 7>, AddrModeRel; - } - let accessSize = WordAccess in - defm LDriw_indexed: LD_Idxd <"memw", "LDriw", IntRegs, s11_2Ext, u6_2Ext, - 13, 8>, AddrModeRel; - - let accessSize = DoubleWordAccess in - defm LDrid_indexed: LD_Idxd <"memd", "LDrid", DoubleRegs, s11_3Ext, u6_3Ext, - 14, 9>, AddrModeRel; -} + (L2_loadrd_io AddrFI:$addr, 0) >; let AddedComplexity = 20 in { def : Pat < (i32 (sextloadi8 (add IntRegs:$src1, s11_0ExtPred:$offset))), - (LDrib_indexed IntRegs:$src1, s11_0ExtPred:$offset) >; + (L2_loadrb_io IntRegs:$src1, s11_0ExtPred:$offset) >; def : Pat < (i32 (zextloadi8 (add IntRegs:$src1, s11_0ExtPred:$offset))), - (LDriub_indexed IntRegs:$src1, s11_0ExtPred:$offset) >; + (L2_loadrub_io IntRegs:$src1, s11_0ExtPred:$offset) >; def : Pat < (i32 (sextloadi16 (add IntRegs:$src1, s11_1ExtPred:$offset))), - (LDrih_indexed IntRegs:$src1, s11_1ExtPred:$offset) >; + (L2_loadrh_io IntRegs:$src1, s11_1ExtPred:$offset) >; def : Pat < (i32 (zextloadi16 (add IntRegs:$src1, s11_1ExtPred:$offset))), - (LDriuh_indexed IntRegs:$src1, s11_1ExtPred:$offset) >; + (L2_loadruh_io IntRegs:$src1, s11_1ExtPred:$offset) >; def : Pat < (i32 (load (add IntRegs:$src1, s11_2ExtPred:$offset))), - (LDriw_indexed IntRegs:$src1, s11_2ExtPred:$offset) >; + (L2_loadri_io IntRegs:$src1, s11_2ExtPred:$offset) >; def : Pat < (i64 (load (add IntRegs:$src1, s11_3ExtPred:$offset))), - (LDrid_indexed IntRegs:$src1, s11_3ExtPred:$offset) >; + (L2_loadrd_io IntRegs:$src1, s11_3ExtPred:$offset) >; } //===----------------------------------------------------------------------===// // Post increment load //===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// Template class for non-predicated post increment loads with immediate offset. +//===----------------------------------------------------------------------===// +let hasSideEffects = 0, addrMode = PostInc in +class T_load_pi <string mnemonic, RegisterClass RC, Operand ImmOp, + bits<4> MajOp > + : LDInstPI <(outs RC:$dst, IntRegs:$dst2), + (ins IntRegs:$src1, ImmOp:$offset), + "$dst = "#mnemonic#"($src1++#$offset)" , + [], + "$src1 = $dst2" > , + PredNewRel { + bits<5> dst; + bits<5> src1; + bits<7> offset; + bits<4> offsetBits; + + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "s4_3Imm"), offset{6-3}, + !if (!eq(ImmOpStr, "s4_2Imm"), offset{5-2}, + !if (!eq(ImmOpStr, "s4_1Imm"), offset{4-1}, + /* s4_0Imm */ offset{3-0}))); + let hasNewValue = !if (!eq(ImmOpStr, "s4_3Imm"), 0, 1); + + let IClass = 0b1001; + + let Inst{27-25} = 0b101; + let Inst{24-21} = MajOp; + let Inst{20-16} = src1; + let Inst{13-12} = 0b00; + let Inst{8-5} = offsetBits; + let Inst{4-0} = dst; + } -multiclass LD_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp, - bit isNot, bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : LDInst2PI<(outs RC:$dst, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#"$dst = "#mnemonic#"($src2++#$offset)", - [], - "$src2 = $dst2">; -} +//===----------------------------------------------------------------------===// +// Template class for predicated post increment loads with immediate offset. +//===----------------------------------------------------------------------===// +let isPredicated = 1, hasSideEffects = 0, addrMode = PostInc in +class T_pload_pi <string mnemonic, RegisterClass RC, Operand ImmOp, + bits<4> MajOp, bit isPredNot, bit isPredNew > + : LDInst <(outs RC:$dst, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset), + !if(isPredNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#"$dst = "#mnemonic#"($src2++#$offset)", + [] , + "$src2 = $dst2" > , + PredNewRel { + bits<5> dst; + bits<2> src1; + bits<5> src2; + bits<7> offset; + bits<4> offsetBits; -multiclass LD_PostInc_Pred<string mnemonic, RegisterClass RC, - Operand ImmOp, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : LD_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 0>; - // Predicate new - let Predicates = [HasV4T], validSubTargets = HasV4SubT in - defm _cdn#NAME#_V4 : LD_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 1>; + let isPredicatedNew = isPredNew; + let isPredicatedFalse = isPredNot; + + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "s4_3Imm"), offset{6-3}, + !if (!eq(ImmOpStr, "s4_2Imm"), offset{5-2}, + !if (!eq(ImmOpStr, "s4_1Imm"), offset{4-1}, + /* s4_0Imm */ offset{3-0}))); + let hasNewValue = !if (!eq(ImmOpStr, "s4_3Imm"), 0, 1); + + let IClass = 0b1001; + + let Inst{27-25} = 0b101; + let Inst{24-21} = MajOp; + let Inst{20-16} = src2; + let Inst{13} = 0b1; + let Inst{12} = isPredNew; + let Inst{11} = isPredNot; + let Inst{10-9} = src1; + let Inst{8-5} = offsetBits; + let Inst{4-0} = dst; } -} -multiclass LD_PostInc<string mnemonic, string BaseOp, RegisterClass RC, - Operand ImmOp> { +//===----------------------------------------------------------------------===// +// Multiclass for post increment loads with immediate offset. +//===----------------------------------------------------------------------===// +multiclass LD_PostInc <string mnemonic, string BaseOp, RegisterClass RC, + Operand ImmOp, bits<4> MajOp> { let BaseOpcode = "POST_"#BaseOp in { let isPredicable = 1 in - def NAME : LDInst2PI<(outs RC:$dst, IntRegs:$dst2), - (ins IntRegs:$src1, ImmOp:$offset), - "$dst = "#mnemonic#"($src1++#$offset)", - [], - "$src1 = $dst2">; - - let isPredicated = 1 in { - defm Pt : LD_PostInc_Pred<mnemonic, RC, ImmOp, 0 >; - defm NotPt : LD_PostInc_Pred<mnemonic, RC, ImmOp, 1 >; - } + def L2_#NAME#_pi : T_load_pi < mnemonic, RC, ImmOp, MajOp>; + + // Predicated + def L2_p#NAME#t_pi : T_pload_pi < mnemonic, RC, ImmOp, MajOp, 0, 0>; + def L2_p#NAME#f_pi : T_pload_pi < mnemonic, RC, ImmOp, MajOp, 1, 0>; + + // Predicated new + def L2_p#NAME#tnew_pi : T_pload_pi < mnemonic, RC, ImmOp, MajOp, 0, 1>; + def L2_p#NAME#fnew_pi : T_pload_pi < mnemonic, RC, ImmOp, MajOp, 1, 1>; } } -let hasCtrlDep = 1, neverHasSideEffects = 1, addrMode = PostInc in { - defm POST_LDrib : LD_PostInc<"memb", "LDrib", IntRegs, s4_0Imm>, - PredNewRel; - defm POST_LDriub : LD_PostInc<"memub", "LDriub", IntRegs, s4_0Imm>, - PredNewRel; - defm POST_LDrih : LD_PostInc<"memh", "LDrih", IntRegs, s4_1Imm>, - PredNewRel; - defm POST_LDriuh : LD_PostInc<"memuh", "LDriuh", IntRegs, s4_1Imm>, - PredNewRel; - defm POST_LDriw : LD_PostInc<"memw", "LDriw", IntRegs, s4_2Imm>, - PredNewRel; - defm POST_LDrid : LD_PostInc<"memd", "LDrid", DoubleRegs, s4_3Imm>, - PredNewRel; +// post increment byte loads with immediate offset +let accessSize = ByteAccess, isCodeGenOnly = 0 in { + defm loadrb : LD_PostInc <"memb", "LDrib", IntRegs, s4_0Imm, 0b1000>; + defm loadrub : LD_PostInc <"memub", "LDriub", IntRegs, s4_0Imm, 0b1001>; } +// post increment halfword loads with immediate offset +let accessSize = HalfWordAccess, opExtentAlign = 1, isCodeGenOnly = 0 in { + defm loadrh : LD_PostInc <"memh", "LDrih", IntRegs, s4_1Imm, 0b1010>; + defm loadruh : LD_PostInc <"memuh", "LDriuh", IntRegs, s4_1Imm, 0b1011>; +} + +// post increment word loads with immediate offset +let accessSize = WordAccess, opExtentAlign = 2, isCodeGenOnly = 0 in +defm loadri : LD_PostInc <"memw", "LDriw", IntRegs, s4_2Imm, 0b1100>; + +// post increment doubleword loads with immediate offset +let accessSize = DoubleWordAccess, opExtentAlign = 3, isCodeGenOnly = 0 in +defm loadrd : LD_PostInc <"memd", "LDrid", DoubleRegs, s4_3Imm, 0b1110>; + def : Pat< (i32 (extloadi1 ADDRriS11_0:$addr)), - (i32 (LDrib ADDRriS11_0:$addr)) >; + (i32 (L2_loadrb_io AddrFI:$addr, 0)) >; // Load byte any-extend. def : Pat < (i32 (extloadi8 ADDRriS11_0:$addr)), - (i32 (LDrib ADDRriS11_0:$addr)) >; + (i32 (L2_loadrb_io AddrFI:$addr, 0)) >; // Indexed load byte any-extend. let AddedComplexity = 20 in def : Pat < (i32 (extloadi8 (add IntRegs:$src1, s11_0ImmPred:$offset))), - (i32 (LDrib_indexed IntRegs:$src1, s11_0ImmPred:$offset)) >; + (i32 (L2_loadrb_io IntRegs:$src1, s11_0ImmPred:$offset)) >; def : Pat < (i32 (extloadi16 ADDRriS11_1:$addr)), - (i32 (LDrih ADDRriS11_1:$addr))>; + (i32 (L2_loadrh_io AddrFI:$addr, 0))>; let AddedComplexity = 20 in def : Pat < (i32 (extloadi16 (add IntRegs:$src1, s11_1ImmPred:$offset))), - (i32 (LDrih_indexed IntRegs:$src1, s11_1ImmPred:$offset)) >; + (i32 (L2_loadrh_io IntRegs:$src1, s11_1ImmPred:$offset)) >; let AddedComplexity = 10 in def : Pat < (i32 (zextloadi1 ADDRriS11_0:$addr)), - (i32 (LDriub ADDRriS11_0:$addr))>; + (i32 (L2_loadrub_io AddrFI:$addr, 0))>; let AddedComplexity = 20 in def : Pat < (i32 (zextloadi1 (add IntRegs:$src1, s11_0ImmPred:$offset))), - (i32 (LDriub_indexed IntRegs:$src1, s11_0ImmPred:$offset))>; + (i32 (L2_loadrub_io IntRegs:$src1, s11_0ImmPred:$offset))>; + +//===----------------------------------------------------------------------===// +// Template class for post increment loads with register offset. +//===----------------------------------------------------------------------===// +let hasSideEffects = 0, addrMode = PostInc in +class T_load_pr <string mnemonic, RegisterClass RC, bits<4> MajOp, + MemAccessSize AccessSz> + : LDInstPI <(outs RC:$dst, IntRegs:$_dst_), + (ins IntRegs:$src1, ModRegs:$src2), + "$dst = "#mnemonic#"($src1++$src2)" , + [], "$src1 = $_dst_" > { + bits<5> dst; + bits<5> src1; + bits<1> src2; + + let accessSize = AccessSz; + let IClass = 0b1001; + + let Inst{27-25} = 0b110; + let Inst{24-21} = MajOp; + let Inst{20-16} = src1; + let Inst{13} = src2; + let Inst{12} = 0b0; + let Inst{7} = 0b0; + let Inst{4-0} = dst; + } + +let hasNewValue = 1, isCodeGenOnly = 0 in { + def L2_loadrb_pr : T_load_pr <"memb", IntRegs, 0b1000, ByteAccess>; + def L2_loadrub_pr : T_load_pr <"memub", IntRegs, 0b1001, ByteAccess>; + def L2_loadrh_pr : T_load_pr <"memh", IntRegs, 0b1010, HalfWordAccess>; + def L2_loadruh_pr : T_load_pr <"memuh", IntRegs, 0b1011, HalfWordAccess>; + def L2_loadri_pr : T_load_pr <"memw", IntRegs, 0b1100, WordAccess>; +} + +let isCodeGenOnly = 0 in +def L2_loadrd_pr : T_load_pr <"memd", DoubleRegs, 0b1110, DoubleWordAccess>; // Load predicate. let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13, -isPseudo = 1, Defs = [R10,R11,D5], neverHasSideEffects = 1 in +isPseudo = 1, Defs = [R10,R11,D5], hasSideEffects = 0 in def LDriw_pred : LDInst2<(outs PredRegs:$dst), (ins MEMri:$addr), "Error; should not emit", []>; -// Deallocate stack frame. -let Defs = [R29, R30, R31], Uses = [R29], neverHasSideEffects = 1 in { - def DEALLOCFRAME : LDInst2<(outs), (ins), +let Defs = [R29, R30, R31], Uses = [R30], hasSideEffects = 0, isCodeGenOnly = 0 in + def L2_deallocframe : LDInst<(outs), (ins), "deallocframe", - []>; + []> { + let IClass = 0b1001; + + let Inst{27-16} = 0b000000011110; + let Inst{13} = 0b0; + let Inst{4-0} = 0b11110; +} + +// Load / Post increment circular addressing mode. +let Uses = [CS], hasSideEffects = 0, hasNewValue = 1, opNewValue = 0 in +class T_load_pcr<string mnemonic, RegisterClass RC, bits<4> MajOp> + : LDInst <(outs RC:$dst, IntRegs:$_dst_), + (ins IntRegs:$Rz, ModRegs:$Mu), + "$dst = "#mnemonic#"($Rz ++ I:circ($Mu))", [], + "$Rz = $_dst_" > { + bits<5> dst; + bits<5> Rz; + bit Mu; + + let IClass = 0b1001; + + let Inst{27-25} = 0b100; + let Inst{24-21} = MajOp; + let Inst{20-16} = Rz; + let Inst{13} = Mu; + let Inst{12} = 0b0; + let Inst{9} = 0b1; + let Inst{7} = 0b0; + let Inst{4-0} = dst; + } + +let accessSize = ByteAccess, isCodeGenOnly = 0 in { + def L2_loadrb_pcr : T_load_pcr <"memb", IntRegs, 0b1000>; + def L2_loadrub_pcr : T_load_pcr <"memub", IntRegs, 0b1001>; +} + +let accessSize = HalfWordAccess, isCodeGenOnly = 0 in { + def L2_loadrh_pcr : T_load_pcr <"memh", IntRegs, 0b1010>; + def L2_loadruh_pcr : T_load_pcr <"memuh", IntRegs, 0b1011>; +} + +let accessSize = WordAccess, isCodeGenOnly = 0 in { + def L2_loadri_pcr : T_load_pcr <"memw", IntRegs, 0b1100>; } -// Load and unpack bytes to halfwords. +let accessSize = DoubleWordAccess, isCodeGenOnly = 0 in +def L2_loadrd_pcr : T_load_pcr <"memd", DoubleRegs, 0b1110>; + +//===----------------------------------------------------------------------===// +// Circular loads with immediate offset. +//===----------------------------------------------------------------------===// +let Uses = [CS], mayLoad = 1, hasSideEffects = 0, hasNewValue = 1 in +class T_load_pci <string mnemonic, RegisterClass RC, + Operand ImmOp, bits<4> MajOp> + : LDInstPI<(outs RC:$dst, IntRegs:$_dst_), + (ins IntRegs:$Rz, ImmOp:$offset, ModRegs:$Mu), + "$dst = "#mnemonic#"($Rz ++ #$offset:circ($Mu))", [], + "$Rz = $_dst_"> { + bits<5> dst; + bits<5> Rz; + bits<1> Mu; + bits<7> offset; + bits<4> offsetBits; + + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "s4_3Imm"), offset{6-3}, + !if (!eq(ImmOpStr, "s4_2Imm"), offset{5-2}, + !if (!eq(ImmOpStr, "s4_1Imm"), offset{4-1}, + /* s4_0Imm */ offset{3-0}))); + let IClass = 0b1001; + let Inst{27-25} = 0b100; + let Inst{24-21} = MajOp; + let Inst{20-16} = Rz; + let Inst{13} = Mu; + let Inst{12} = 0b0; + let Inst{9} = 0b0; + let Inst{8-5} = offsetBits; + let Inst{4-0} = dst; + } + +// Byte variants of circ load +let accessSize = ByteAccess, isCodeGenOnly = 0 in { + def L2_loadrb_pci : T_load_pci <"memb", IntRegs, s4_0Imm, 0b1000>; + def L2_loadrub_pci : T_load_pci <"memub", IntRegs, s4_0Imm, 0b1001>; +} + +// Half word variants of circ load +let accessSize = HalfWordAccess, isCodeGenOnly = 0 in { + def L2_loadrh_pci : T_load_pci <"memh", IntRegs, s4_1Imm, 0b1010>; + def L2_loadruh_pci : T_load_pci <"memuh", IntRegs, s4_1Imm, 0b1011>; +} + +// Word variants of circ load +let accessSize = WordAccess, isCodeGenOnly = 0 in +def L2_loadri_pci : T_load_pci <"memw", IntRegs, s4_2Imm, 0b1100>; + +let accessSize = DoubleWordAccess, hasNewValue = 0, isCodeGenOnly = 0 in +def L2_loadrd_pci : T_load_pci <"memd", DoubleRegs, s4_3Imm, 0b1110>; + +// L[24]_load[wd]_locked: Load word/double with lock. +let isSoloAX = 1 in +class T_load_locked <string mnemonic, RegisterClass RC> + : LD0Inst <(outs RC:$dst), + (ins IntRegs:$src), + "$dst = "#mnemonic#"($src)"> { + bits<5> dst; + bits<5> src; + let IClass = 0b1001; + let Inst{27-21} = 0b0010000; + let Inst{20-16} = src; + let Inst{13-12} = !if (!eq(mnemonic, "memd_locked"), 0b01, 0b00); + let Inst{4-0} = dst; +} +let hasNewValue = 1, accessSize = WordAccess, opNewValue = 0, isCodeGenOnly = 0 in + def L2_loadw_locked : T_load_locked <"memw_locked", IntRegs>; +let accessSize = DoubleWordAccess, isCodeGenOnly = 0 in + def L4_loadd_locked : T_load_locked <"memd_locked", DoubleRegs>; +//===----------------------------------------------------------------------===// +// Bit-reversed loads with auto-increment register +//===----------------------------------------------------------------------===// +let hasSideEffects = 0 in +class T_load_pbr<string mnemonic, RegisterClass RC, + MemAccessSize addrSize, bits<4> majOp> + : LDInst + <(outs RC:$dst, IntRegs:$_dst_), + (ins IntRegs:$Rz, ModRegs:$Mu), + "$dst = "#mnemonic#"($Rz ++ $Mu:brev)" , + [] , "$Rz = $_dst_" > { + + let accessSize = addrSize; + + bits<5> dst; + bits<5> Rz; + bits<1> Mu; + + let IClass = 0b1001; + + let Inst{27-25} = 0b111; + let Inst{24-21} = majOp; + let Inst{20-16} = Rz; + let Inst{13} = Mu; + let Inst{12} = 0b0; + let Inst{7} = 0b0; + let Inst{4-0} = dst; + } + +let hasNewValue =1, opNewValue = 0, isCodeGenOnly = 0 in { + def L2_loadrb_pbr : T_load_pbr <"memb", IntRegs, ByteAccess, 0b1000>; + def L2_loadrub_pbr : T_load_pbr <"memub", IntRegs, ByteAccess, 0b1001>; + def L2_loadrh_pbr : T_load_pbr <"memh", IntRegs, HalfWordAccess, 0b1010>; + def L2_loadruh_pbr : T_load_pbr <"memuh", IntRegs, HalfWordAccess, 0b1011>; + def L2_loadri_pbr : T_load_pbr <"memw", IntRegs, WordAccess, 0b1100>; +} + +let isCodeGenOnly = 0 in +def L2_loadrd_pbr : T_load_pbr <"memd", DoubleRegs, DoubleWordAccess, 0b1110>; + //===----------------------------------------------------------------------===// // LD - //===----------------------------------------------------------------------===// @@ -1180,180 +1968,663 @@ let Defs = [R29, R30, R31], Uses = [R29], neverHasSideEffects = 1 in { //===----------------------------------------------------------------------===// // MTYPE/MPYH + //===----------------------------------------------------------------------===// -// Multiply and use lower result. -// Rd=+mpyi(Rs,#u8) -let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 8 in -def MPYI_riu : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u8Ext:$src2), - "$dst =+ mpyi($src1, #$src2)", - [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1), - u8ExtPred:$src2))]>; -// Rd=-mpyi(Rs,#u8) -def MPYI_rin : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u8Imm:$src2), - "$dst =- mpyi($src1, #$src2)", - [(set (i32 IntRegs:$dst), (ineg (mul (i32 IntRegs:$src1), - u8ImmPred:$src2)))]>; +//===----------------------------------------------------------------------===// +// Template Class +// MPYS / Multipy signed/unsigned halfwords +//Rd=mpy[u](Rs.[H|L],Rt.[H|L])[:<<1][:rnd][:sat] +//===----------------------------------------------------------------------===// + +let hasNewValue = 1, opNewValue = 0 in +class T_M2_mpy < bits<2> LHbits, bit isSat, bit isRnd, + bit hasShift, bit isUnsigned> + : MInst < (outs IntRegs:$Rd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = "#!if(isUnsigned,"mpyu","mpy")#"($Rs."#!if(LHbits{1},"h","l") + #", $Rt."#!if(LHbits{0},"h)","l)") + #!if(hasShift,":<<1","") + #!if(isRnd,":rnd","") + #!if(isSat,":sat",""), + [], "", M_tc_3x_SLOT23 > { + bits<5> Rd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + + let Inst{27-24} = 0b1100; + let Inst{23} = hasShift; + let Inst{22} = isUnsigned; + let Inst{21} = isRnd; + let Inst{7} = isSat; + let Inst{6-5} = LHbits; + let Inst{4-0} = Rd; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + } + +//Rd=mpy(Rs.[H|L],Rt.[H|L])[:<<1] +let isCodeGenOnly = 0 in { +def M2_mpy_ll_s1: T_M2_mpy<0b00, 0, 0, 1, 0>; +def M2_mpy_ll_s0: T_M2_mpy<0b00, 0, 0, 0, 0>; +def M2_mpy_lh_s1: T_M2_mpy<0b01, 0, 0, 1, 0>; +def M2_mpy_lh_s0: T_M2_mpy<0b01, 0, 0, 0, 0>; +def M2_mpy_hl_s1: T_M2_mpy<0b10, 0, 0, 1, 0>; +def M2_mpy_hl_s0: T_M2_mpy<0b10, 0, 0, 0, 0>; +def M2_mpy_hh_s1: T_M2_mpy<0b11, 0, 0, 1, 0>; +def M2_mpy_hh_s0: T_M2_mpy<0b11, 0, 0, 0, 0>; +} + +//Rd=mpyu(Rs.[H|L],Rt.[H|L])[:<<1] +let isCodeGenOnly = 0 in { +def M2_mpyu_ll_s1: T_M2_mpy<0b00, 0, 0, 1, 1>; +def M2_mpyu_ll_s0: T_M2_mpy<0b00, 0, 0, 0, 1>; +def M2_mpyu_lh_s1: T_M2_mpy<0b01, 0, 0, 1, 1>; +def M2_mpyu_lh_s0: T_M2_mpy<0b01, 0, 0, 0, 1>; +def M2_mpyu_hl_s1: T_M2_mpy<0b10, 0, 0, 1, 1>; +def M2_mpyu_hl_s0: T_M2_mpy<0b10, 0, 0, 0, 1>; +def M2_mpyu_hh_s1: T_M2_mpy<0b11, 0, 0, 1, 1>; +def M2_mpyu_hh_s0: T_M2_mpy<0b11, 0, 0, 0, 1>; +} + +//Rd=mpy(Rs.[H|L],Rt.[H|L])[:<<1]:rnd +let isCodeGenOnly = 0 in { +def M2_mpy_rnd_ll_s1: T_M2_mpy <0b00, 0, 1, 1, 0>; +def M2_mpy_rnd_ll_s0: T_M2_mpy <0b00, 0, 1, 0, 0>; +def M2_mpy_rnd_lh_s1: T_M2_mpy <0b01, 0, 1, 1, 0>; +def M2_mpy_rnd_lh_s0: T_M2_mpy <0b01, 0, 1, 0, 0>; +def M2_mpy_rnd_hl_s1: T_M2_mpy <0b10, 0, 1, 1, 0>; +def M2_mpy_rnd_hl_s0: T_M2_mpy <0b10, 0, 1, 0, 0>; +def M2_mpy_rnd_hh_s1: T_M2_mpy <0b11, 0, 1, 1, 0>; +def M2_mpy_rnd_hh_s0: T_M2_mpy <0b11, 0, 1, 0, 0>; +} + +//Rd=mpy(Rs.[H|L],Rt.[H|L])[:<<1][:sat] +//Rd=mpy(Rs.[H|L],Rt.[H|L])[:<<1][:rnd][:sat] +let Defs = [USR_OVF], isCodeGenOnly = 0 in { + def M2_mpy_sat_ll_s1: T_M2_mpy <0b00, 1, 0, 1, 0>; + def M2_mpy_sat_ll_s0: T_M2_mpy <0b00, 1, 0, 0, 0>; + def M2_mpy_sat_lh_s1: T_M2_mpy <0b01, 1, 0, 1, 0>; + def M2_mpy_sat_lh_s0: T_M2_mpy <0b01, 1, 0, 0, 0>; + def M2_mpy_sat_hl_s1: T_M2_mpy <0b10, 1, 0, 1, 0>; + def M2_mpy_sat_hl_s0: T_M2_mpy <0b10, 1, 0, 0, 0>; + def M2_mpy_sat_hh_s1: T_M2_mpy <0b11, 1, 0, 1, 0>; + def M2_mpy_sat_hh_s0: T_M2_mpy <0b11, 1, 0, 0, 0>; + + def M2_mpy_sat_rnd_ll_s1: T_M2_mpy <0b00, 1, 1, 1, 0>; + def M2_mpy_sat_rnd_ll_s0: T_M2_mpy <0b00, 1, 1, 0, 0>; + def M2_mpy_sat_rnd_lh_s1: T_M2_mpy <0b01, 1, 1, 1, 0>; + def M2_mpy_sat_rnd_lh_s0: T_M2_mpy <0b01, 1, 1, 0, 0>; + def M2_mpy_sat_rnd_hl_s1: T_M2_mpy <0b10, 1, 1, 1, 0>; + def M2_mpy_sat_rnd_hl_s0: T_M2_mpy <0b10, 1, 1, 0, 0>; + def M2_mpy_sat_rnd_hh_s1: T_M2_mpy <0b11, 1, 1, 1, 0>; + def M2_mpy_sat_rnd_hh_s0: T_M2_mpy <0b11, 1, 1, 0, 0>; +} + +//===----------------------------------------------------------------------===// +// Template Class +// MPYS / Multipy signed/unsigned halfwords and add/subtract the +// result from the accumulator. +//Rx [-+]= mpy[u](Rs.[H|L],Rt.[H|L])[:<<1][:sat] +//===----------------------------------------------------------------------===// + +let hasNewValue = 1, opNewValue = 0 in +class T_M2_mpy_acc < bits<2> LHbits, bit isSat, bit isNac, + bit hasShift, bit isUnsigned > + : MInst_acc<(outs IntRegs:$Rx), (ins IntRegs:$dst2, IntRegs:$Rs, IntRegs:$Rt), + "$Rx "#!if(isNac,"-= ","+= ")#!if(isUnsigned,"mpyu","mpy") + #"($Rs."#!if(LHbits{1},"h","l") + #", $Rt."#!if(LHbits{0},"h)","l)") + #!if(hasShift,":<<1","") + #!if(isSat,":sat",""), + [], "$dst2 = $Rx", M_tc_3x_SLOT23 > { + bits<5> Rx; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + let Inst{27-24} = 0b1110; + let Inst{23} = hasShift; + let Inst{22} = isUnsigned; + let Inst{21} = isNac; + let Inst{7} = isSat; + let Inst{6-5} = LHbits; + let Inst{4-0} = Rx; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + } + +//Rx += mpy(Rs.[H|L],Rt.[H|L])[:<<1] +let isCodeGenOnly = 0 in { +def M2_mpy_acc_ll_s1: T_M2_mpy_acc <0b00, 0, 0, 1, 0>; +def M2_mpy_acc_ll_s0: T_M2_mpy_acc <0b00, 0, 0, 0, 0>; +def M2_mpy_acc_lh_s1: T_M2_mpy_acc <0b01, 0, 0, 1, 0>; +def M2_mpy_acc_lh_s0: T_M2_mpy_acc <0b01, 0, 0, 0, 0>; +def M2_mpy_acc_hl_s1: T_M2_mpy_acc <0b10, 0, 0, 1, 0>; +def M2_mpy_acc_hl_s0: T_M2_mpy_acc <0b10, 0, 0, 0, 0>; +def M2_mpy_acc_hh_s1: T_M2_mpy_acc <0b11, 0, 0, 1, 0>; +def M2_mpy_acc_hh_s0: T_M2_mpy_acc <0b11, 0, 0, 0, 0>; +} + +//Rx += mpyu(Rs.[H|L],Rt.[H|L])[:<<1] +let isCodeGenOnly = 0 in { +def M2_mpyu_acc_ll_s1: T_M2_mpy_acc <0b00, 0, 0, 1, 1>; +def M2_mpyu_acc_ll_s0: T_M2_mpy_acc <0b00, 0, 0, 0, 1>; +def M2_mpyu_acc_lh_s1: T_M2_mpy_acc <0b01, 0, 0, 1, 1>; +def M2_mpyu_acc_lh_s0: T_M2_mpy_acc <0b01, 0, 0, 0, 1>; +def M2_mpyu_acc_hl_s1: T_M2_mpy_acc <0b10, 0, 0, 1, 1>; +def M2_mpyu_acc_hl_s0: T_M2_mpy_acc <0b10, 0, 0, 0, 1>; +def M2_mpyu_acc_hh_s1: T_M2_mpy_acc <0b11, 0, 0, 1, 1>; +def M2_mpyu_acc_hh_s0: T_M2_mpy_acc <0b11, 0, 0, 0, 1>; +} + +//Rx -= mpy(Rs.[H|L],Rt.[H|L])[:<<1] +let isCodeGenOnly = 0 in { +def M2_mpy_nac_ll_s1: T_M2_mpy_acc <0b00, 0, 1, 1, 0>; +def M2_mpy_nac_ll_s0: T_M2_mpy_acc <0b00, 0, 1, 0, 0>; +def M2_mpy_nac_lh_s1: T_M2_mpy_acc <0b01, 0, 1, 1, 0>; +def M2_mpy_nac_lh_s0: T_M2_mpy_acc <0b01, 0, 1, 0, 0>; +def M2_mpy_nac_hl_s1: T_M2_mpy_acc <0b10, 0, 1, 1, 0>; +def M2_mpy_nac_hl_s0: T_M2_mpy_acc <0b10, 0, 1, 0, 0>; +def M2_mpy_nac_hh_s1: T_M2_mpy_acc <0b11, 0, 1, 1, 0>; +def M2_mpy_nac_hh_s0: T_M2_mpy_acc <0b11, 0, 1, 0, 0>; +} + +//Rx -= mpyu(Rs.[H|L],Rt.[H|L])[:<<1] +let isCodeGenOnly = 0 in { +def M2_mpyu_nac_ll_s1: T_M2_mpy_acc <0b00, 0, 1, 1, 1>; +def M2_mpyu_nac_ll_s0: T_M2_mpy_acc <0b00, 0, 1, 0, 1>; +def M2_mpyu_nac_lh_s1: T_M2_mpy_acc <0b01, 0, 1, 1, 1>; +def M2_mpyu_nac_lh_s0: T_M2_mpy_acc <0b01, 0, 1, 0, 1>; +def M2_mpyu_nac_hl_s1: T_M2_mpy_acc <0b10, 0, 1, 1, 1>; +def M2_mpyu_nac_hl_s0: T_M2_mpy_acc <0b10, 0, 1, 0, 1>; +def M2_mpyu_nac_hh_s1: T_M2_mpy_acc <0b11, 0, 1, 1, 1>; +def M2_mpyu_nac_hh_s0: T_M2_mpy_acc <0b11, 0, 1, 0, 1>; +} + +//Rx += mpy(Rs.[H|L],Rt.[H|L])[:<<1]:sat +let isCodeGenOnly = 0 in { +def M2_mpy_acc_sat_ll_s1: T_M2_mpy_acc <0b00, 1, 0, 1, 0>; +def M2_mpy_acc_sat_ll_s0: T_M2_mpy_acc <0b00, 1, 0, 0, 0>; +def M2_mpy_acc_sat_lh_s1: T_M2_mpy_acc <0b01, 1, 0, 1, 0>; +def M2_mpy_acc_sat_lh_s0: T_M2_mpy_acc <0b01, 1, 0, 0, 0>; +def M2_mpy_acc_sat_hl_s1: T_M2_mpy_acc <0b10, 1, 0, 1, 0>; +def M2_mpy_acc_sat_hl_s0: T_M2_mpy_acc <0b10, 1, 0, 0, 0>; +def M2_mpy_acc_sat_hh_s1: T_M2_mpy_acc <0b11, 1, 0, 1, 0>; +def M2_mpy_acc_sat_hh_s0: T_M2_mpy_acc <0b11, 1, 0, 0, 0>; +} + +//Rx -= mpy(Rs.[H|L],Rt.[H|L])[:<<1]:sat +let isCodeGenOnly = 0 in { +def M2_mpy_nac_sat_ll_s1: T_M2_mpy_acc <0b00, 1, 1, 1, 0>; +def M2_mpy_nac_sat_ll_s0: T_M2_mpy_acc <0b00, 1, 1, 0, 0>; +def M2_mpy_nac_sat_lh_s1: T_M2_mpy_acc <0b01, 1, 1, 1, 0>; +def M2_mpy_nac_sat_lh_s0: T_M2_mpy_acc <0b01, 1, 1, 0, 0>; +def M2_mpy_nac_sat_hl_s1: T_M2_mpy_acc <0b10, 1, 1, 1, 0>; +def M2_mpy_nac_sat_hl_s0: T_M2_mpy_acc <0b10, 1, 1, 0, 0>; +def M2_mpy_nac_sat_hh_s1: T_M2_mpy_acc <0b11, 1, 1, 1, 0>; +def M2_mpy_nac_sat_hh_s0: T_M2_mpy_acc <0b11, 1, 1, 0, 0>; +} + +//===----------------------------------------------------------------------===// +// Template Class +// MPYS / Multipy signed/unsigned halfwords and add/subtract the +// result from the 64-bit destination register. +//Rxx [-+]= mpy[u](Rs.[H|L],Rt.[H|L])[:<<1][:sat] +//===----------------------------------------------------------------------===// + +class T_M2_mpyd_acc < bits<2> LHbits, bit isNac, bit hasShift, bit isUnsigned> + : MInst_acc<(outs DoubleRegs:$Rxx), + (ins DoubleRegs:$dst2, IntRegs:$Rs, IntRegs:$Rt), + "$Rxx "#!if(isNac,"-= ","+= ")#!if(isUnsigned,"mpyu","mpy") + #"($Rs."#!if(LHbits{1},"h","l") + #", $Rt."#!if(LHbits{0},"h)","l)") + #!if(hasShift,":<<1",""), + [], "$dst2 = $Rxx", M_tc_3x_SLOT23 > { + bits<5> Rxx; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + + let Inst{27-24} = 0b0110; + let Inst{23} = hasShift; + let Inst{22} = isUnsigned; + let Inst{21} = isNac; + let Inst{7} = 0; + let Inst{6-5} = LHbits; + let Inst{4-0} = Rxx; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + } + +let isCodeGenOnly = 0 in { +def M2_mpyd_acc_hh_s0: T_M2_mpyd_acc <0b11, 0, 0, 0>; +def M2_mpyd_acc_hl_s0: T_M2_mpyd_acc <0b10, 0, 0, 0>; +def M2_mpyd_acc_lh_s0: T_M2_mpyd_acc <0b01, 0, 0, 0>; +def M2_mpyd_acc_ll_s0: T_M2_mpyd_acc <0b00, 0, 0, 0>; + +def M2_mpyd_acc_hh_s1: T_M2_mpyd_acc <0b11, 0, 1, 0>; +def M2_mpyd_acc_hl_s1: T_M2_mpyd_acc <0b10, 0, 1, 0>; +def M2_mpyd_acc_lh_s1: T_M2_mpyd_acc <0b01, 0, 1, 0>; +def M2_mpyd_acc_ll_s1: T_M2_mpyd_acc <0b00, 0, 1, 0>; + +def M2_mpyd_nac_hh_s0: T_M2_mpyd_acc <0b11, 1, 0, 0>; +def M2_mpyd_nac_hl_s0: T_M2_mpyd_acc <0b10, 1, 0, 0>; +def M2_mpyd_nac_lh_s0: T_M2_mpyd_acc <0b01, 1, 0, 0>; +def M2_mpyd_nac_ll_s0: T_M2_mpyd_acc <0b00, 1, 0, 0>; + +def M2_mpyd_nac_hh_s1: T_M2_mpyd_acc <0b11, 1, 1, 0>; +def M2_mpyd_nac_hl_s1: T_M2_mpyd_acc <0b10, 1, 1, 0>; +def M2_mpyd_nac_lh_s1: T_M2_mpyd_acc <0b01, 1, 1, 0>; +def M2_mpyd_nac_ll_s1: T_M2_mpyd_acc <0b00, 1, 1, 0>; + +def M2_mpyud_acc_hh_s0: T_M2_mpyd_acc <0b11, 0, 0, 1>; +def M2_mpyud_acc_hl_s0: T_M2_mpyd_acc <0b10, 0, 0, 1>; +def M2_mpyud_acc_lh_s0: T_M2_mpyd_acc <0b01, 0, 0, 1>; +def M2_mpyud_acc_ll_s0: T_M2_mpyd_acc <0b00, 0, 0, 1>; + +def M2_mpyud_acc_hh_s1: T_M2_mpyd_acc <0b11, 0, 1, 1>; +def M2_mpyud_acc_hl_s1: T_M2_mpyd_acc <0b10, 0, 1, 1>; +def M2_mpyud_acc_lh_s1: T_M2_mpyd_acc <0b01, 0, 1, 1>; +def M2_mpyud_acc_ll_s1: T_M2_mpyd_acc <0b00, 0, 1, 1>; + +def M2_mpyud_nac_hh_s0: T_M2_mpyd_acc <0b11, 1, 0, 1>; +def M2_mpyud_nac_hl_s0: T_M2_mpyd_acc <0b10, 1, 0, 1>; +def M2_mpyud_nac_lh_s0: T_M2_mpyd_acc <0b01, 1, 0, 1>; +def M2_mpyud_nac_ll_s0: T_M2_mpyd_acc <0b00, 1, 0, 1>; + +def M2_mpyud_nac_hh_s1: T_M2_mpyd_acc <0b11, 1, 1, 1>; +def M2_mpyud_nac_hl_s1: T_M2_mpyd_acc <0b10, 1, 1, 1>; +def M2_mpyud_nac_lh_s1: T_M2_mpyd_acc <0b01, 1, 1, 1>; +def M2_mpyud_nac_ll_s1: T_M2_mpyd_acc <0b00, 1, 1, 1>; +} + +let hasNewValue = 1, opNewValue = 0 in +class T_MType_mpy <string mnemonic, bits<4> RegTyBits, RegisterClass RC, + bits<3> MajOp, bits<3> MinOp, bit isSat = 0, bit isRnd = 0, + string op2Suffix = "", bit isRaw = 0, bit isHi = 0 > + : MInst <(outs IntRegs:$dst), (ins RC:$src1, RC:$src2), + "$dst = "#mnemonic + #"($src1, $src2"#op2Suffix#")" + #!if(MajOp{2}, ":<<1", "") + #!if(isRnd, ":rnd", "") + #!if(isSat, ":sat", "") + #!if(isRaw, !if(isHi, ":raw:hi", ":raw:lo"), ""), [] > { + bits<5> dst; + bits<5> src1; + bits<5> src2; + + let IClass = 0b1110; + + let Inst{27-24} = RegTyBits; + let Inst{23-21} = MajOp; + let Inst{20-16} = src1; + let Inst{13} = 0b0; + let Inst{12-8} = src2; + let Inst{7-5} = MinOp; + let Inst{4-0} = dst; + } + +class T_MType_dd <string mnemonic, bits<3> MajOp, bits<3> MinOp, + bit isSat = 0, bit isRnd = 0 > + : T_MType_mpy <mnemonic, 0b1001, DoubleRegs, MajOp, MinOp, isSat, isRnd>; + +class T_MType_rr1 <string mnemonic, bits<3> MajOp, bits<3> MinOp, + bit isSat = 0, bit isRnd = 0 > + : T_MType_mpy<mnemonic, 0b1101, IntRegs, MajOp, MinOp, isSat, isRnd>; + +class T_MType_rr2 <string mnemonic, bits<3> MajOp, bits<3> MinOp, + bit isSat = 0, bit isRnd = 0, string op2str = "" > + : T_MType_mpy<mnemonic, 0b1101, IntRegs, MajOp, MinOp, isSat, isRnd, op2str>; + +let CextOpcode = "mpyi", InputType = "reg", isCodeGenOnly = 0 in +def M2_mpyi : T_MType_rr1 <"mpyi", 0b000, 0b000>, ImmRegRel; + +let isCodeGenOnly = 0 in { +def M2_mpy_up : T_MType_rr1 <"mpy", 0b000, 0b001>; +def M2_mpyu_up : T_MType_rr1 <"mpyu", 0b010, 0b001>; +} + +let isCodeGenOnly = 0 in +def M2_dpmpyss_rnd_s0 : T_MType_rr1 <"mpy", 0b001, 0b001, 0, 1>; + +let isCodeGenOnly = 0 in { +def M2_hmmpyh_rs1 : T_MType_rr2 <"mpy", 0b101, 0b100, 1, 1, ".h">; +def M2_hmmpyl_rs1 : T_MType_rr2 <"mpy", 0b111, 0b100, 1, 1, ".l">; +} + +// V4 Instructions +let isCodeGenOnly = 0 in { +def M2_mpysu_up : T_MType_rr1 <"mpysu", 0b011, 0b001, 0>; +def M2_mpy_up_s1_sat : T_MType_rr1 <"mpy", 0b111, 0b000, 1>; + +def M2_hmmpyh_s1 : T_MType_rr2 <"mpy", 0b101, 0b000, 1, 0, ".h">; +def M2_hmmpyl_s1 : T_MType_rr2 <"mpy", 0b101, 0b001, 1, 0, ".l">; +} + +def: Pat<(i32 (mul I32:$src1, I32:$src2)), (M2_mpyi I32:$src1, I32:$src2)>; +def: Pat<(i32 (mulhs I32:$src1, I32:$src2)), (M2_mpy_up I32:$src1, I32:$src2)>; +def: Pat<(i32 (mulhu I32:$src1, I32:$src2)), (M2_mpyu_up I32:$src1, I32:$src2)>; + +let hasNewValue = 1, opNewValue = 0 in +class T_MType_mpy_ri <bit isNeg, Operand ImmOp, list<dag> pattern> + : MInst < (outs IntRegs:$Rd), (ins IntRegs:$Rs, ImmOp:$u8), + "$Rd ="#!if(isNeg, "- ", "+ ")#"mpyi($Rs, #$u8)" , + pattern, "", M_tc_3x_SLOT23> { + bits<5> Rd; + bits<5> Rs; + bits<8> u8; + + let IClass = 0b1110; + + let Inst{27-24} = 0b0000; + let Inst{23} = isNeg; + let Inst{13} = 0b0; + let Inst{4-0} = Rd; + let Inst{20-16} = Rs; + let Inst{12-5} = u8; + } + +let isExtendable = 1, opExtentBits = 8, opExtendable = 2, isCodeGenOnly = 0 in +def M2_mpysip : T_MType_mpy_ri <0, u8Ext, + [(set (i32 IntRegs:$Rd), (mul IntRegs:$Rs, u8ExtPred:$u8))]>; + +let isCodeGenOnly = 0 in +def M2_mpysin : T_MType_mpy_ri <1, u8Imm, + [(set (i32 IntRegs:$Rd), (ineg (mul IntRegs:$Rs, + u8ImmPred:$u8)))]>; + +// Assember mapped to M2_mpyi +let isAsmParserOnly = 1 in +def M2_mpyui : MInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = mpyui($src1, $src2)">; // Rd=mpyi(Rs,#m9) // s9 is NOT the same as m9 - but it works.. so far. -// Assembler maps to either Rd=+mpyi(Rs,#u8 or Rd=-mpyi(Rs,#u8) +// Assembler maps to either Rd=+mpyi(Rs,#u8) or Rd=-mpyi(Rs,#u8) // depending on the value of m9. See Arch Spec. let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 9, -CextOpcode = "MPYI", InputType = "imm" in -def MPYI_ri : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, s9Ext:$src2), - "$dst = mpyi($src1, #$src2)", - [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1), - s9ExtPred:$src2))]>, ImmRegRel; - -// Rd=mpyi(Rs,Rt) -let CextOpcode = "MPYI", InputType = "reg" in -def MPYI : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = mpyi($src1, $src2)", - [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))]>, ImmRegRel; - -// Rx+=mpyi(Rs,#u8) -let isExtendable = 1, opExtendable = 3, isExtentSigned = 0, opExtentBits = 8, -CextOpcode = "MPYI_acc", InputType = "imm" in -def MPYI_acc_ri : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u8Ext:$src3), - "$dst += mpyi($src2, #$src3)", - [(set (i32 IntRegs:$dst), - (add (mul (i32 IntRegs:$src2), u8ExtPred:$src3), - (i32 IntRegs:$src1)))], - "$src1 = $dst">, ImmRegRel; + CextOpcode = "mpyi", InputType = "imm", hasNewValue = 1 in +def M2_mpysmi : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, s9Ext:$src2), + "$dst = mpyi($src1, #$src2)", + [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1), + s9ExtPred:$src2))]>, ImmRegRel; + +let hasNewValue = 1, isExtendable = 1, opExtentBits = 8, opExtendable = 3, + InputType = "imm" in +class T_MType_acc_ri <string mnemonic, bits<3> MajOp, Operand ImmOp, + list<dag> pattern = []> + : MInst < (outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, ImmOp:$src3), + "$dst "#mnemonic#"($src2, #$src3)", + pattern, "$src1 = $dst", M_tc_2_SLOT23> { + bits<5> dst; + bits<5> src2; + bits<8> src3; + + let IClass = 0b1110; -// Rx+=mpyi(Rs,Rt) -let CextOpcode = "MPYI_acc", InputType = "reg" in -def MPYI_acc_rr : MInst_acc<(outs IntRegs:$dst), + let Inst{27-26} = 0b00; + let Inst{25-23} = MajOp; + let Inst{20-16} = src2; + let Inst{13} = 0b0; + let Inst{12-5} = src3; + let Inst{4-0} = dst; + } + +let InputType = "reg", hasNewValue = 1 in +class T_MType_acc_rr <string mnemonic, bits<3> MajOp, bits<3> MinOp, + bit isSwap = 0, list<dag> pattern = [], bit hasNot = 0, + bit isSat = 0, bit isShift = 0> + : MInst < (outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "$dst += mpyi($src2, $src3)", - [(set (i32 IntRegs:$dst), - (add (mul (i32 IntRegs:$src2), (i32 IntRegs:$src3)), - (i32 IntRegs:$src1)))], - "$src1 = $dst">, ImmRegRel; - -// Rx-=mpyi(Rs,#u8) -let isExtendable = 1, opExtendable = 3, isExtentSigned = 0, opExtentBits = 8 in -def MPYI_sub_ri : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u8Ext:$src3), - "$dst -= mpyi($src2, #$src3)", - [(set (i32 IntRegs:$dst), - (sub (i32 IntRegs:$src1), (mul (i32 IntRegs:$src2), - u8ExtPred:$src3)))], - "$src1 = $dst">; - -// Multiply and use upper result. -// Rd=mpy(Rs,Rt.H):<<1:rnd:sat -// Rd=mpy(Rs,Rt.L):<<1:rnd:sat -// Rd=mpy(Rs,Rt) -def MPY : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = mpy($src1, $src2)", - [(set (i32 IntRegs:$dst), (mulhs (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))]>; - -// Rd=mpy(Rs,Rt):rnd -// Rd=mpyu(Rs,Rt) -def MPYU : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = mpyu($src1, $src2)", - [(set (i32 IntRegs:$dst), (mulhu (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))]>; - -// Multiply and use full result. -// Rdd=mpyu(Rs,Rt) -def MPYU64 : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = mpyu($src1, $src2)", - [(set (i64 DoubleRegs:$dst), - (mul (i64 (anyext (i32 IntRegs:$src1))), - (i64 (anyext (i32 IntRegs:$src2)))))]>; - -// Rdd=mpy(Rs,Rt) -def MPY64 : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = mpy($src1, $src2)", - [(set (i64 DoubleRegs:$dst), - (mul (i64 (sext (i32 IntRegs:$src1))), - (i64 (sext (i32 IntRegs:$src2)))))]>; + "$dst "#mnemonic#"($src2, "#!if(hasNot, "~$src3)","$src3)") + #!if(isShift, ":<<1", "") + #!if(isSat, ":sat", ""), + pattern, "$src1 = $dst", M_tc_2_SLOT23 > { + bits<5> dst; + bits<5> src2; + bits<5> src3; + + let IClass = 0b1110; + + let Inst{27-24} = 0b1111; + let Inst{23-21} = MajOp; + let Inst{20-16} = !if(isSwap, src3, src2); + let Inst{13} = 0b0; + let Inst{12-8} = !if(isSwap, src2, src3); + let Inst{7-5} = MinOp; + let Inst{4-0} = dst; + } + +let CextOpcode = "MPYI_acc", Itinerary = M_tc_3x_SLOT23, isCodeGenOnly = 0 in { + def M2_macsip : T_MType_acc_ri <"+= mpyi", 0b010, u8Ext, + [(set (i32 IntRegs:$dst), + (add (mul IntRegs:$src2, u8ExtPred:$src3), + IntRegs:$src1))]>, ImmRegRel; + + def M2_maci : T_MType_acc_rr <"+= mpyi", 0b000, 0b000, 0, + [(set (i32 IntRegs:$dst), + (add (mul IntRegs:$src2, IntRegs:$src3), + IntRegs:$src1))]>, ImmRegRel; +} + +let CextOpcode = "ADD_acc", isCodeGenOnly = 0 in { + let isExtentSigned = 1 in + def M2_accii : T_MType_acc_ri <"+= add", 0b100, s8Ext, + [(set (i32 IntRegs:$dst), + (add (add (i32 IntRegs:$src2), s8_16ExtPred:$src3), + (i32 IntRegs:$src1)))]>, ImmRegRel; + + def M2_acci : T_MType_acc_rr <"+= add", 0b000, 0b001, 0, + [(set (i32 IntRegs:$dst), + (add (add (i32 IntRegs:$src2), (i32 IntRegs:$src3)), + (i32 IntRegs:$src1)))]>, ImmRegRel; +} + +let CextOpcode = "SUB_acc", isCodeGenOnly = 0 in { + let isExtentSigned = 1 in + def M2_naccii : T_MType_acc_ri <"-= add", 0b101, s8Ext>, ImmRegRel; + + def M2_nacci : T_MType_acc_rr <"-= add", 0b100, 0b001, 0>, ImmRegRel; +} + +let Itinerary = M_tc_3x_SLOT23, isCodeGenOnly = 0 in +def M2_macsin : T_MType_acc_ri <"-= mpyi", 0b011, u8Ext>; + +let isCodeGenOnly = 0 in { +def M2_xor_xacc : T_MType_acc_rr < "^= xor", 0b100, 0b011, 0>; +def M2_subacc : T_MType_acc_rr <"+= sub", 0b000, 0b011, 1>; +} + +class T_MType_acc_pat1 <InstHexagon MI, SDNode firstOp, SDNode secOp, + PatLeaf ImmPred> + : Pat <(secOp IntRegs:$src1, (firstOp IntRegs:$src2, ImmPred:$src3)), + (MI IntRegs:$src1, IntRegs:$src2, ImmPred:$src3)>; + +class T_MType_acc_pat2 <InstHexagon MI, SDNode firstOp, SDNode secOp> + : Pat <(i32 (secOp IntRegs:$src1, (firstOp IntRegs:$src2, IntRegs:$src3))), + (MI IntRegs:$src1, IntRegs:$src2, IntRegs:$src3)>; + +def : T_MType_acc_pat2 <M2_xor_xacc, xor, xor>; +def : T_MType_acc_pat1 <M2_macsin, mul, sub, u8ExtPred>; + +def : T_MType_acc_pat1 <M2_naccii, add, sub, s8_16ExtPred>; +def : T_MType_acc_pat2 <M2_nacci, add, sub>; +//===----------------------------------------------------------------------===// +// Template Class -- Multiply signed/unsigned halfwords with and without +// saturation and rounding +//===----------------------------------------------------------------------===// +class T_M2_mpyd < bits<2> LHbits, bit isRnd, bit hasShift, bit isUnsigned > + : MInst < (outs DoubleRegs:$Rdd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rdd = "#!if(isUnsigned,"mpyu","mpy")#"($Rs."#!if(LHbits{1},"h","l") + #", $Rt."#!if(LHbits{0},"h)","l)") + #!if(hasShift,":<<1","") + #!if(isRnd,":rnd",""), + [] > { + bits<5> Rdd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + + let Inst{27-24} = 0b0100; + let Inst{23} = hasShift; + let Inst{22} = isUnsigned; + let Inst{21} = isRnd; + let Inst{6-5} = LHbits; + let Inst{4-0} = Rdd; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; +} + +let isCodeGenOnly = 0 in { +def M2_mpyd_hh_s0: T_M2_mpyd<0b11, 0, 0, 0>; +def M2_mpyd_hl_s0: T_M2_mpyd<0b10, 0, 0, 0>; +def M2_mpyd_lh_s0: T_M2_mpyd<0b01, 0, 0, 0>; +def M2_mpyd_ll_s0: T_M2_mpyd<0b00, 0, 0, 0>; + +def M2_mpyd_hh_s1: T_M2_mpyd<0b11, 0, 1, 0>; +def M2_mpyd_hl_s1: T_M2_mpyd<0b10, 0, 1, 0>; +def M2_mpyd_lh_s1: T_M2_mpyd<0b01, 0, 1, 0>; +def M2_mpyd_ll_s1: T_M2_mpyd<0b00, 0, 1, 0>; + +def M2_mpyd_rnd_hh_s0: T_M2_mpyd<0b11, 1, 0, 0>; +def M2_mpyd_rnd_hl_s0: T_M2_mpyd<0b10, 1, 0, 0>; +def M2_mpyd_rnd_lh_s0: T_M2_mpyd<0b01, 1, 0, 0>; +def M2_mpyd_rnd_ll_s0: T_M2_mpyd<0b00, 1, 0, 0>; + +def M2_mpyd_rnd_hh_s1: T_M2_mpyd<0b11, 1, 1, 0>; +def M2_mpyd_rnd_hl_s1: T_M2_mpyd<0b10, 1, 1, 0>; +def M2_mpyd_rnd_lh_s1: T_M2_mpyd<0b01, 1, 1, 0>; +def M2_mpyd_rnd_ll_s1: T_M2_mpyd<0b00, 1, 1, 0>; + +//Rdd=mpyu(Rs.[HL],Rt.[HL])[:<<1] +def M2_mpyud_hh_s0: T_M2_mpyd<0b11, 0, 0, 1>; +def M2_mpyud_hl_s0: T_M2_mpyd<0b10, 0, 0, 1>; +def M2_mpyud_lh_s0: T_M2_mpyd<0b01, 0, 0, 1>; +def M2_mpyud_ll_s0: T_M2_mpyd<0b00, 0, 0, 1>; + +def M2_mpyud_hh_s1: T_M2_mpyd<0b11, 0, 1, 1>; +def M2_mpyud_hl_s1: T_M2_mpyd<0b10, 0, 1, 1>; +def M2_mpyud_lh_s1: T_M2_mpyd<0b01, 0, 1, 1>; +def M2_mpyud_ll_s1: T_M2_mpyd<0b00, 0, 1, 1>; +} +//===----------------------------------------------------------------------===// +// Template Class for xtype mpy: +// Vector multiply +// Complex multiply +// multiply 32X32 and use full result +//===----------------------------------------------------------------------===// +let hasSideEffects = 0 in +class T_XTYPE_mpy64 <string mnemonic, bits<3> MajOp, bits<3> MinOp, + bit isSat, bit hasShift, bit isConj> + : MInst <(outs DoubleRegs:$Rdd), + (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rdd = "#mnemonic#"($Rs, $Rt"#!if(isConj,"*)",")") + #!if(hasShift,":<<1","") + #!if(isSat,":sat",""), + [] > { + bits<5> Rdd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + + let Inst{27-24} = 0b0101; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rdd; + } + +//===----------------------------------------------------------------------===// +// Template Class for xtype mpy with accumulation into 64-bit: +// Vector multiply +// Complex multiply +// multiply 32X32 and use full result +//===----------------------------------------------------------------------===// +class T_XTYPE_mpy64_acc <string op1, string op2, bits<3> MajOp, bits<3> MinOp, + bit isSat, bit hasShift, bit isConj> + : MInst <(outs DoubleRegs:$Rxx), + (ins DoubleRegs:$dst2, IntRegs:$Rs, IntRegs:$Rt), + "$Rxx "#op2#"= "#op1#"($Rs, $Rt"#!if(isConj,"*)",")") + #!if(hasShift,":<<1","") + #!if(isSat,":sat",""), + + [] , "$dst2 = $Rxx" > { + bits<5> Rxx; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + + let Inst{27-24} = 0b0111; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rxx; + } + +// MPY - Multiply and use full result +// Rdd = mpy[u](Rs,Rt) +let isCodeGenOnly = 0 in { +def M2_dpmpyss_s0 : T_XTYPE_mpy64 < "mpy", 0b000, 0b000, 0, 0, 0>; +def M2_dpmpyuu_s0 : T_XTYPE_mpy64 < "mpyu", 0b010, 0b000, 0, 0, 0>; + +// Rxx[+-]= mpy[u](Rs,Rt) +def M2_dpmpyss_acc_s0 : T_XTYPE_mpy64_acc < "mpy", "+", 0b000, 0b000, 0, 0, 0>; +def M2_dpmpyss_nac_s0 : T_XTYPE_mpy64_acc < "mpy", "-", 0b001, 0b000, 0, 0, 0>; +def M2_dpmpyuu_acc_s0 : T_XTYPE_mpy64_acc < "mpyu", "+", 0b010, 0b000, 0, 0, 0>; +def M2_dpmpyuu_nac_s0 : T_XTYPE_mpy64_acc < "mpyu", "-", 0b011, 0b000, 0, 0, 0>; +} + +def: Pat<(i64 (mul (i64 (anyext (i32 IntRegs:$src1))), + (i64 (anyext (i32 IntRegs:$src2))))), + (M2_dpmpyuu_s0 IntRegs:$src1, IntRegs:$src2)>; + +def: Pat<(i64 (mul (i64 (sext (i32 IntRegs:$src1))), + (i64 (sext (i32 IntRegs:$src2))))), + (M2_dpmpyss_s0 IntRegs:$src1, IntRegs:$src2)>; + +def: Pat<(i64 (mul (is_sext_i32:$src1), + (is_sext_i32:$src2))), + (M2_dpmpyss_s0 (LoReg DoubleRegs:$src1), (LoReg DoubleRegs:$src2))>; // Multiply and accumulate, use full result. // Rxx[+-]=mpy(Rs,Rt) -// Rxx+=mpy(Rs,Rt) -def MPY64_acc : MInst_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "$dst += mpy($src2, $src3)", - [(set (i64 DoubleRegs:$dst), - (add (mul (i64 (sext (i32 IntRegs:$src2))), - (i64 (sext (i32 IntRegs:$src3)))), - (i64 DoubleRegs:$src1)))], - "$src1 = $dst">; - -// Rxx-=mpy(Rs,Rt) -def MPY64_sub : MInst_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "$dst -= mpy($src2, $src3)", - [(set (i64 DoubleRegs:$dst), - (sub (i64 DoubleRegs:$src1), - (mul (i64 (sext (i32 IntRegs:$src2))), - (i64 (sext (i32 IntRegs:$src3))))))], - "$src1 = $dst">; - -// Rxx[+-]=mpyu(Rs,Rt) -// Rxx+=mpyu(Rs,Rt) -def MPYU64_acc : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - IntRegs:$src2, IntRegs:$src3), - "$dst += mpyu($src2, $src3)", - [(set (i64 DoubleRegs:$dst), - (add (mul (i64 (anyext (i32 IntRegs:$src2))), - (i64 (anyext (i32 IntRegs:$src3)))), - (i64 DoubleRegs:$src1)))], "$src1 = $dst">; - -// Rxx-=mpyu(Rs,Rt) -def MPYU64_sub : MInst_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "$dst -= mpyu($src2, $src3)", - [(set (i64 DoubleRegs:$dst), - (sub (i64 DoubleRegs:$src1), - (mul (i64 (anyext (i32 IntRegs:$src2))), - (i64 (anyext (i32 IntRegs:$src3))))))], - "$src1 = $dst">; - - -let InputType = "reg", CextOpcode = "ADD_acc" in -def ADDrr_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, - IntRegs:$src2, IntRegs:$src3), - "$dst += add($src2, $src3)", - [(set (i32 IntRegs:$dst), (add (add (i32 IntRegs:$src2), - (i32 IntRegs:$src3)), - (i32 IntRegs:$src1)))], - "$src1 = $dst">, ImmRegRel; - -let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 8, -InputType = "imm", CextOpcode = "ADD_acc" in -def ADDri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, - IntRegs:$src2, s8Ext:$src3), - "$dst += add($src2, #$src3)", - [(set (i32 IntRegs:$dst), (add (add (i32 IntRegs:$src2), - s8_16ExtPred:$src3), - (i32 IntRegs:$src1)))], - "$src1 = $dst">, ImmRegRel; - -let CextOpcode = "SUB_acc", InputType = "reg" in -def SUBrr_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, - IntRegs:$src2, IntRegs:$src3), - "$dst -= add($src2, $src3)", - [(set (i32 IntRegs:$dst), - (sub (i32 IntRegs:$src1), (add (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, ImmRegRel; - -let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 8, -CextOpcode = "SUB_acc", InputType = "imm" in -def SUBri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, - IntRegs:$src2, s8Ext:$src3), - "$dst -= add($src2, #$src3)", - [(set (i32 IntRegs:$dst), (sub (i32 IntRegs:$src1), - (add (i32 IntRegs:$src2), - s8_16ExtPred:$src3)))], - "$src1 = $dst">, ImmRegRel; + +def: Pat<(i64 (add (i64 DoubleRegs:$src1), + (mul (i64 (sext (i32 IntRegs:$src2))), + (i64 (sext (i32 IntRegs:$src3)))))), + (M2_dpmpyss_acc_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>; + +def: Pat<(i64 (sub (i64 DoubleRegs:$src1), + (mul (i64 (sext (i32 IntRegs:$src2))), + (i64 (sext (i32 IntRegs:$src3)))))), + (M2_dpmpyss_nac_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>; + +def: Pat<(i64 (add (i64 DoubleRegs:$src1), + (mul (i64 (anyext (i32 IntRegs:$src2))), + (i64 (anyext (i32 IntRegs:$src3)))))), + (M2_dpmpyuu_acc_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>; + +def: Pat<(i64 (add (i64 DoubleRegs:$src1), + (mul (i64 (zext (i32 IntRegs:$src2))), + (i64 (zext (i32 IntRegs:$src3)))))), + (M2_dpmpyuu_acc_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>; + +def: Pat<(i64 (sub (i64 DoubleRegs:$src1), + (mul (i64 (anyext (i32 IntRegs:$src2))), + (i64 (anyext (i32 IntRegs:$src3)))))), + (M2_dpmpyuu_nac_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>; + +def: Pat<(i64 (sub (i64 DoubleRegs:$src1), + (mul (i64 (zext (i32 IntRegs:$src2))), + (i64 (zext (i32 IntRegs:$src3)))))), + (M2_dpmpyuu_nac_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>; //===----------------------------------------------------------------------===// // MTYPE/MPYH - @@ -1385,245 +2656,459 @@ def SUBri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, //===----------------------------------------------------------------------===// /// // Store doubleword. - //===----------------------------------------------------------------------===// -// Post increment store +// Template class for non-predicated post increment stores with immediate offset //===----------------------------------------------------------------------===// +let isPredicable = 1, hasSideEffects = 0, addrMode = PostInc in +class T_store_pi <string mnemonic, RegisterClass RC, Operand ImmOp, + bits<4> MajOp, bit isHalf > + : STInst <(outs IntRegs:$_dst_), + (ins IntRegs:$src1, ImmOp:$offset, RC:$src2), + mnemonic#"($src1++#$offset) = $src2"#!if(isHalf, ".h", ""), + [], "$src1 = $_dst_" >, + AddrModeRel { + bits<5> src1; + bits<5> src2; + bits<7> offset; + bits<4> offsetBits; + + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "s4_3Imm"), offset{6-3}, + !if (!eq(ImmOpStr, "s4_2Imm"), offset{5-2}, + !if (!eq(ImmOpStr, "s4_1Imm"), offset{4-1}, + /* s4_0Imm */ offset{3-0}))); + let isNVStorable = !if (!eq(ImmOpStr, "s4_3Imm"), 0, 1); + + let IClass = 0b1010; + + let Inst{27-25} = 0b101; + let Inst{24-21} = MajOp; + let Inst{20-16} = src1; + let Inst{13} = 0b0; + let Inst{12-8} = src2; + let Inst{7} = 0b0; + let Inst{6-3} = offsetBits; + let Inst{1} = 0b0; + } -multiclass ST_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp, - bit isNot, bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : STInst2PI<(outs IntRegs:$dst), +//===----------------------------------------------------------------------===// +// Template class for predicated post increment stores with immediate offset +//===----------------------------------------------------------------------===// +let isPredicated = 1, hasSideEffects = 0, addrMode = PostInc in +class T_pstore_pi <string mnemonic, RegisterClass RC, Operand ImmOp, + bits<4> MajOp, bit isHalf, bit isPredNot, bit isPredNew > + : STInst <(outs IntRegs:$_dst_), (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset, RC:$src3), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"($src2++#$offset) = $src3", - [], - "$src2 = $dst">; -} + !if(isPredNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($src2++#$offset) = $src3"#!if(isHalf, ".h", ""), + [], "$src2 = $_dst_" >, + AddrModeRel { + bits<2> src1; + bits<5> src2; + bits<7> offset; + bits<5> src3; + bits<4> offsetBits; -multiclass ST_PostInc_Pred<string mnemonic, RegisterClass RC, - Operand ImmOp, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ST_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 0>; - // Predicate new - let Predicates = [HasV4T], validSubTargets = HasV4SubT in - defm _cdn#NAME#_V4 : ST_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 1>; + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "s4_3Imm"), offset{6-3}, + !if (!eq(ImmOpStr, "s4_2Imm"), offset{5-2}, + !if (!eq(ImmOpStr, "s4_1Imm"), offset{4-1}, + /* s4_0Imm */ offset{3-0}))); + + let isNVStorable = !if (!eq(ImmOpStr, "s4_3Imm"), 0, 1); + let isPredicatedNew = isPredNew; + let isPredicatedFalse = isPredNot; + + let IClass = 0b1010; + + let Inst{27-25} = 0b101; + let Inst{24-21} = MajOp; + let Inst{20-16} = src2; + let Inst{13} = 0b1; + let Inst{12-8} = src3; + let Inst{7} = isPredNew; + let Inst{6-3} = offsetBits; + let Inst{2} = isPredNot; + let Inst{1-0} = src1; } -} -let hasCtrlDep = 1, isNVStorable = 1, neverHasSideEffects = 1 in multiclass ST_PostInc<string mnemonic, string BaseOp, RegisterClass RC, - Operand ImmOp> { + Operand ImmOp, bits<4> MajOp, bit isHalf = 0 > { - let hasCtrlDep = 1, BaseOpcode = "POST_"#BaseOp in { - let isPredicable = 1 in - def NAME : STInst2PI<(outs IntRegs:$dst), - (ins IntRegs:$src1, ImmOp:$offset, RC:$src2), - mnemonic#"($src1++#$offset) = $src2", - [], - "$src1 = $dst">; - - let isPredicated = 1 in { - defm Pt : ST_PostInc_Pred<mnemonic, RC, ImmOp, 0 >; - defm NotPt : ST_PostInc_Pred<mnemonic, RC, ImmOp, 1 >; - } + let BaseOpcode = "POST_"#BaseOp in { + def S2_#NAME#_pi : T_store_pi <mnemonic, RC, ImmOp, MajOp, isHalf>; + + // Predicated + def S2_p#NAME#t_pi : T_pstore_pi <mnemonic, RC, ImmOp, MajOp, isHalf, 0, 0>; + def S2_p#NAME#f_pi : T_pstore_pi <mnemonic, RC, ImmOp, MajOp, isHalf, 1, 0>; + + // Predicated new + def S2_p#NAME#tnew_pi : T_pstore_pi <mnemonic, RC, ImmOp, MajOp, + isHalf, 0, 1>; + def S2_p#NAME#fnew_pi : T_pstore_pi <mnemonic, RC, ImmOp, MajOp, + isHalf, 1, 1>; } } -defm POST_STbri: ST_PostInc <"memb", "STrib", IntRegs, s4_0Imm>, AddrModeRel; -defm POST_SThri: ST_PostInc <"memh", "STrih", IntRegs, s4_1Imm>, AddrModeRel; -defm POST_STwri: ST_PostInc <"memw", "STriw", IntRegs, s4_2Imm>, AddrModeRel; +let accessSize = ByteAccess, isCodeGenOnly = 0 in +defm storerb: ST_PostInc <"memb", "STrib", IntRegs, s4_0Imm, 0b1000>; + +let accessSize = HalfWordAccess, isCodeGenOnly = 0 in +defm storerh: ST_PostInc <"memh", "STrih", IntRegs, s4_1Imm, 0b1010>; + +let accessSize = WordAccess, isCodeGenOnly = 0 in +defm storeri: ST_PostInc <"memw", "STriw", IntRegs, s4_2Imm, 0b1100>; -let isNVStorable = 0 in -defm POST_STdri: ST_PostInc <"memd", "STrid", DoubleRegs, s4_3Imm>, AddrModeRel; +let accessSize = DoubleWordAccess, isCodeGenOnly = 0 in +defm storerd: ST_PostInc <"memd", "STrid", DoubleRegs, s4_3Imm, 0b1110>; + +let accessSize = HalfWordAccess, isNVStorable = 0, isCodeGenOnly = 0 in +defm storerf: ST_PostInc <"memh", "STrih_H", IntRegs, s4_1Imm, 0b1011, 1>; def : Pat<(post_truncsti8 (i32 IntRegs:$src1), IntRegs:$src2, s4_3ImmPred:$offset), - (POST_STbri IntRegs:$src2, s4_0ImmPred:$offset, IntRegs:$src1)>; + (S2_storerb_pi IntRegs:$src2, s4_0ImmPred:$offset, IntRegs:$src1)>; def : Pat<(post_truncsti16 (i32 IntRegs:$src1), IntRegs:$src2, s4_3ImmPred:$offset), - (POST_SThri IntRegs:$src2, s4_1ImmPred:$offset, IntRegs:$src1)>; + (S2_storerh_pi IntRegs:$src2, s4_1ImmPred:$offset, IntRegs:$src1)>; def : Pat<(post_store (i32 IntRegs:$src1), IntRegs:$src2, s4_2ImmPred:$offset), - (POST_STwri IntRegs:$src2, s4_1ImmPred:$offset, IntRegs:$src1)>; + (S2_storeri_pi IntRegs:$src2, s4_1ImmPred:$offset, IntRegs:$src1)>; def : Pat<(post_store (i64 DoubleRegs:$src1), IntRegs:$src2, s4_3ImmPred:$offset), - (POST_STdri IntRegs:$src2, s4_3ImmPred:$offset, DoubleRegs:$src1)>; + (S2_storerd_pi IntRegs:$src2, s4_3ImmPred:$offset, DoubleRegs:$src1)>; //===----------------------------------------------------------------------===// -// multiclass for the store instructions with MEMri operand. +// Template class for post increment stores with register offset. //===----------------------------------------------------------------------===// -multiclass ST_MEMri_Pbase<string mnemonic, RegisterClass RC, bit isNot, - bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, RC: $src2), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"($addr) = $src2", - []>; +let isNVStorable = 1 in +class T_store_pr <string mnemonic, RegisterClass RC, bits<3> MajOp, + MemAccessSize AccessSz, bit isHalf = 0> + : STInst <(outs IntRegs:$_dst_), + (ins IntRegs:$src1, ModRegs:$src2, RC:$src3), + mnemonic#"($src1++$src2) = $src3"#!if(isHalf, ".h", ""), + [], "$src1 = $_dst_" > { + bits<5> src1; + bits<1> src2; + bits<5> src3; + let accessSize = AccessSz; + + let IClass = 0b1010; + + let Inst{27-24} = 0b1101; + let Inst{23-21} = MajOp; + let Inst{20-16} = src1; + let Inst{13} = src2; + let Inst{12-8} = src3; + let Inst{7} = 0b0; + } + +let isCodeGenOnly = 0 in { +def S2_storerb_pr : T_store_pr<"memb", IntRegs, 0b000, ByteAccess>; +def S2_storerh_pr : T_store_pr<"memh", IntRegs, 0b010, HalfWordAccess>; +def S2_storeri_pr : T_store_pr<"memw", IntRegs, 0b100, WordAccess>; +def S2_storerd_pr : T_store_pr<"memd", DoubleRegs, 0b110, DoubleWordAccess>; + +def S2_storerf_pr : T_store_pr<"memh", IntRegs, 0b011, HalfWordAccess, 1>; } +let opExtendable = 1, isExtentSigned = 1, isPredicable = 1 in +class T_store_io <string mnemonic, RegisterClass RC, Operand ImmOp, + bits<3>MajOp, bit isH = 0> + : STInst <(outs), + (ins IntRegs:$src1, ImmOp:$src2, RC:$src3), + mnemonic#"($src1+#$src2) = $src3"#!if(isH,".h","")>, + AddrModeRel, ImmRegRel { + bits<5> src1; + bits<14> src2; // Actual address offset + bits<5> src3; + bits<11> offsetBits; // Represents offset encoding + + string ImmOpStr = !cast<string>(ImmOp); + + let opExtentBits = !if (!eq(ImmOpStr, "s11_3Ext"), 14, + !if (!eq(ImmOpStr, "s11_2Ext"), 13, + !if (!eq(ImmOpStr, "s11_1Ext"), 12, + /* s11_0Ext */ 11))); + let offsetBits = !if (!eq(ImmOpStr, "s11_3Ext"), src2{13-3}, + !if (!eq(ImmOpStr, "s11_2Ext"), src2{12-2}, + !if (!eq(ImmOpStr, "s11_1Ext"), src2{11-1}, + /* s11_0Ext */ src2{10-0}))); + let IClass = 0b1010; + + let Inst{27} = 0b0; + let Inst{26-25} = offsetBits{10-9}; + let Inst{24} = 0b1; + let Inst{23-21} = MajOp; + let Inst{20-16} = src1; + let Inst{13} = offsetBits{8}; + let Inst{12-8} = src3; + let Inst{7-0} = offsetBits{7-0}; + } -multiclass ST_MEMri_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ST_MEMri_Pbase<mnemonic, RC, PredNot, 0>; +let opExtendable = 2, isPredicated = 1 in +class T_pstore_io <string mnemonic, RegisterClass RC, Operand ImmOp, + bits<3>MajOp, bit PredNot, bit isPredNew, bit isH = 0> + : STInst <(outs), + (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$src3, RC:$src4), + !if(PredNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($src2+#$src3) = $src4"#!if(isH,".h",""), + [],"",V2LDST_tc_st_SLOT01 >, + AddrModeRel, ImmRegRel { + bits<2> src1; + bits<5> src2; + bits<9> src3; // Actual address offset + bits<5> src4; + bits<6> offsetBits; // Represents offset encoding - // Predicate new - let validSubTargets = HasV4SubT, Predicates = [HasV4T] in - defm _cdn#NAME#_V4 : ST_MEMri_Pbase<mnemonic, RC, PredNot, 1>; + let isPredicatedNew = isPredNew; + let isPredicatedFalse = PredNot; + + string ImmOpStr = !cast<string>(ImmOp); + let opExtentBits = !if (!eq(ImmOpStr, "u6_3Ext"), 9, + !if (!eq(ImmOpStr, "u6_2Ext"), 8, + !if (!eq(ImmOpStr, "u6_1Ext"), 7, + /* u6_0Ext */ 6))); + let offsetBits = !if (!eq(ImmOpStr, "u6_3Ext"), src3{8-3}, + !if (!eq(ImmOpStr, "u6_2Ext"), src3{7-2}, + !if (!eq(ImmOpStr, "u6_1Ext"), src3{6-1}, + /* u6_0Ext */ src3{5-0}))); + let IClass = 0b0100; + + let Inst{27} = 0b0; + let Inst{26} = PredNot; + let Inst{25} = isPredNew; + let Inst{24} = 0b0; + let Inst{23-21} = MajOp; + let Inst{20-16} = src2; + let Inst{13} = offsetBits{5}; + let Inst{12-8} = src4; + let Inst{7-3} = offsetBits{4-0}; + let Inst{1-0} = src1; } -} -let isExtendable = 1, isNVStorable = 1, neverHasSideEffects = 1 in -multiclass ST_MEMri<string mnemonic, string CextOp, RegisterClass RC, - bits<5> ImmBits, bits<5> PredImmBits> { +let isExtendable = 1, isNVStorable = 1, hasSideEffects = 0 in +multiclass ST_Idxd<string mnemonic, string CextOp, RegisterClass RC, + Operand ImmOp, Operand predImmOp, bits<3> MajOp, bit isH = 0> { + let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in { + def S2_#NAME#_io : T_store_io <mnemonic, RC, ImmOp, MajOp, isH>; - let CextOpcode = CextOp, BaseOpcode = CextOp in { - let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, - isPredicable = 1 in - def NAME : STInst2<(outs), - (ins MEMri:$addr, RC:$src), - mnemonic#"($addr) = $src", - []>; + // Predicated + def S2_p#NAME#t_io : T_pstore_io<mnemonic, RC, predImmOp, MajOp, 0, 0, isH>; + def S2_p#NAME#f_io : T_pstore_io<mnemonic, RC, predImmOp, MajOp, 1, 0, isH>; - let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits, - isPredicated = 1 in { - defm Pt : ST_MEMri_Pred<mnemonic, RC, 0>; - defm NotPt : ST_MEMri_Pred<mnemonic, RC, 1>; - } + // Predicated new + def S4_p#NAME#tnew_io : T_pstore_io <mnemonic, RC, predImmOp, + MajOp, 0, 1, isH>; + def S4_p#NAME#fnew_io : T_pstore_io <mnemonic, RC, predImmOp, + MajOp, 1, 1, isH>; } } -let addrMode = BaseImmOffset, isMEMri = "true" in { +let addrMode = BaseImmOffset, InputType = "imm", isCodeGenOnly = 0 in { let accessSize = ByteAccess in - defm STrib: ST_MEMri < "memb", "STrib", IntRegs, 11, 6>, AddrModeRel; + defm storerb: ST_Idxd < "memb", "STrib", IntRegs, s11_0Ext, u6_0Ext, 0b000>; - let accessSize = HalfWordAccess in - defm STrih: ST_MEMri < "memh", "STrih", IntRegs, 12, 7>, AddrModeRel; + let accessSize = HalfWordAccess, opExtentAlign = 1 in + defm storerh: ST_Idxd < "memh", "STrih", IntRegs, s11_1Ext, u6_1Ext, 0b010>; - let accessSize = WordAccess in - defm STriw: ST_MEMri < "memw", "STriw", IntRegs, 13, 8>, AddrModeRel; + let accessSize = WordAccess, opExtentAlign = 2 in + defm storeri: ST_Idxd < "memw", "STriw", IntRegs, s11_2Ext, u6_2Ext, 0b100>; - let accessSize = DoubleWordAccess, isNVStorable = 0 in - defm STrid: ST_MEMri < "memd", "STrid", DoubleRegs, 14, 9>, AddrModeRel; + let accessSize = DoubleWordAccess, isNVStorable = 0, opExtentAlign = 3 in + defm storerd: ST_Idxd < "memd", "STrid", DoubleRegs, s11_3Ext, + u6_3Ext, 0b110>; + + let accessSize = HalfWordAccess, opExtentAlign = 1 in + defm storerf: ST_Idxd < "memh", "STrif", IntRegs, s11_1Ext, + u6_1Ext, 0b011, 1>; } def : Pat<(truncstorei8 (i32 IntRegs:$src1), ADDRriS11_0:$addr), - (STrib ADDRriS11_0:$addr, (i32 IntRegs:$src1))>; + (S2_storerb_io AddrFI:$addr, 0, (i32 IntRegs:$src1))>; def : Pat<(truncstorei16 (i32 IntRegs:$src1), ADDRriS11_1:$addr), - (STrih ADDRriS11_1:$addr, (i32 IntRegs:$src1))>; + (S2_storerh_io AddrFI:$addr, 0, (i32 IntRegs:$src1))>; def : Pat<(store (i32 IntRegs:$src1), ADDRriS11_2:$addr), - (STriw ADDRriS11_2:$addr, (i32 IntRegs:$src1))>; + (S2_storeri_io AddrFI:$addr, 0, (i32 IntRegs:$src1))>; def : Pat<(store (i64 DoubleRegs:$src1), ADDRriS11_3:$addr), - (STrid ADDRriS11_3:$addr, (i64 DoubleRegs:$src1))>; - - -//===----------------------------------------------------------------------===// -// multiclass for the store instructions with base+immediate offset -// addressing mode -//===----------------------------------------------------------------------===// -multiclass ST_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp, - bit isNot, bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC: $src4), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"($src2+#$src3) = $src4", - []>; -} - -multiclass ST_Idxd_Pred<string mnemonic, RegisterClass RC, Operand predImmOp, - bit PredNot> { - let isPredicatedFalse = PredNot, isPredicated = 1 in { - defm _c#NAME : ST_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 0>; - - // Predicate new - let validSubTargets = HasV4SubT, Predicates = [HasV4T] in - defm _cdn#NAME#_V4 : ST_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 1>; - } -} + (S2_storerd_io AddrFI:$addr, 0, (i64 DoubleRegs:$src1))>; -let isExtendable = 1, isNVStorable = 1, neverHasSideEffects = 1 in -multiclass ST_Idxd<string mnemonic, string CextOp, RegisterClass RC, - Operand ImmOp, Operand predImmOp, bits<5> ImmBits, - bits<5> PredImmBits> { - - let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in { - let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, - isPredicable = 1 in - def NAME : STInst2<(outs), - (ins IntRegs:$src1, ImmOp:$src2, RC:$src3), - mnemonic#"($src1+#$src2) = $src3", - []>; - - let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits in { - defm Pt : ST_Idxd_Pred<mnemonic, RC, predImmOp, 0>; - defm NotPt : ST_Idxd_Pred<mnemonic, RC, predImmOp, 1>; - } - } -} - -let addrMode = BaseImmOffset, InputType = "reg" in { - let accessSize = ByteAccess in - defm STrib_indexed: ST_Idxd < "memb", "STrib", IntRegs, s11_0Ext, - u6_0Ext, 11, 6>, AddrModeRel, ImmRegRel; - - let accessSize = HalfWordAccess in - defm STrih_indexed: ST_Idxd < "memh", "STrih", IntRegs, s11_1Ext, - u6_1Ext, 12, 7>, AddrModeRel, ImmRegRel; - - let accessSize = WordAccess in - defm STriw_indexed: ST_Idxd < "memw", "STriw", IntRegs, s11_2Ext, - u6_2Ext, 13, 8>, AddrModeRel, ImmRegRel; - - let accessSize = DoubleWordAccess, isNVStorable = 0 in - defm STrid_indexed: ST_Idxd < "memd", "STrid", DoubleRegs, s11_3Ext, - u6_3Ext, 14, 9>, AddrModeRel; -} let AddedComplexity = 10 in { def : Pat<(truncstorei8 (i32 IntRegs:$src1), (add IntRegs:$src2, s11_0ExtPred:$offset)), - (STrib_indexed IntRegs:$src2, s11_0ImmPred:$offset, + (S2_storerb_io IntRegs:$src2, s11_0ImmPred:$offset, (i32 IntRegs:$src1))>; def : Pat<(truncstorei16 (i32 IntRegs:$src1), (add IntRegs:$src2, s11_1ExtPred:$offset)), - (STrih_indexed IntRegs:$src2, s11_1ImmPred:$offset, + (S2_storerh_io IntRegs:$src2, s11_1ImmPred:$offset, (i32 IntRegs:$src1))>; def : Pat<(store (i32 IntRegs:$src1), (add IntRegs:$src2, s11_2ExtPred:$offset)), - (STriw_indexed IntRegs:$src2, s11_2ImmPred:$offset, + (S2_storeri_io IntRegs:$src2, s11_2ImmPred:$offset, (i32 IntRegs:$src1))>; def : Pat<(store (i64 DoubleRegs:$src1), (add IntRegs:$src2, s11_3ExtPred:$offset)), - (STrid_indexed IntRegs:$src2, s11_3ImmPred:$offset, + (S2_storerd_io IntRegs:$src2, s11_3ImmPred:$offset, (i64 DoubleRegs:$src1))>; } // memh(Rx++#s4:1)=Rt.H -// Store word. // Store predicate. -let Defs = [R10,R11,D5], neverHasSideEffects = 1 in -def STriw_pred : STInst2<(outs), - (ins MEMri:$addr, PredRegs:$src1), - "Error; should not emit", - []>; +let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13, + isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in +def STriw_pred : STInst<(outs), + (ins IntRegs:$addr, s11_2Ext:$off, PredRegs:$src1), + ".error \"should not emit\"", []>; + +// S2_allocframe: Allocate stack frame. +let Defs = [R29, R30], Uses = [R29, R31, R30], + hasSideEffects = 0, accessSize = DoubleWordAccess, isCodeGenOnly = 0 in +def S2_allocframe: ST0Inst < + (outs), (ins u11_3Imm:$u11_3), + "allocframe(#$u11_3)" > { + bits<14> u11_3; + + let IClass = 0b1010; + let Inst{27-16} = 0b000010011101; + let Inst{13-11} = 0b000; + let Inst{10-0} = u11_3{13-3}; + } -// Allocate stack frame. -let Defs = [R29, R30], Uses = [R31, R30], neverHasSideEffects = 1 in { - def ALLOCFRAME : STInst2<(outs), - (ins i32imm:$amt), - "allocframe(#$amt)", - []>; +// S2_storer[bhwdf]_pci: Store byte/half/word/double. +// S2_storer[bhwdf]_pci -> S2_storerbnew_pci +let Uses = [CS], isNVStorable = 1 in +class T_store_pci <string mnemonic, RegisterClass RC, + Operand Imm, bits<4>MajOp, + MemAccessSize AlignSize, string RegSrc = "Rt"> + : STInst <(outs IntRegs:$_dst_), + (ins IntRegs:$Rz, Imm:$offset, ModRegs:$Mu, RC:$Rt), + #mnemonic#"($Rz ++ #$offset:circ($Mu)) = $"#RegSrc#"", + [] , + "$Rz = $_dst_" > { + bits<5> Rz; + bits<7> offset; + bits<1> Mu; + bits<5> Rt; + let accessSize = AlignSize; + + let IClass = 0b1010; + let Inst{27-25} = 0b100; + let Inst{24-21} = MajOp; + let Inst{20-16} = Rz; + let Inst{13} = Mu; + let Inst{12-8} = Rt; + let Inst{7} = 0b0; + let Inst{6-3} = + !if (!eq(!cast<string>(AlignSize), "DoubleWordAccess"), offset{6-3}, + !if (!eq(!cast<string>(AlignSize), "WordAccess"), offset{5-2}, + !if (!eq(!cast<string>(AlignSize), "HalfWordAccess"), offset{4-1}, + /* ByteAccess */ offset{3-0}))); + let Inst{1} = 0b0; + } + +let isCodeGenOnly = 0 in { +def S2_storerb_pci : T_store_pci<"memb", IntRegs, s4_0Imm, 0b1000, + ByteAccess>; +def S2_storerh_pci : T_store_pci<"memh", IntRegs, s4_1Imm, 0b1010, + HalfWordAccess>; +def S2_storerf_pci : T_store_pci<"memh", IntRegs, s4_1Imm, 0b1011, + HalfWordAccess, "Rt.h">; +def S2_storeri_pci : T_store_pci<"memw", IntRegs, s4_2Imm, 0b1100, + WordAccess>; +def S2_storerd_pci : T_store_pci<"memd", DoubleRegs, s4_3Imm, 0b1110, + DoubleWordAccess>; } + +//===----------------------------------------------------------------------===// +// Circular stores with auto-increment register +//===----------------------------------------------------------------------===// +let Uses = [CS], isNVStorable = 1, isCodeGenOnly = 0 in +class T_store_pcr <string mnemonic, RegisterClass RC, bits<4>MajOp, + MemAccessSize AlignSize, string RegSrc = "Rt"> + : STInst <(outs IntRegs:$_dst_), + (ins IntRegs:$Rz, ModRegs:$Mu, RC:$Rt), + #mnemonic#"($Rz ++ I:circ($Mu)) = $"#RegSrc#"", + [], + "$Rz = $_dst_" > { + bits<5> Rz; + bits<1> Mu; + bits<5> Rt; + + let accessSize = AlignSize; + + let IClass = 0b1010; + let Inst{27-25} = 0b100; + let Inst{24-21} = MajOp; + let Inst{20-16} = Rz; + let Inst{13} = Mu; + let Inst{12-8} = Rt; + let Inst{7} = 0b0; + let Inst{1} = 0b1; + } + +let isCodeGenOnly = 0 in { +def S2_storerb_pcr : T_store_pcr<"memb", IntRegs, 0b1000, ByteAccess>; +def S2_storerh_pcr : T_store_pcr<"memh", IntRegs, 0b1010, HalfWordAccess>; +def S2_storeri_pcr : T_store_pcr<"memw", IntRegs, 0b1100, WordAccess>; +def S2_storerd_pcr : T_store_pcr<"memd", DoubleRegs, 0b1110, DoubleWordAccess>; +def S2_storerf_pcr : T_store_pcr<"memh", IntRegs, 0b1011, + HalfWordAccess, "Rt.h">; +} + +//===----------------------------------------------------------------------===// +// Bit-reversed stores with auto-increment register +//===----------------------------------------------------------------------===// +let hasSideEffects = 0 in +class T_store_pbr<string mnemonic, RegisterClass RC, + MemAccessSize addrSize, bits<3> majOp, + bit isHalf = 0> + : STInst + <(outs IntRegs:$_dst_), + (ins IntRegs:$Rz, ModRegs:$Mu, RC:$src), + #mnemonic#"($Rz ++ $Mu:brev) = $src"#!if (!eq(isHalf, 1), ".h", ""), + [], "$Rz = $_dst_" > { + + let accessSize = addrSize; + + bits<5> Rz; + bits<1> Mu; + bits<5> src; + + let IClass = 0b1010; + + let Inst{27-24} = 0b1111; + let Inst{23-21} = majOp; + let Inst{7} = 0b0; + let Inst{20-16} = Rz; + let Inst{13} = Mu; + let Inst{12-8} = src; + } + +let isNVStorable = 1, isCodeGenOnly = 0 in { + let BaseOpcode = "S2_storerb_pbr" in + def S2_storerb_pbr : T_store_pbr<"memb", IntRegs, ByteAccess, + 0b000>, NewValueRel; + let BaseOpcode = "S2_storerh_pbr" in + def S2_storerh_pbr : T_store_pbr<"memh", IntRegs, HalfWordAccess, + 0b010>, NewValueRel; + let BaseOpcode = "S2_storeri_pbr" in + def S2_storeri_pbr : T_store_pbr<"memw", IntRegs, WordAccess, + 0b100>, NewValueRel; +} +let isCodeGenOnly = 0 in { +def S2_storerf_pbr : T_store_pbr<"memh", IntRegs, HalfWordAccess, 0b011, 1>; +def S2_storerd_pbr : T_store_pbr<"memd", DoubleRegs, DoubleWordAccess, 0b110>; +} + //===----------------------------------------------------------------------===// // ST - //===----------------------------------------------------------------------===// @@ -1637,69 +3122,423 @@ def NOT_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1), [(set (i64 DoubleRegs:$dst), (not (i64 DoubleRegs:$src1)))]>; -// Sign extend word to doubleword. -def SXTW : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1), - "$dst = sxtw($src1)", - [(set (i64 DoubleRegs:$dst), (sext (i32 IntRegs:$src1)))]>; //===----------------------------------------------------------------------===// // STYPE/ALU - //===----------------------------------------------------------------------===// +let hasSideEffects = 0 in +class T_S2op_1 <string mnemonic, bits<4> RegTyBits, RegisterClass RCOut, + RegisterClass RCIn, bits<2> MajOp, bits<3> MinOp, bit isSat> + : SInst <(outs RCOut:$dst), (ins RCIn:$src), + "$dst = "#mnemonic#"($src)"#!if(isSat, ":sat", ""), + [], "", S_2op_tc_1_SLOT23 > { + bits<5> dst; + bits<5> src; + + let IClass = 0b1000; + + let Inst{27-24} = RegTyBits; + let Inst{23-22} = MajOp; + let Inst{21} = 0b0; + let Inst{20-16} = src; + let Inst{7-5} = MinOp; + let Inst{4-0} = dst; + } + +class T_S2op_1_di <string mnemonic, bits<2> MajOp, bits<3> MinOp> + : T_S2op_1 <mnemonic, 0b0100, DoubleRegs, IntRegs, MajOp, MinOp, 0>; + +let hasNewValue = 1 in +class T_S2op_1_id <string mnemonic, bits<2> MajOp, bits<3> MinOp, bit isSat = 0> + : T_S2op_1 <mnemonic, 0b1000, IntRegs, DoubleRegs, MajOp, MinOp, isSat>; + +let hasNewValue = 1 in +class T_S2op_1_ii <string mnemonic, bits<2> MajOp, bits<3> MinOp, bit isSat = 0> + : T_S2op_1 <mnemonic, 0b1100, IntRegs, IntRegs, MajOp, MinOp, isSat>; + +// Sign extend word to doubleword +let isCodeGenOnly = 0 in +def A2_sxtw : T_S2op_1_di <"sxtw", 0b01, 0b000>; + +def: Pat <(i64 (sext I32:$src)), (A2_sxtw I32:$src)>; + +// Swizzle the bytes of a word +let isCodeGenOnly = 0 in +def A2_swiz : T_S2op_1_ii <"swiz", 0b10, 0b111>; + +// Saturate +let Defs = [USR_OVF], isCodeGenOnly = 0 in { + def A2_sat : T_S2op_1_id <"sat", 0b11, 0b000>; + def A2_satb : T_S2op_1_ii <"satb", 0b11, 0b111>; + def A2_satub : T_S2op_1_ii <"satub", 0b11, 0b110>; + def A2_sath : T_S2op_1_ii <"sath", 0b11, 0b100>; + def A2_satuh : T_S2op_1_ii <"satuh", 0b11, 0b101>; +} + +let Itinerary = S_2op_tc_2_SLOT23, isCodeGenOnly = 0 in { + // Absolute value word + def A2_abs : T_S2op_1_ii <"abs", 0b10, 0b100>; + + let Defs = [USR_OVF] in + def A2_abssat : T_S2op_1_ii <"abs", 0b10, 0b101, 1>; + + // Negate with saturation + let Defs = [USR_OVF] in + def A2_negsat : T_S2op_1_ii <"neg", 0b10, 0b110, 1>; +} + +def: Pat<(i32 (select (i1 (setlt (i32 IntRegs:$src), 0)), + (i32 (sub 0, (i32 IntRegs:$src))), + (i32 IntRegs:$src))), + (A2_abs IntRegs:$src)>; + +let AddedComplexity = 50 in +def: Pat<(i32 (xor (add (sra (i32 IntRegs:$src), (i32 31)), + (i32 IntRegs:$src)), + (sra (i32 IntRegs:$src), (i32 31)))), + (A2_abs IntRegs:$src)>; + +class T_S2op_2 <string mnemonic, bits<4> RegTyBits, RegisterClass RCOut, + RegisterClass RCIn, bits<3> MajOp, bits<3> MinOp, + bit isSat, bit isRnd, list<dag> pattern = []> + : SInst <(outs RCOut:$dst), + (ins RCIn:$src, u5Imm:$u5), + "$dst = "#mnemonic#"($src, #$u5)"#!if(isSat, ":sat", "") + #!if(isRnd, ":rnd", ""), + pattern, "", S_2op_tc_2_SLOT23> { + bits<5> dst; + bits<5> src; + bits<5> u5; + + let IClass = 0b1000; + + let Inst{27-24} = RegTyBits; + let Inst{23-21} = MajOp; + let Inst{20-16} = src; + let Inst{13} = 0b0; + let Inst{12-8} = u5; + let Inst{7-5} = MinOp; + let Inst{4-0} = dst; + } + +class T_S2op_2_di <string mnemonic, bits<3> MajOp, bits<3> MinOp> + : T_S2op_2 <mnemonic, 0b1000, DoubleRegs, IntRegs, MajOp, MinOp, 0, 0>; + +let hasNewValue = 1 in +class T_S2op_2_id <string mnemonic, bits<3> MajOp, bits<3> MinOp> + : T_S2op_2 <mnemonic, 0b1000, IntRegs, DoubleRegs, MajOp, MinOp, 0, 0>; + +let hasNewValue = 1 in +class T_S2op_2_ii <string mnemonic, bits<3> MajOp, bits<3> MinOp, + bit isSat = 0, bit isRnd = 0, list<dag> pattern = []> + : T_S2op_2 <mnemonic, 0b1100, IntRegs, IntRegs, MajOp, MinOp, + isSat, isRnd, pattern>; + +class T_S2op_shift <string mnemonic, bits<3> MajOp, bits<3> MinOp, SDNode OpNd> + : T_S2op_2_ii <mnemonic, MajOp, MinOp, 0, 0, + [(set (i32 IntRegs:$dst), (OpNd (i32 IntRegs:$src), + (u5ImmPred:$u5)))]>; + +// Arithmetic/logical shift right/left by immediate +let Itinerary = S_2op_tc_1_SLOT23, isCodeGenOnly = 0 in { + def S2_asr_i_r : T_S2op_shift <"asr", 0b000, 0b000, sra>; + def S2_lsr_i_r : T_S2op_shift <"lsr", 0b000, 0b001, srl>; + def S2_asl_i_r : T_S2op_shift <"asl", 0b000, 0b010, shl>; +} + +// Shift left by immediate with saturation +let Defs = [USR_OVF], isCodeGenOnly = 0 in +def S2_asl_i_r_sat : T_S2op_2_ii <"asl", 0b010, 0b010, 1>; + +// Shift right with round +let isCodeGenOnly = 0 in +def S2_asr_i_r_rnd : T_S2op_2_ii <"asr", 0b010, 0b000, 0, 1>; + +def: Pat<(i32 (sra (i32 (add (i32 (sra I32:$src1, u5ImmPred:$src2)), + (i32 1))), + (i32 1))), + (S2_asr_i_r_rnd IntRegs:$src1, u5ImmPred:$src2)>; + +class T_S2op_3<string opc, bits<2>MajOp, bits<3>minOp, bits<1> sat = 0> + : SInst<(outs DoubleRegs:$Rdd), (ins DoubleRegs:$Rss), + "$Rdd = "#opc#"($Rss)"#!if(!eq(sat, 1),":sat","")> { + bits<5> Rss; + bits<5> Rdd; + let IClass = 0b1000; + let Inst{27-24} = 0; + let Inst{23-22} = MajOp; + let Inst{20-16} = Rss; + let Inst{7-5} = minOp; + let Inst{4-0} = Rdd; +} + +let isCodeGenOnly = 0 in { +def A2_absp : T_S2op_3 <"abs", 0b10, 0b110>; +def A2_negp : T_S2op_3 <"neg", 0b10, 0b101>; +def A2_notp : T_S2op_3 <"not", 0b10, 0b100>; +} + +// Innterleave/deinterleave +let isCodeGenOnly = 0 in { +def S2_interleave : T_S2op_3 <"interleave", 0b11, 0b101>; +def S2_deinterleave : T_S2op_3 <"deinterleave", 0b11, 0b100>; +} + //===----------------------------------------------------------------------===// // STYPE/BIT + //===----------------------------------------------------------------------===// -// clrbit. -def CLRBIT : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), - "$dst = clrbit($src1, #$src2)", - [(set (i32 IntRegs:$dst), (and (i32 IntRegs:$src1), - (not - (shl 1, u5ImmPred:$src2))))]>; +// Bit count + +let hasSideEffects = 0, hasNewValue = 1 in +class T_COUNT_LEADING<string MnOp, bits<3> MajOp, bits<3> MinOp, bit Is32, + dag Out, dag Inp> + : SInst<Out, Inp, "$Rd = "#MnOp#"($Rs)", [], "", S_2op_tc_1_SLOT23> { + bits<5> Rs; + bits<5> Rd; + let IClass = 0b1000; + let Inst{27} = 0b1; + let Inst{26} = Is32; + let Inst{25-24} = 0b00; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rd; +} -def CLRBIT_31 : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), - "$dst = clrbit($src1, #$src2)", - []>; +class T_COUNT_LEADING_32<string MnOp, bits<3> MajOp, bits<3> MinOp> + : T_COUNT_LEADING<MnOp, MajOp, MinOp, 0b1, + (outs IntRegs:$Rd), (ins IntRegs:$Rs)>; + +class T_COUNT_LEADING_64<string MnOp, bits<3> MajOp, bits<3> MinOp> + : T_COUNT_LEADING<MnOp, MajOp, MinOp, 0b0, + (outs IntRegs:$Rd), (ins DoubleRegs:$Rs)>; + +let isCodeGenOnly = 0 in { +def S2_cl0 : T_COUNT_LEADING_32<"cl0", 0b000, 0b101>; +def S2_cl1 : T_COUNT_LEADING_32<"cl1", 0b000, 0b110>; +def S2_ct0 : T_COUNT_LEADING_32<"ct0", 0b010, 0b100>; +def S2_ct1 : T_COUNT_LEADING_32<"ct1", 0b010, 0b101>; +def S2_cl0p : T_COUNT_LEADING_64<"cl0", 0b010, 0b010>; +def S2_cl1p : T_COUNT_LEADING_64<"cl1", 0b010, 0b100>; +def S2_clb : T_COUNT_LEADING_32<"clb", 0b000, 0b100>; +def S2_clbp : T_COUNT_LEADING_64<"clb", 0b010, 0b000>; +def S2_clbnorm : T_COUNT_LEADING_32<"normamt", 0b000, 0b111>; +} -// Map from r0 = and(r1, 2147483647) to r0 = clrbit(r1, #31). -def : Pat <(and (i32 IntRegs:$src1), 2147483647), - (CLRBIT_31 (i32 IntRegs:$src1), 31)>; +def: Pat<(i32 (ctlz I32:$Rs)), (S2_cl0 I32:$Rs)>; +def: Pat<(i32 (ctlz (not I32:$Rs))), (S2_cl1 I32:$Rs)>; +def: Pat<(i32 (cttz I32:$Rs)), (S2_ct0 I32:$Rs)>; +def: Pat<(i32 (cttz (not I32:$Rs))), (S2_ct1 I32:$Rs)>; +def: Pat<(i32 (trunc (ctlz I64:$Rss))), (S2_cl0p I64:$Rss)>; +def: Pat<(i32 (trunc (ctlz (not I64:$Rss)))), (S2_cl1p I64:$Rss)>; + +// Bit set/clear/toggle + +let hasSideEffects = 0, hasNewValue = 1 in +class T_SCT_BIT_IMM<string MnOp, bits<3> MinOp> + : SInst<(outs IntRegs:$Rd), (ins IntRegs:$Rs, u5Imm:$u5), + "$Rd = "#MnOp#"($Rs, #$u5)", [], "", S_2op_tc_1_SLOT23> { + bits<5> Rd; + bits<5> Rs; + bits<5> u5; + let IClass = 0b1000; + let Inst{27-21} = 0b1100110; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-8} = u5; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rd; +} -// setbit. -def SETBIT : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), - "$dst = setbit($src1, #$src2)", - [(set (i32 IntRegs:$dst), (or (i32 IntRegs:$src1), - (shl 1, u5ImmPred:$src2)))]>; +let hasSideEffects = 0, hasNewValue = 1 in +class T_SCT_BIT_REG<string MnOp, bits<2> MinOp> + : SInst<(outs IntRegs:$Rd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = "#MnOp#"($Rs, $Rt)", [], "", S_3op_tc_1_SLOT23> { + bits<5> Rd; + bits<5> Rs; + bits<5> Rt; + let IClass = 0b1100; + let Inst{27-22} = 0b011010; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{7-6} = MinOp; + let Inst{4-0} = Rd; +} -// Map from r0 = or(r1, -2147483648) to r0 = setbit(r1, #31). -def SETBIT_31 : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), - "$dst = setbit($src1, #$src2)", - []>; +let isCodeGenOnly = 0 in { +def S2_clrbit_i : T_SCT_BIT_IMM<"clrbit", 0b001>; +def S2_setbit_i : T_SCT_BIT_IMM<"setbit", 0b000>; +def S2_togglebit_i : T_SCT_BIT_IMM<"togglebit", 0b010>; +def S2_clrbit_r : T_SCT_BIT_REG<"clrbit", 0b01>; +def S2_setbit_r : T_SCT_BIT_REG<"setbit", 0b00>; +def S2_togglebit_r : T_SCT_BIT_REG<"togglebit", 0b10>; +} -def : Pat <(or (i32 IntRegs:$src1), -2147483648), - (SETBIT_31 (i32 IntRegs:$src1), 31)>; +def: Pat<(i32 (and (i32 IntRegs:$Rs), (not (shl 1, u5ImmPred:$u5)))), + (S2_clrbit_i IntRegs:$Rs, u5ImmPred:$u5)>; +def: Pat<(i32 (or (i32 IntRegs:$Rs), (shl 1, u5ImmPred:$u5))), + (S2_setbit_i IntRegs:$Rs, u5ImmPred:$u5)>; +def: Pat<(i32 (xor (i32 IntRegs:$Rs), (shl 1, u5ImmPred:$u5))), + (S2_togglebit_i IntRegs:$Rs, u5ImmPred:$u5)>; +def: Pat<(i32 (and (i32 IntRegs:$Rs), (not (shl 1, (i32 IntRegs:$Rt))))), + (S2_clrbit_r IntRegs:$Rs, IntRegs:$Rt)>; +def: Pat<(i32 (or (i32 IntRegs:$Rs), (shl 1, (i32 IntRegs:$Rt)))), + (S2_setbit_r IntRegs:$Rs, IntRegs:$Rt)>; +def: Pat<(i32 (xor (i32 IntRegs:$Rs), (shl 1, (i32 IntRegs:$Rt)))), + (S2_togglebit_r IntRegs:$Rs, IntRegs:$Rt)>; + +// Bit test + +let hasSideEffects = 0 in +class T_TEST_BIT_IMM<string MnOp, bits<3> MajOp> + : SInst<(outs PredRegs:$Pd), (ins IntRegs:$Rs, u5Imm:$u5), + "$Pd = "#MnOp#"($Rs, #$u5)", + [], "", S_2op_tc_2early_SLOT23> { + bits<2> Pd; + bits<5> Rs; + bits<5> u5; + let IClass = 0b1000; + let Inst{27-24} = 0b0101; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{13} = 0; + let Inst{12-8} = u5; + let Inst{1-0} = Pd; +} -// togglebit. -def TOGBIT : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), - "$dst = setbit($src1, #$src2)", - [(set (i32 IntRegs:$dst), (xor (i32 IntRegs:$src1), - (shl 1, u5ImmPred:$src2)))]>; +let hasSideEffects = 0 in +class T_TEST_BIT_REG<string MnOp, bit IsNeg> + : SInst<(outs PredRegs:$Pd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Pd = "#MnOp#"($Rs, $Rt)", + [], "", S_3op_tc_2early_SLOT23> { + bits<2> Pd; + bits<5> Rs; + bits<5> Rt; + let IClass = 0b1100; + let Inst{27-22} = 0b011100; + let Inst{21} = IsNeg; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{1-0} = Pd; +} -// Map from r0 = xor(r1, -2147483648) to r0 = togglebit(r1, #31). -def TOGBIT_31 : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), - "$dst = togglebit($src1, #$src2)", - []>; +let isCodeGenOnly = 0 in { +def S2_tstbit_i : T_TEST_BIT_IMM<"tstbit", 0b000>; +def S2_tstbit_r : T_TEST_BIT_REG<"tstbit", 0>; +} + +let AddedComplexity = 20 in { // Complexity greater than cmp reg-imm. + def: Pat<(i1 (setne (and (shl 1, u5ImmPred:$u5), (i32 IntRegs:$Rs)), 0)), + (S2_tstbit_i IntRegs:$Rs, u5ImmPred:$u5)>; + def: Pat<(i1 (setne (and (shl 1, (i32 IntRegs:$Rt)), (i32 IntRegs:$Rs)), 0)), + (S2_tstbit_r IntRegs:$Rs, IntRegs:$Rt)>; + def: Pat<(i1 (trunc (i32 IntRegs:$Rs))), + (S2_tstbit_i IntRegs:$Rs, 0)>; + def: Pat<(i1 (trunc (i64 DoubleRegs:$Rs))), + (S2_tstbit_i (LoReg DoubleRegs:$Rs), 0)>; +} +let hasSideEffects = 0 in +class T_TEST_BITS_IMM<string MnOp, bits<2> MajOp, bit IsNeg> + : SInst<(outs PredRegs:$Pd), (ins IntRegs:$Rs, u6Imm:$u6), + "$Pd = "#MnOp#"($Rs, #$u6)", + [], "", S_2op_tc_2early_SLOT23> { + bits<2> Pd; + bits<5> Rs; + bits<6> u6; + let IClass = 0b1000; + let Inst{27-24} = 0b0101; + let Inst{23-22} = MajOp; + let Inst{21} = IsNeg; + let Inst{20-16} = Rs; + let Inst{13-8} = u6; + let Inst{1-0} = Pd; +} + +let hasSideEffects = 0 in +class T_TEST_BITS_REG<string MnOp, bits<2> MajOp, bit IsNeg> + : SInst<(outs PredRegs:$Pd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Pd = "#MnOp#"($Rs, $Rt)", + [], "", S_3op_tc_2early_SLOT23> { + bits<2> Pd; + bits<5> Rs; + bits<5> Rt; + let IClass = 0b1100; + let Inst{27-24} = 0b0111; + let Inst{23-22} = MajOp; + let Inst{21} = IsNeg; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{1-0} = Pd; +} -def : Pat <(xor (i32 IntRegs:$src1), -2147483648), - (TOGBIT_31 (i32 IntRegs:$src1), 31)>; +let isCodeGenOnly = 0 in { +def C2_bitsclri : T_TEST_BITS_IMM<"bitsclr", 0b10, 0>; +def C2_bitsclr : T_TEST_BITS_REG<"bitsclr", 0b10, 0>; +def C2_bitsset : T_TEST_BITS_REG<"bitsset", 0b01, 0>; +} + +let AddedComplexity = 20 in { // Complexity greater than compare reg-imm. + def: Pat<(i1 (seteq (and (i32 IntRegs:$Rs), u6ImmPred:$u6), 0)), + (C2_bitsclri IntRegs:$Rs, u6ImmPred:$u6)>; + def: Pat<(i1 (seteq (and (i32 IntRegs:$Rs), (i32 IntRegs:$Rt)), 0)), + (C2_bitsclr IntRegs:$Rs, IntRegs:$Rt)>; +} + +let AddedComplexity = 10 in // Complexity greater than compare reg-reg. +def: Pat<(i1 (seteq (and (i32 IntRegs:$Rs), (i32 IntRegs:$Rt)), IntRegs:$Rt)), + (C2_bitsset IntRegs:$Rs, IntRegs:$Rt)>; + +//===----------------------------------------------------------------------===// +// STYPE/BIT - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// STYPE/COMPLEX + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// STYPE/COMPLEX - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// XTYPE/PERM + +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// XTYPE/PERM - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// STYPE/PRED + +//===----------------------------------------------------------------------===// // Predicate transfer. -let neverHasSideEffects = 1 in -def TFR_RsPd : SInst<(outs IntRegs:$dst), (ins PredRegs:$src1), - "$dst = $src1 /* Should almost never emit this. */", - []>; +let hasSideEffects = 0, hasNewValue = 1, isCodeGenOnly = 0 in +def C2_tfrpr : SInst<(outs IntRegs:$Rd), (ins PredRegs:$Ps), + "$Rd = $Ps", [], "", S_2op_tc_1_SLOT23> { + bits<5> Rd; + bits<2> Ps; + + let IClass = 0b1000; + let Inst{27-24} = 0b1001; + let Inst{22} = 0b1; + let Inst{17-16} = Ps; + let Inst{4-0} = Rd; +} + +// Transfer general register to predicate. +let hasSideEffects = 0, isCodeGenOnly = 0 in +def C2_tfrrp: SInst<(outs PredRegs:$Pd), (ins IntRegs:$Rs), + "$Pd = $Rs", [], "", S_2op_tc_2early_SLOT23> { + bits<2> Pd; + bits<5> Rs; + + let IClass = 0b1000; + let Inst{27-21} = 0b0101010; + let Inst{20-16} = Rs; + let Inst{1-0} = Pd; +} + -def TFR_PdRs : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1), - "$dst = $src1 /* Should almost never emit this. */", - [(set (i1 PredRegs:$dst), (trunc (i32 IntRegs:$src1)))]>; //===----------------------------------------------------------------------===// // STYPE/PRED - //===----------------------------------------------------------------------===// @@ -1707,88 +3546,59 @@ def TFR_PdRs : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1), //===----------------------------------------------------------------------===// // STYPE/SHIFT + //===----------------------------------------------------------------------===// +class S_2OpInstImm<string Mnemonic, bits<3>MajOp, bits<3>MinOp, + Operand Imm, list<dag> pattern = [], bit isRnd = 0> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, Imm:$src2), + "$dst = "#Mnemonic#"($src1, #$src2)"#!if(isRnd, ":rnd", ""), + pattern> { + bits<5> src1; + bits<5> dst; + let IClass = 0b1000; + let Inst{27-24} = 0; + let Inst{23-21} = MajOp; + let Inst{20-16} = src1; + let Inst{7-5} = MinOp; + let Inst{4-0} = dst; +} + +class S_2OpInstImmI6<string Mnemonic, SDNode OpNode, bits<3>MinOp> + : S_2OpInstImm<Mnemonic, 0b000, MinOp, u6Imm, + [(set (i64 DoubleRegs:$dst), (OpNode (i64 DoubleRegs:$src1), + u6ImmPred:$src2))]> { + bits<6> src2; + let Inst{13-8} = src2; +} + // Shift by immediate. -def ASR_ri : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), - "$dst = asr($src1, #$src2)", - [(set (i32 IntRegs:$dst), (sra (i32 IntRegs:$src1), - u5ImmPred:$src2))]>; - -def ASRd_ri : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2), - "$dst = asr($src1, #$src2)", - [(set (i64 DoubleRegs:$dst), (sra (i64 DoubleRegs:$src1), - u6ImmPred:$src2))]>; - -def ASL : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), - "$dst = asl($src1, #$src2)", - [(set (i32 IntRegs:$dst), (shl (i32 IntRegs:$src1), - u5ImmPred:$src2))]>; - -def ASLd_ri : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2), - "$dst = asl($src1, #$src2)", - [(set (i64 DoubleRegs:$dst), (shl (i64 DoubleRegs:$src1), - u6ImmPred:$src2))]>; - -def LSR_ri : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), - "$dst = lsr($src1, #$src2)", - [(set (i32 IntRegs:$dst), (srl (i32 IntRegs:$src1), - u5ImmPred:$src2))]>; - -def LSRd_ri : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2), - "$dst = lsr($src1, #$src2)", - [(set (i64 DoubleRegs:$dst), (srl (i64 DoubleRegs:$src1), - u6ImmPred:$src2))]>; - -// Shift by immediate and add. -let AddedComplexity = 100 in -def ADDASL : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, - u3Imm:$src3), - "$dst = addasl($src1, $src2, #$src3)", - [(set (i32 IntRegs:$dst), (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u3ImmPred:$src3)))]>; - -// Shift by register. -def ASL_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = asl($src1, $src2)", - [(set (i32 IntRegs:$dst), (shl (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))]>; - -def ASR_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = asr($src1, $src2)", - [(set (i32 IntRegs:$dst), (sra (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))]>; - -def LSL_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = lsl($src1, $src2)", - [(set (i32 IntRegs:$dst), (shl (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))]>; - -def LSR_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), - "$dst = lsr($src1, $src2)", - [(set (i32 IntRegs:$dst), (srl (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))]>; - -def ASLd : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2), - "$dst = asl($src1, $src2)", - [(set (i64 DoubleRegs:$dst), (shl (i64 DoubleRegs:$src1), - (i32 IntRegs:$src2)))]>; - -def LSLd : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2), - "$dst = lsl($src1, $src2)", - [(set (i64 DoubleRegs:$dst), (shl (i64 DoubleRegs:$src1), - (i32 IntRegs:$src2)))]>; - -def ASRd_rr : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - IntRegs:$src2), - "$dst = asr($src1, $src2)", - [(set (i64 DoubleRegs:$dst), (sra (i64 DoubleRegs:$src1), - (i32 IntRegs:$src2)))]>; - -def LSRd_rr : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - IntRegs:$src2), - "$dst = lsr($src1, $src2)", - [(set (i64 DoubleRegs:$dst), (srl (i64 DoubleRegs:$src1), - (i32 IntRegs:$src2)))]>; +let isCodeGenOnly = 0 in { +def S2_asr_i_p : S_2OpInstImmI6<"asr", sra, 0b000>; +def S2_asl_i_p : S_2OpInstImmI6<"asl", shl, 0b010>; +def S2_lsr_i_p : S_2OpInstImmI6<"lsr", srl, 0b001>; +} + +// Shift left by small amount and add. +let AddedComplexity = 100, hasNewValue = 1, hasSideEffects = 0, + isCodeGenOnly = 0 in +def S2_addasl_rrri: SInst <(outs IntRegs:$Rd), + (ins IntRegs:$Rt, IntRegs:$Rs, u3Imm:$u3), + "$Rd = addasl($Rt, $Rs, #$u3)" , + [(set (i32 IntRegs:$Rd), (add (i32 IntRegs:$Rt), + (shl (i32 IntRegs:$Rs), u3ImmPred:$u3)))], + "", S_3op_tc_2_SLOT23> { + bits<5> Rd; + bits<5> Rt; + bits<5> Rs; + bits<3> u3; + + let IClass = 0b1100; + + let Inst{27-21} = 0b0100000; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-8} = Rt; + let Inst{7-5} = u3; + let Inst{4-0} = Rd; + } //===----------------------------------------------------------------------===// // STYPE/SHIFT - @@ -1815,38 +3625,191 @@ def LSRd_rr : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, //===----------------------------------------------------------------------===// // SYSTEM/USER + //===----------------------------------------------------------------------===// -def SDHexagonBARRIER: SDTypeProfile<0, 0, []>; -def HexagonBARRIER: SDNode<"HexagonISD::BARRIER", SDHexagonBARRIER, - [SDNPHasChain]>; +def HexagonBARRIER: SDNode<"HexagonISD::BARRIER", SDTNone, [SDNPHasChain]>; -let hasSideEffects = 1, isSolo = 1 in +let hasSideEffects = 1, isSoloAX = 1, isCodeGenOnly = 0 in def BARRIER : SYSInst<(outs), (ins), "barrier", - [(HexagonBARRIER)]>; + [(HexagonBARRIER)],"",ST_tc_st_SLOT0> { + let Inst{31-28} = 0b1010; + let Inst{27-21} = 0b1000000; +} //===----------------------------------------------------------------------===// // SYSTEM/SUPER - //===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// CRUSER - Type. +//===----------------------------------------------------------------------===// +// HW loop +let isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2, + opExtendable = 0, hasSideEffects = 0 in +class LOOP_iBase<string mnemonic, Operand brOp, bit mustExtend = 0> + : CRInst<(outs), (ins brOp:$offset, u10Imm:$src2), + #mnemonic#"($offset, #$src2)", + [], "" , CR_tc_3x_SLOT3> { + bits<9> offset; + bits<10> src2; + + let IClass = 0b0110; + + let Inst{27-22} = 0b100100; + let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1); + let Inst{20-16} = src2{9-5}; + let Inst{12-8} = offset{8-4}; + let Inst{7-5} = src2{4-2}; + let Inst{4-3} = offset{3-2}; + let Inst{1-0} = src2{1-0}; +} + +let isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2, + opExtendable = 0, hasSideEffects = 0 in +class LOOP_rBase<string mnemonic, Operand brOp, bit mustExtend = 0> + : CRInst<(outs), (ins brOp:$offset, IntRegs:$src2), + #mnemonic#"($offset, $src2)", + [], "" ,CR_tc_3x_SLOT3> { + bits<9> offset; + bits<5> src2; + + let IClass = 0b0110; + + let Inst{27-22} = 0b000000; + let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1); + let Inst{20-16} = src2; + let Inst{12-8} = offset{8-4}; + let Inst{4-3} = offset{3-2}; + } + +multiclass LOOP_ri<string mnemonic> { + def i : LOOP_iBase<mnemonic, brtarget>; + def r : LOOP_rBase<mnemonic, brtarget>; +} + + +let Defs = [SA0, LC0, USR], isCodeGenOnly = 0 in +defm J2_loop0 : LOOP_ri<"loop0">; + +// Interestingly only loop0's appear to set usr.lpcfg +let Defs = [SA1, LC1], isCodeGenOnly = 0 in +defm J2_loop1 : LOOP_ri<"loop1">; + +let isBranch = 1, isTerminator = 1, hasSideEffects = 0, + Defs = [PC, LC0], Uses = [SA0, LC0] in { +def ENDLOOP0 : Endloop<(outs), (ins brtarget:$offset), + ":endloop0", + []>; +} + +let isBranch = 1, isTerminator = 1, hasSideEffects = 0, + Defs = [PC, LC1], Uses = [SA1, LC1] in { +def ENDLOOP1 : Endloop<(outs), (ins brtarget:$offset), + ":endloop1", + []>; +} + +// Pipelined loop instructions, sp[123]loop0 +let Defs = [LC0, SA0, P3, USR], hasSideEffects = 0, + isExtentSigned = 1, isExtendable = 1, opExtentBits = 9, opExtentAlign = 2, + opExtendable = 0, isPredicateLate = 1 in +class SPLOOP_iBase<string SP, bits<2> op> + : CRInst <(outs), (ins brtarget:$r7_2, u10Imm:$U10), + "p3 = sp"#SP#"loop0($r7_2, #$U10)" > { + bits<9> r7_2; + bits<10> U10; + + let IClass = 0b0110; + + let Inst{22-21} = op; + let Inst{27-23} = 0b10011; + let Inst{20-16} = U10{9-5}; + let Inst{12-8} = r7_2{8-4}; + let Inst{7-5} = U10{4-2}; + let Inst{4-3} = r7_2{3-2}; + let Inst{1-0} = U10{1-0}; + } + +let Defs = [LC0, SA0, P3, USR], hasSideEffects = 0, + isExtentSigned = 1, isExtendable = 1, opExtentBits = 9, opExtentAlign = 2, + opExtendable = 0, isPredicateLate = 1 in +class SPLOOP_rBase<string SP, bits<2> op> + : CRInst <(outs), (ins brtarget:$r7_2, IntRegs:$Rs), + "p3 = sp"#SP#"loop0($r7_2, $Rs)" > { + bits<9> r7_2; + bits<5> Rs; + + let IClass = 0b0110; + + let Inst{22-21} = op; + let Inst{27-23} = 0b00001; + let Inst{20-16} = Rs; + let Inst{12-8} = r7_2{8-4}; + let Inst{4-3} = r7_2{3-2}; + } + +multiclass SPLOOP_ri<string mnemonic, bits<2> op> { + def i : SPLOOP_iBase<mnemonic, op>; + def r : SPLOOP_rBase<mnemonic, op>; +} + +let isCodeGenOnly = 0 in { +defm J2_ploop1s : SPLOOP_ri<"1", 0b01>; +defm J2_ploop2s : SPLOOP_ri<"2", 0b10>; +defm J2_ploop3s : SPLOOP_ri<"3", 0b11>; +} + +// Transfer to/from Control/GPR Guest/GPR +let hasSideEffects = 0 in +class TFR_CR_RS_base<RegisterClass CTRC, RegisterClass RC, bit isDouble> + : CRInst <(outs CTRC:$dst), (ins RC:$src), + "$dst = $src", [], "", CR_tc_3x_SLOT3> { + bits<5> dst; + bits<5> src; + + let IClass = 0b0110; + + let Inst{27-25} = 0b001; + let Inst{24} = isDouble; + let Inst{23-21} = 0b001; + let Inst{20-16} = src; + let Inst{4-0} = dst; + } +let isCodeGenOnly = 0 in +def A2_tfrrcr : TFR_CR_RS_base<CtrRegs, IntRegs, 0b0>; +def : InstAlias<"m0 = $Rs", (A2_tfrrcr C6, IntRegs:$Rs)>; +def : InstAlias<"m1 = $Rs", (A2_tfrrcr C7, IntRegs:$Rs)>; + +let hasSideEffects = 0 in +class TFR_RD_CR_base<RegisterClass RC, RegisterClass CTRC, bit isSingle> + : CRInst <(outs RC:$dst), (ins CTRC:$src), + "$dst = $src", [], "", CR_tc_3x_SLOT3> { + bits<5> dst; + bits<5> src; + + let IClass = 0b0110; + + let Inst{27-26} = 0b10; + let Inst{25} = isSingle; + let Inst{24-21} = 0b0000; + let Inst{20-16} = src; + let Inst{4-0} = dst; + } + +let hasNewValue = 1, opNewValue = 0, isCodeGenOnly = 0 in +def A2_tfrcrr : TFR_RD_CR_base<IntRegs, CtrRegs, 1>; +def : InstAlias<"$Rd = m0", (A2_tfrcrr IntRegs:$Rd, C6)>; +def : InstAlias<"$Rd = m1", (A2_tfrcrr IntRegs:$Rd, C7)>; + +// Y4_trace: Send value to etm trace. +let isSoloAX = 1, hasSideEffects = 0, isCodeGenOnly = 0 in +def Y4_trace: CRInst <(outs), (ins IntRegs:$Rs), + "trace($Rs)"> { + bits<5> Rs; + + let IClass = 0b0110; + let Inst{27-21} = 0b0010010; + let Inst{20-16} = Rs; + } -// TFRI64 - assembly mapped. -let isReMaterializable = 1 in -def TFRI64 : ALU64_rr<(outs DoubleRegs:$dst), (ins s8Imm64:$src1), - "$dst = #$src1", - [(set (i64 DoubleRegs:$dst), s8Imm64Pred:$src1)]>; - -// Pseudo instruction to encode a set of conditional transfers. -// This instruction is used instead of a mux and trades-off codesize -// for performance. We conduct this transformation optimistically in -// the hope that these instructions get promoted to dot-new transfers. -let AddedComplexity = 100, isPredicated = 1 in -def TFR_condset_rr : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, - IntRegs:$src2, - IntRegs:$src3), - "Error; should not emit", - [(set (i32 IntRegs:$dst), - (i32 (select (i1 PredRegs:$src1), - (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))]>; let AddedComplexity = 100, isPredicated = 1 in def TFR_condset_ri : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, s12Imm:$src3), @@ -1877,28 +3840,6 @@ def TFR_FI : ALU32_ri<(outs IntRegs:$dst), (ins FrameIndex:$src1), "$dst = add($src1)", [(set (i32 IntRegs:$dst), ADDRri:$src1)]>; -// -// CR - Type. -// -let neverHasSideEffects = 1, Defs = [SA0, LC0] in { -def LOOP0_i : CRInst<(outs), (ins brtarget:$offset, u10Imm:$src2), - "loop0($offset, #$src2)", - []>; -} - -let neverHasSideEffects = 1, Defs = [SA0, LC0] in { -def LOOP0_r : CRInst<(outs), (ins brtarget:$offset, IntRegs:$src2), - "loop0($offset, $src2)", - []>; -} - -let isBranch = 1, isTerminator = 1, neverHasSideEffects = 1, - Defs = [PC, LC0], Uses = [SA0, LC0] in { -def ENDLOOP0 : Endloop<(outs), (ins brtarget:$offset), - ":endloop0", - []>; -} - // Support for generating global address. // Taken from X86InstrInfo.td. def SDTHexagonCONST32 : SDTypeProfile<1, 1, [ @@ -1909,44 +3850,44 @@ def HexagonCONST32 : SDNode<"HexagonISD::CONST32", SDTHexagonCONST32>; def HexagonCONST32_GP : SDNode<"HexagonISD::CONST32_GP", SDTHexagonCONST32>; // HI/LO Instructions -let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in +let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0 in def LO : ALU32_ri<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst.l = #LO($global)", []>; -let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in +let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0 in def HI : ALU32_ri<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst.h = #HI($global)", []>; -let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in +let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0 in def LOi : ALU32_ri<(outs IntRegs:$dst), (ins i32imm:$imm_value), "$dst.l = #LO($imm_value)", []>; -let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in +let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0 in def HIi : ALU32_ri<(outs IntRegs:$dst), (ins i32imm:$imm_value), "$dst.h = #HI($imm_value)", []>; -let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in +let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0 in def LO_jt : ALU32_ri<(outs IntRegs:$dst), (ins jumptablebase:$jt), "$dst.l = #LO($jt)", []>; -let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in +let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0 in def HI_jt : ALU32_ri<(outs IntRegs:$dst), (ins jumptablebase:$jt), "$dst.h = #HI($jt)", []>; -let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in +let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0 in def LO_label : ALU32_ri<(outs IntRegs:$dst), (ins bblabel:$label), "$dst.l = #LO($label)", []>; -let isReMaterializable = 1, isMoveImm = 1 , neverHasSideEffects = 1 in +let isReMaterializable = 1, isMoveImm = 1 , hasSideEffects = 0 in def HI_label : ALU32_ri<(outs IntRegs:$dst), (ins bblabel:$label), "$dst.h = #HI($label)", []>; @@ -2044,22 +3985,16 @@ let Defs = [R29, R30, R31], Uses = [R29] in { [(callseq_end timm:$amt1, timm:$amt2)]>; } // Call subroutine. -let isCall = 1, neverHasSideEffects = 1, +let isCall = 1, hasSideEffects = 0, Defs = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, R22, R23, R28, R31, P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { def CALL : JInst<(outs), (ins calltarget:$dst), "call $dst", []>; } -// Call subroutine from register. -let isCall = 1, neverHasSideEffects = 1, - Defs = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, - R22, R23, R28, R31, P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { - def CALLR : JRInst<(outs), (ins IntRegs:$dst), - "callr $dst", - []>; - } - +// Call subroutine indirectly. +let Defs = VolatileV3.Regs, isCodeGenOnly = 0 in +def J2_callr : JUMPR_MISC_CALLR<0, 1>; // Indirect tail-call. let isCodeGenOnly = 1, isCall = 1, isReturn = 1 in @@ -2068,13 +4003,15 @@ def TCRETURNR : T_JMPr; // Direct tail-calls. let isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0, isTerminator = 1, isCodeGenOnly = 1 in { - def TCRETURNtg : T_JMP<(ins calltarget:$dst)>; - def TCRETURNtext : T_JMP<(ins calltarget:$dst)>; + def TCRETURNtg : JInst<(outs), (ins calltarget:$dst), "jump $dst", + [], "", J_tc_2early_SLOT23>; + def TCRETURNtext : JInst<(outs), (ins calltarget:$dst), "jump $dst", + [], "", J_tc_2early_SLOT23>; } // Map call instruction. def : Pat<(call (i32 IntRegs:$dst)), - (CALLR (i32 IntRegs:$dst))>, Requires<[HasV2TOnly]>; + (J2_callr (i32 IntRegs:$dst))>, Requires<[HasV2TOnly]>; def : Pat<(call tglobaladdr:$dst), (CALL tglobaladdr:$dst)>, Requires<[HasV2TOnly]>; def : Pat<(call texternalsym:$dst), @@ -2090,91 +4027,81 @@ def : Pat<(HexagonTCRet (i32 IntRegs:$dst)), // Atomic load and store support // 8 bit atomic load def : Pat<(atomic_load_8 ADDRriS11_0:$src1), - (i32 (LDriub ADDRriS11_0:$src1))>; + (i32 (L2_loadrub_io AddrFI:$src1, 0))>; def : Pat<(atomic_load_8 (add (i32 IntRegs:$src1), s11_0ImmPred:$offset)), - (i32 (LDriub_indexed (i32 IntRegs:$src1), s11_0ImmPred:$offset))>; + (i32 (L2_loadrub_io (i32 IntRegs:$src1), s11_0ImmPred:$offset))>; // 16 bit atomic load def : Pat<(atomic_load_16 ADDRriS11_1:$src1), - (i32 (LDriuh ADDRriS11_1:$src1))>; + (i32 (L2_loadruh_io AddrFI:$src1, 0))>; def : Pat<(atomic_load_16 (add (i32 IntRegs:$src1), s11_1ImmPred:$offset)), - (i32 (LDriuh_indexed (i32 IntRegs:$src1), s11_1ImmPred:$offset))>; + (i32 (L2_loadruh_io (i32 IntRegs:$src1), s11_1ImmPred:$offset))>; def : Pat<(atomic_load_32 ADDRriS11_2:$src1), - (i32 (LDriw ADDRriS11_2:$src1))>; + (i32 (L2_loadri_io AddrFI:$src1, 0))>; def : Pat<(atomic_load_32 (add (i32 IntRegs:$src1), s11_2ImmPred:$offset)), - (i32 (LDriw_indexed (i32 IntRegs:$src1), s11_2ImmPred:$offset))>; + (i32 (L2_loadri_io (i32 IntRegs:$src1), s11_2ImmPred:$offset))>; // 64 bit atomic load def : Pat<(atomic_load_64 ADDRriS11_3:$src1), - (i64 (LDrid ADDRriS11_3:$src1))>; + (i64 (L2_loadrd_io AddrFI:$src1, 0))>; def : Pat<(atomic_load_64 (add (i32 IntRegs:$src1), s11_3ImmPred:$offset)), - (i64 (LDrid_indexed (i32 IntRegs:$src1), s11_3ImmPred:$offset))>; + (i64 (L2_loadrd_io (i32 IntRegs:$src1), s11_3ImmPred:$offset))>; def : Pat<(atomic_store_8 ADDRriS11_0:$src2, (i32 IntRegs:$src1)), - (STrib ADDRriS11_0:$src2, (i32 IntRegs:$src1))>; + (S2_storerb_io AddrFI:$src2, 0, (i32 IntRegs:$src1))>; def : Pat<(atomic_store_8 (add (i32 IntRegs:$src2), s11_0ImmPred:$offset), (i32 IntRegs:$src1)), - (STrib_indexed (i32 IntRegs:$src2), s11_0ImmPred:$offset, + (S2_storerb_io (i32 IntRegs:$src2), s11_0ImmPred:$offset, (i32 IntRegs:$src1))>; def : Pat<(atomic_store_16 ADDRriS11_1:$src2, (i32 IntRegs:$src1)), - (STrih ADDRriS11_1:$src2, (i32 IntRegs:$src1))>; + (S2_storerh_io AddrFI:$src2, 0, (i32 IntRegs:$src1))>; def : Pat<(atomic_store_16 (i32 IntRegs:$src1), (add (i32 IntRegs:$src2), s11_1ImmPred:$offset)), - (STrih_indexed (i32 IntRegs:$src2), s11_1ImmPred:$offset, + (S2_storerh_io (i32 IntRegs:$src2), s11_1ImmPred:$offset, (i32 IntRegs:$src1))>; def : Pat<(atomic_store_32 ADDRriS11_2:$src2, (i32 IntRegs:$src1)), - (STriw ADDRriS11_2:$src2, (i32 IntRegs:$src1))>; + (S2_storeri_io AddrFI:$src2, 0, (i32 IntRegs:$src1))>; def : Pat<(atomic_store_32 (add (i32 IntRegs:$src2), s11_2ImmPred:$offset), (i32 IntRegs:$src1)), - (STriw_indexed (i32 IntRegs:$src2), s11_2ImmPred:$offset, + (S2_storeri_io (i32 IntRegs:$src2), s11_2ImmPred:$offset, (i32 IntRegs:$src1))>; def : Pat<(atomic_store_64 ADDRriS11_3:$src2, (i64 DoubleRegs:$src1)), - (STrid ADDRriS11_3:$src2, (i64 DoubleRegs:$src1))>; + (S2_storerd_io AddrFI:$src2, 0, (i64 DoubleRegs:$src1))>; def : Pat<(atomic_store_64 (add (i32 IntRegs:$src2), s11_3ImmPred:$offset), (i64 DoubleRegs:$src1)), - (STrid_indexed (i32 IntRegs:$src2), s11_3ImmPred:$offset, + (S2_storerd_io (i32 IntRegs:$src2), s11_3ImmPred:$offset, (i64 DoubleRegs:$src1))>; // Map from r0 = and(r1, 65535) to r0 = zxth(r1) def : Pat <(and (i32 IntRegs:$src1), 65535), - (ZXTH (i32 IntRegs:$src1))>; + (A2_zxth (i32 IntRegs:$src1))>; // Map from r0 = and(r1, 255) to r0 = zxtb(r1). def : Pat <(and (i32 IntRegs:$src1), 255), - (ZXTB (i32 IntRegs:$src1))>; + (A2_zxtb (i32 IntRegs:$src1))>; // Map Add(p1, true) to p1 = not(p1). // Add(p1, false) should never be produced, // if it does, it got to be mapped to NOOP. def : Pat <(add (i1 PredRegs:$src1), -1), - (NOT_p (i1 PredRegs:$src1))>; - -// Map from p0 = setlt(r0, r1) r2 = mux(p0, r3, r4) => -// p0 = cmp.lt(r0, r1), r0 = mux(p0, r2, r1). -// cmp.lt(r0, r1) -> cmp.gt(r1, r0) -def : Pat <(select (i1 (setlt (i32 IntRegs:$src1), (i32 IntRegs:$src2))), - (i32 IntRegs:$src3), - (i32 IntRegs:$src4)), - (i32 (TFR_condset_rr (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)), - (i32 IntRegs:$src4), (i32 IntRegs:$src3)))>, - Requires<[HasV2TOnly]>; + (C2_not (i1 PredRegs:$src1))>; // Map from p0 = pnot(p0); r0 = mux(p0, #i, #j) => r0 = mux(p0, #j, #i). def : Pat <(select (not (i1 PredRegs:$src1)), s8ImmPred:$src2, s8ImmPred:$src3), @@ -2196,91 +4123,91 @@ def : Pat <(select (not (i1 PredRegs:$src1)), IntRegs:$src2, s12ImmPred:$src3), // Map from p0 = pnot(p0); if (p0) jump => if (!p0) jump. def : Pat <(brcond (not (i1 PredRegs:$src1)), bb:$offset), - (JMP_f (i1 PredRegs:$src1), bb:$offset)>; + (J2_jumpf (i1 PredRegs:$src1), bb:$offset)>; // Map from p2 = pnot(p2); p1 = and(p0, p2) => p1 = and(p0, !p2). def : Pat <(and (i1 PredRegs:$src1), (not (i1 PredRegs:$src2))), - (i1 (AND_pnotp (i1 PredRegs:$src1), (i1 PredRegs:$src2)))>; + (i1 (C2_andn (i1 PredRegs:$src1), (i1 PredRegs:$src2)))>; let AddedComplexity = 100 in def : Pat <(i64 (zextloadi1 (HexagonCONST32 tglobaladdr:$global))), - (i64 (COMBINE_rr (TFRI 0), - (LDriub_indexed (CONST32_set tglobaladdr:$global), 0)))>, + (i64 (A2_combinew (A2_tfrsi 0), + (L2_loadrub_io (CONST32_set tglobaladdr:$global), 0)))>, Requires<[NoV4T]>; // Map from i1 loads to 32 bits. This assumes that the i1* is byte aligned. let AddedComplexity = 10 in def : Pat <(i32 (zextloadi1 ADDRriS11_0:$addr)), - (i32 (AND_rr (i32 (LDrib ADDRriS11_0:$addr)), (TFRI 0x1)))>; + (i32 (A2_and (i32 (L2_loadrb_io AddrFI:$addr, 0)), (A2_tfrsi 0x1)))>; -// Map from Rdd = sign_extend_inreg(Rss, i32) -> Rdd = SXTW(Rss.lo). +// Map from Rdd = sign_extend_inreg(Rss, i32) -> Rdd = A2_sxtw(Rss.lo). def : Pat <(i64 (sext_inreg (i64 DoubleRegs:$src1), i32)), - (i64 (SXTW (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg))))>; + (i64 (A2_sxtw (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg))))>; -// Map from Rdd = sign_extend_inreg(Rss, i16) -> Rdd = SXTW(SXTH(Rss.lo)). +// Map from Rdd = sign_extend_inreg(Rss, i16) -> Rdd = A2_sxtw(SXTH(Rss.lo)). def : Pat <(i64 (sext_inreg (i64 DoubleRegs:$src1), i16)), - (i64 (SXTW (i32 (SXTH (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), + (i64 (A2_sxtw (i32 (A2_sxth (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg))))))>; -// Map from Rdd = sign_extend_inreg(Rss, i8) -> Rdd = SXTW(SXTB(Rss.lo)). +// Map from Rdd = sign_extend_inreg(Rss, i8) -> Rdd = A2_sxtw(SXTB(Rss.lo)). def : Pat <(i64 (sext_inreg (i64 DoubleRegs:$src1), i8)), - (i64 (SXTW (i32 (SXTB (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), + (i64 (A2_sxtw (i32 (A2_sxtb (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg))))))>; // We want to prevent emitting pnot's as much as possible. -// Map brcond with an unsupported setcc to a JMP_f. +// Map brcond with an unsupported setcc to a J2_jumpf. def : Pat <(brcond (i1 (setne (i32 IntRegs:$src1), (i32 IntRegs:$src2))), bb:$offset), - (JMP_f (CMPEQrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)), + (J2_jumpf (C2_cmpeq (i32 IntRegs:$src1), (i32 IntRegs:$src2)), bb:$offset)>; def : Pat <(brcond (i1 (setne (i32 IntRegs:$src1), s10ImmPred:$src2)), bb:$offset), - (JMP_f (CMPEQri (i32 IntRegs:$src1), s10ImmPred:$src2), bb:$offset)>; + (J2_jumpf (C2_cmpeqi (i32 IntRegs:$src1), s10ImmPred:$src2), bb:$offset)>; def : Pat <(brcond (i1 (setne (i1 PredRegs:$src1), (i1 -1))), bb:$offset), - (JMP_f (i1 PredRegs:$src1), bb:$offset)>; + (J2_jumpf (i1 PredRegs:$src1), bb:$offset)>; def : Pat <(brcond (i1 (setne (i1 PredRegs:$src1), (i1 0))), bb:$offset), - (JMP_t (i1 PredRegs:$src1), bb:$offset)>; + (J2_jumpt (i1 PredRegs:$src1), bb:$offset)>; // cmp.lt(Rs, Imm) -> !cmp.ge(Rs, Imm) -> !cmp.gt(Rs, Imm-1) def : Pat <(brcond (i1 (setlt (i32 IntRegs:$src1), s8ImmPred:$src2)), bb:$offset), - (JMP_f (CMPGTri (i32 IntRegs:$src1), + (J2_jumpf (C2_cmpgti (i32 IntRegs:$src1), (DEC_CONST_SIGNED s8ImmPred:$src2)), bb:$offset)>; // cmp.lt(r0, r1) -> cmp.gt(r1, r0) def : Pat <(brcond (i1 (setlt (i32 IntRegs:$src1), (i32 IntRegs:$src2))), bb:$offset), - (JMP_t (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)), bb:$offset)>; + (J2_jumpt (C2_cmpgt (i32 IntRegs:$src2), (i32 IntRegs:$src1)), bb:$offset)>; def : Pat <(brcond (i1 (setuge (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), bb:$offset), - (JMP_f (CMPGTU64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)), + (J2_jumpf (C2_cmpgtup (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)), bb:$offset)>; def : Pat <(brcond (i1 (setule (i32 IntRegs:$src1), (i32 IntRegs:$src2))), bb:$offset), - (JMP_f (CMPGTUrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)), + (J2_jumpf (C2_cmpgtu (i32 IntRegs:$src1), (i32 IntRegs:$src2)), bb:$offset)>; def : Pat <(brcond (i1 (setule (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), bb:$offset), - (JMP_f (CMPGTU64rr (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)), + (J2_jumpf (C2_cmpgtup (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)), bb:$offset)>; // Map from a 64-bit select to an emulated 64-bit mux. // Hexagon does not support 64-bit MUXes; so emulate with combines. def : Pat <(select (i1 PredRegs:$src1), (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src3)), - (i64 (COMBINE_rr (i32 (MUX_rr (i1 PredRegs:$src1), + (i64 (A2_combinew (i32 (C2_mux (i1 PredRegs:$src1), (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_hireg)), (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src3), subreg_hireg)))), - (i32 (MUX_rr (i1 PredRegs:$src1), + (i32 (C2_mux (i1 PredRegs:$src1), (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_loreg)), (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src3), @@ -2290,12 +4217,12 @@ def : Pat <(select (i1 PredRegs:$src1), (i64 DoubleRegs:$src2), // From LegalizeDAG.cpp: (B1 ? B2 : B3) <=> (B1 & B2)|(!B1&B3). def : Pat <(select (i1 PredRegs:$src1), (i1 PredRegs:$src2), (i1 PredRegs:$src3)), - (OR_pp (AND_pp (i1 PredRegs:$src1), (i1 PredRegs:$src2)), - (AND_pp (NOT_p (i1 PredRegs:$src1)), (i1 PredRegs:$src3)))>; + (C2_or (C2_and (i1 PredRegs:$src1), (i1 PredRegs:$src2)), + (C2_and (C2_not (i1 PredRegs:$src1)), (i1 PredRegs:$src3)))>; // Map Pd = load(addr) -> Rs = load(addr); Pd = Rs. def : Pat<(i1 (load ADDRriS11_2:$addr)), - (i1 (TFR_PdRs (i32 (LDrib ADDRriS11_2:$addr))))>; + (i1 (C2_tfrrp (i32 (L2_loadrb_io AddrFI:$addr, 0))))>; // Map for truncating from 64 immediates to 32 bit immediates. def : Pat<(i32 (trunc (i64 DoubleRegs:$src))), @@ -2303,263 +4230,263 @@ def : Pat<(i32 (trunc (i64 DoubleRegs:$src))), // Map for truncating from i64 immediates to i1 bit immediates. def : Pat<(i1 (trunc (i64 DoubleRegs:$src))), - (i1 (TFR_PdRs (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), + (i1 (C2_tfrrp (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), subreg_loreg))))>; // Map memb(Rs) = Rdd -> memb(Rs) = Rt. def : Pat<(truncstorei8 (i64 DoubleRegs:$src), ADDRriS11_0:$addr), - (STrib ADDRriS11_0:$addr, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), + (S2_storerb_io AddrFI:$addr, 0, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), subreg_loreg)))>; // Map memh(Rs) = Rdd -> memh(Rs) = Rt. def : Pat<(truncstorei16 (i64 DoubleRegs:$src), ADDRriS11_0:$addr), - (STrih ADDRriS11_0:$addr, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), + (S2_storerh_io AddrFI:$addr, 0, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), subreg_loreg)))>; // Map memw(Rs) = Rdd -> memw(Rs) = Rt def : Pat<(truncstorei32 (i64 DoubleRegs:$src), ADDRriS11_0:$addr), - (STriw ADDRriS11_0:$addr, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), + (S2_storeri_io AddrFI:$addr, 0, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), subreg_loreg)))>; // Map memw(Rs) = Rdd -> memw(Rs) = Rt. def : Pat<(truncstorei32 (i64 DoubleRegs:$src), ADDRriS11_0:$addr), - (STriw ADDRriS11_0:$addr, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), + (S2_storeri_io AddrFI:$addr, 0, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), subreg_loreg)))>; // Map from i1 = constant<-1>; memw(addr) = i1 -> r0 = 1; memw(addr) = r0. def : Pat<(store (i1 -1), ADDRriS11_2:$addr), - (STrib ADDRriS11_2:$addr, (TFRI 1))>; + (S2_storerb_io AddrFI:$addr, 0, (A2_tfrsi 1))>; // Map from i1 = constant<-1>; store i1 -> r0 = 1; store r0. def : Pat<(store (i1 -1), ADDRriS11_2:$addr), - (STrib ADDRriS11_2:$addr, (TFRI 1))>; + (S2_storerb_io AddrFI:$addr, 0, (A2_tfrsi 1))>; // Map from memb(Rs) = Pd -> Rt = mux(Pd, #0, #1); store Rt. def : Pat<(store (i1 PredRegs:$src1), ADDRriS11_2:$addr), - (STrib ADDRriS11_2:$addr, (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0)) )>; + (S2_storerb_io AddrFI:$addr, 0, (i32 (C2_muxii (i1 PredRegs:$src1), 1, 0)) )>; -// Map Rdd = anyext(Rs) -> Rdd = sxtw(Rs). +// Map Rdd = anyext(Rs) -> Rdd = A2_sxtw(Rs). // Hexagon_TODO: We can probably use combine but that will cost 2 instructions. // Better way to do this? def : Pat<(i64 (anyext (i32 IntRegs:$src1))), - (i64 (SXTW (i32 IntRegs:$src1)))>; + (i64 (A2_sxtw (i32 IntRegs:$src1)))>; // Map cmple -> cmpgt. // rs <= rt -> !(rs > rt). def : Pat<(i1 (setle (i32 IntRegs:$src1), s10ExtPred:$src2)), - (i1 (NOT_p (CMPGTri (i32 IntRegs:$src1), s10ExtPred:$src2)))>; + (i1 (C2_not (C2_cmpgti (i32 IntRegs:$src1), s10ExtPred:$src2)))>; // rs <= rt -> !(rs > rt). def : Pat<(i1 (setle (i32 IntRegs:$src1), (i32 IntRegs:$src2))), - (i1 (NOT_p (CMPGTrr (i32 IntRegs:$src1), (i32 IntRegs:$src2))))>; + (i1 (C2_not (C2_cmpgt (i32 IntRegs:$src1), (i32 IntRegs:$src2))))>; // Rss <= Rtt -> !(Rss > Rtt). def : Pat<(i1 (setle (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), - (i1 (NOT_p (CMPGT64rr (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))))>; + (i1 (C2_not (C2_cmpgtp (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))))>; // Map cmpne -> cmpeq. // Hexagon_TODO: We should improve on this. // rs != rt -> !(rs == rt). def : Pat <(i1 (setne (i32 IntRegs:$src1), s10ExtPred:$src2)), - (i1 (NOT_p(i1 (CMPEQri (i32 IntRegs:$src1), s10ExtPred:$src2))))>; + (i1 (C2_not(i1 (C2_cmpeqi (i32 IntRegs:$src1), s10ExtPred:$src2))))>; // Map cmpne(Rs) -> !cmpeqe(Rs). // rs != rt -> !(rs == rt). def : Pat <(i1 (setne (i32 IntRegs:$src1), (i32 IntRegs:$src2))), - (i1 (NOT_p (i1 (CMPEQrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)))))>; + (i1 (C2_not (i1 (C2_cmpeq (i32 IntRegs:$src1), (i32 IntRegs:$src2)))))>; // Convert setne back to xor for hexagon since we compute w/ pred registers. def : Pat <(i1 (setne (i1 PredRegs:$src1), (i1 PredRegs:$src2))), - (i1 (XOR_pp (i1 PredRegs:$src1), (i1 PredRegs:$src2)))>; + (i1 (C2_xor (i1 PredRegs:$src1), (i1 PredRegs:$src2)))>; // Map cmpne(Rss) -> !cmpew(Rss). // rs != rt -> !(rs == rt). def : Pat <(i1 (setne (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), - (i1 (NOT_p (i1 (CMPEHexagon4rr (i64 DoubleRegs:$src1), + (i1 (C2_not (i1 (C2_cmpeqp (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)))))>; // Map cmpge(Rs, Rt) -> !(cmpgt(Rs, Rt). // rs >= rt -> !(rt > rs). def : Pat <(i1 (setge (i32 IntRegs:$src1), (i32 IntRegs:$src2))), - (i1 (NOT_p (i1 (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)))))>; + (i1 (C2_not (i1 (C2_cmpgt (i32 IntRegs:$src2), (i32 IntRegs:$src1)))))>; // cmpge(Rs, Imm) -> cmpgt(Rs, Imm-1) def : Pat <(i1 (setge (i32 IntRegs:$src1), s8ExtPred:$src2)), - (i1 (CMPGTri (i32 IntRegs:$src1), (DEC_CONST_SIGNED s8ExtPred:$src2)))>; + (i1 (C2_cmpgti (i32 IntRegs:$src1), (DEC_CONST_SIGNED s8ExtPred:$src2)))>; // Map cmpge(Rss, Rtt) -> !cmpgt(Rtt, Rss). // rss >= rtt -> !(rtt > rss). def : Pat <(i1 (setge (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), - (i1 (NOT_p (i1 (CMPGT64rr (i64 DoubleRegs:$src2), + (i1 (C2_not (i1 (C2_cmpgtp (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)))))>; // Map cmplt(Rs, Imm) -> !cmpge(Rs, Imm). // !cmpge(Rs, Imm) -> !cmpgt(Rs, Imm-1). // rs < rt -> !(rs >= rt). def : Pat <(i1 (setlt (i32 IntRegs:$src1), s8ExtPred:$src2)), - (i1 (NOT_p (CMPGTri (i32 IntRegs:$src1), (DEC_CONST_SIGNED s8ExtPred:$src2))))>; + (i1 (C2_not (C2_cmpgti (i32 IntRegs:$src1), (DEC_CONST_SIGNED s8ExtPred:$src2))))>; // Map cmplt(Rs, Rt) -> cmpgt(Rt, Rs). // rs < rt -> rt > rs. // We can let assembler map it, or we can do in the compiler itself. def : Pat <(i1 (setlt (i32 IntRegs:$src1), (i32 IntRegs:$src2))), - (i1 (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)))>; + (i1 (C2_cmpgt (i32 IntRegs:$src2), (i32 IntRegs:$src1)))>; // Map cmplt(Rss, Rtt) -> cmpgt(Rtt, Rss). // rss < rtt -> (rtt > rss). def : Pat <(i1 (setlt (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), - (i1 (CMPGT64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)))>; + (i1 (C2_cmpgtp (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)))>; // Map from cmpltu(Rs, Rd) -> cmpgtu(Rd, Rs) // rs < rt -> rt > rs. // We can let assembler map it, or we can do in the compiler itself. def : Pat <(i1 (setult (i32 IntRegs:$src1), (i32 IntRegs:$src2))), - (i1 (CMPGTUrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)))>; + (i1 (C2_cmpgtu (i32 IntRegs:$src2), (i32 IntRegs:$src1)))>; // Map from cmpltu(Rss, Rdd) -> cmpgtu(Rdd, Rss). // rs < rt -> rt > rs. def : Pat <(i1 (setult (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), - (i1 (CMPGTU64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)))>; + (i1 (C2_cmpgtup (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)))>; // Generate cmpgeu(Rs, #0) -> cmpeq(Rs, Rs) def : Pat <(i1 (setuge (i32 IntRegs:$src1), 0)), - (i1 (CMPEQrr (i32 IntRegs:$src1), (i32 IntRegs:$src1)))>; + (i1 (C2_cmpeq (i32 IntRegs:$src1), (i32 IntRegs:$src1)))>; // Generate cmpgeu(Rs, #u8) -> cmpgtu(Rs, #u8 -1) def : Pat <(i1 (setuge (i32 IntRegs:$src1), u8ExtPred:$src2)), - (i1 (CMPGTUri (i32 IntRegs:$src1), (DEC_CONST_UNSIGNED u8ExtPred:$src2)))>; + (i1 (C2_cmpgtui (i32 IntRegs:$src1), (DEC_CONST_UNSIGNED u8ExtPred:$src2)))>; // Generate cmpgtu(Rs, #u9) def : Pat <(i1 (setugt (i32 IntRegs:$src1), u9ExtPred:$src2)), - (i1 (CMPGTUri (i32 IntRegs:$src1), u9ExtPred:$src2))>; + (i1 (C2_cmpgtui (i32 IntRegs:$src1), u9ExtPred:$src2))>; // Map from Rs >= Rt -> !(Rt > Rs). // rs >= rt -> !(rt > rs). def : Pat <(i1 (setuge (i32 IntRegs:$src1), (i32 IntRegs:$src2))), - (i1 (NOT_p (CMPGTUrr (i32 IntRegs:$src2), (i32 IntRegs:$src1))))>; + (i1 (C2_not (C2_cmpgtu (i32 IntRegs:$src2), (i32 IntRegs:$src1))))>; // Map from Rs >= Rt -> !(Rt > Rs). // rs >= rt -> !(rt > rs). def : Pat <(i1 (setuge (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), - (i1 (NOT_p (CMPGTU64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1))))>; + (i1 (C2_not (C2_cmpgtup (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1))))>; // Map from cmpleu(Rs, Rt) -> !cmpgtu(Rs, Rt). // Map from (Rs <= Rt) -> !(Rs > Rt). def : Pat <(i1 (setule (i32 IntRegs:$src1), (i32 IntRegs:$src2))), - (i1 (NOT_p (CMPGTUrr (i32 IntRegs:$src1), (i32 IntRegs:$src2))))>; + (i1 (C2_not (C2_cmpgtu (i32 IntRegs:$src1), (i32 IntRegs:$src2))))>; // Map from cmpleu(Rss, Rtt) -> !cmpgtu(Rss, Rtt-1). // Map from (Rs <= Rt) -> !(Rs > Rt). def : Pat <(i1 (setule (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))), - (i1 (NOT_p (CMPGTU64rr (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))))>; + (i1 (C2_not (C2_cmpgtup (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))))>; // Sign extends. // i1 -> i32 def : Pat <(i32 (sext (i1 PredRegs:$src1))), - (i32 (MUX_ii (i1 PredRegs:$src1), -1, 0))>; + (i32 (C2_muxii (i1 PredRegs:$src1), -1, 0))>; // i1 -> i64 def : Pat <(i64 (sext (i1 PredRegs:$src1))), - (i64 (COMBINE_rr (TFRI -1), (MUX_ii (i1 PredRegs:$src1), -1, 0)))>; + (i64 (A2_combinew (A2_tfrsi -1), (C2_muxii (i1 PredRegs:$src1), -1, 0)))>; // Convert sign-extended load back to load and sign extend. // i8 -> i64 def: Pat <(i64 (sextloadi8 ADDRriS11_0:$src1)), - (i64 (SXTW (LDrib ADDRriS11_0:$src1)))>; + (i64 (A2_sxtw (L2_loadrb_io AddrFI:$src1, 0)))>; // Convert any-extended load back to load and sign extend. // i8 -> i64 def: Pat <(i64 (extloadi8 ADDRriS11_0:$src1)), - (i64 (SXTW (LDrib ADDRriS11_0:$src1)))>; + (i64 (A2_sxtw (L2_loadrb_io AddrFI:$src1, 0)))>; // Convert sign-extended load back to load and sign extend. // i16 -> i64 def: Pat <(i64 (sextloadi16 ADDRriS11_1:$src1)), - (i64 (SXTW (LDrih ADDRriS11_1:$src1)))>; + (i64 (A2_sxtw (L2_loadrh_io AddrFI:$src1, 0)))>; // Convert sign-extended load back to load and sign extend. // i32 -> i64 def: Pat <(i64 (sextloadi32 ADDRriS11_2:$src1)), - (i64 (SXTW (LDriw ADDRriS11_2:$src1)))>; + (i64 (A2_sxtw (L2_loadri_io AddrFI:$src1, 0)))>; // Zero extends. // i1 -> i32 def : Pat <(i32 (zext (i1 PredRegs:$src1))), - (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0))>; + (i32 (C2_muxii (i1 PredRegs:$src1), 1, 0))>; // i1 -> i64 def : Pat <(i64 (zext (i1 PredRegs:$src1))), - (i64 (COMBINE_rr (TFRI 0), (MUX_ii (i1 PredRegs:$src1), 1, 0)))>, + (i64 (A2_combinew (A2_tfrsi 0), (C2_muxii (i1 PredRegs:$src1), 1, 0)))>, Requires<[NoV4T]>; // i32 -> i64 def : Pat <(i64 (zext (i32 IntRegs:$src1))), - (i64 (COMBINE_rr (TFRI 0), (i32 IntRegs:$src1)))>, + (i64 (A2_combinew (A2_tfrsi 0), (i32 IntRegs:$src1)))>, Requires<[NoV4T]>; // i8 -> i64 def: Pat <(i64 (zextloadi8 ADDRriS11_0:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDriub ADDRriS11_0:$src1)))>, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadrub_io AddrFI:$src1, 0)))>, Requires<[NoV4T]>; let AddedComplexity = 20 in def: Pat <(i64 (zextloadi8 (add (i32 IntRegs:$src1), s11_0ExtPred:$offset))), - (i64 (COMBINE_rr (TFRI 0), (LDriub_indexed IntRegs:$src1, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadrub_io IntRegs:$src1, s11_0ExtPred:$offset)))>, Requires<[NoV4T]>; // i1 -> i64 def: Pat <(i64 (zextloadi1 ADDRriS11_0:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDriub ADDRriS11_0:$src1)))>, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadrub_io AddrFI:$src1, 0)))>, Requires<[NoV4T]>; let AddedComplexity = 20 in def: Pat <(i64 (zextloadi1 (add (i32 IntRegs:$src1), s11_0ExtPred:$offset))), - (i64 (COMBINE_rr (TFRI 0), (LDriub_indexed IntRegs:$src1, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadrub_io IntRegs:$src1, s11_0ExtPred:$offset)))>, Requires<[NoV4T]>; // i16 -> i64 def: Pat <(i64 (zextloadi16 ADDRriS11_1:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDriuh ADDRriS11_1:$src1)))>, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadruh_io AddrFI:$src1, 0)))>, Requires<[NoV4T]>; let AddedComplexity = 20 in def: Pat <(i64 (zextloadi16 (add (i32 IntRegs:$src1), s11_1ExtPred:$offset))), - (i64 (COMBINE_rr (TFRI 0), (LDriuh_indexed IntRegs:$src1, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadruh_io IntRegs:$src1, s11_1ExtPred:$offset)))>, Requires<[NoV4T]>; // i32 -> i64 def: Pat <(i64 (zextloadi32 ADDRriS11_2:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadri_io AddrFI:$src1, 0)))>, Requires<[NoV4T]>; let AddedComplexity = 100 in def: Pat <(i64 (zextloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))), - (i64 (COMBINE_rr (TFRI 0), (LDriw_indexed IntRegs:$src1, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadri_io IntRegs:$src1, s11_2ExtPred:$offset)))>, Requires<[NoV4T]>; let AddedComplexity = 10 in def: Pat <(i32 (zextloadi1 ADDRriS11_0:$src1)), - (i32 (LDriw ADDRriS11_0:$src1))>; + (i32 (L2_loadri_io AddrFI:$src1, 0))>; // Map from Rs = Pd to Pd = mux(Pd, #1, #0) def : Pat <(i32 (zext (i1 PredRegs:$src1))), - (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0))>; + (i32 (C2_muxii (i1 PredRegs:$src1), 1, 0))>; // Map from Rs = Pd to Pd = mux(Pd, #1, #0) def : Pat <(i32 (anyext (i1 PredRegs:$src1))), - (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0))>; + (i32 (C2_muxii (i1 PredRegs:$src1), 1, 0))>; -// Map from Rss = Pd to Rdd = sxtw (mux(Pd, #1, #0)) +// Map from Rss = Pd to Rdd = A2_sxtw (mux(Pd, #1, #0)) def : Pat <(i64 (anyext (i1 PredRegs:$src1))), - (i64 (SXTW (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0))))>; + (i64 (A2_sxtw (i32 (C2_muxii (i1 PredRegs:$src1), 1, 0))))>; let AddedComplexity = 100 in @@ -2567,20 +4494,20 @@ def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), (i32 32))), (i64 (zextloadi32 (i32 (add IntRegs:$src2, s11_2ExtPred:$offset2)))))), - (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), - (LDriw_indexed IntRegs:$src2, + (i64 (A2_combinew (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + (L2_loadri_io IntRegs:$src2, s11_2ExtPred:$offset2)))>; def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), (i32 32))), (i64 (zextloadi32 ADDRriS11_2:$srcLow)))), - (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), - (LDriw ADDRriS11_2:$srcLow)))>; + (i64 (A2_combinew (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + (L2_loadri_io AddrFI:$srcLow, 0)))>; def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), (i32 32))), (i64 (zext (i32 IntRegs:$srcLow))))), - (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + (i64 (A2_combinew (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), IntRegs:$srcLow))>; let AddedComplexity = 100 in @@ -2588,26 +4515,26 @@ def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), (i32 32))), (i64 (zextloadi32 (i32 (add IntRegs:$src2, s11_2ExtPred:$offset2)))))), - (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), - (LDriw_indexed IntRegs:$src2, + (i64 (A2_combinew (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + (L2_loadri_io IntRegs:$src2, s11_2ExtPred:$offset2)))>; def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), (i32 32))), (i64 (zextloadi32 ADDRriS11_2:$srcLow)))), - (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), - (LDriw ADDRriS11_2:$srcLow)))>; + (i64 (A2_combinew (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + (L2_loadri_io AddrFI:$srcLow, 0)))>; def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh), (i32 32))), (i64 (zext (i32 IntRegs:$srcLow))))), - (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), + (i64 (A2_combinew (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg), IntRegs:$srcLow))>; // Any extended 64-bit load. // anyext i32 -> i64 def: Pat <(i64 (extloadi32 ADDRriS11_2:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadri_io AddrFI:$src1, 0)))>, Requires<[NoV4T]>; // When there is an offset we should prefer the pattern below over the pattern above. @@ -2622,50 +4549,51 @@ def: Pat <(i64 (extloadi32 ADDRriS11_2:$src1)), // ******************************************** let AddedComplexity = 100 in def: Pat <(i64 (extloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))), - (i64 (COMBINE_rr (TFRI 0), (LDriw_indexed IntRegs:$src1, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadri_io IntRegs:$src1, s11_2ExtPred:$offset)))>, Requires<[NoV4T]>; // anyext i16 -> i64. def: Pat <(i64 (extloadi16 ADDRriS11_2:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDrih ADDRriS11_2:$src1)))>, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadrh_io AddrFI:$src1, 0)))>, Requires<[NoV4T]>; let AddedComplexity = 20 in def: Pat <(i64 (extloadi16 (add (i32 IntRegs:$src1), s11_1ExtPred:$offset))), - (i64 (COMBINE_rr (TFRI 0), (LDrih_indexed IntRegs:$src1, + (i64 (A2_combinew (A2_tfrsi 0), (L2_loadrh_io IntRegs:$src1, s11_1ExtPred:$offset)))>, Requires<[NoV4T]>; // Map from Rdd = zxtw(Rs) -> Rdd = combine(0, Rs). def : Pat<(i64 (zext (i32 IntRegs:$src1))), - (i64 (COMBINE_rr (TFRI 0), (i32 IntRegs:$src1)))>, + (i64 (A2_combinew (A2_tfrsi 0), (i32 IntRegs:$src1)))>, Requires<[NoV4T]>; // Multiply 64-bit unsigned and use upper result. def : Pat <(mulhu (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)), (i64 - (MPYU64_acc + (M2_dpmpyuu_acc_s0 (i64 - (COMBINE_rr - (TFRI 0), + (A2_combinew + (A2_tfrsi 0), (i32 (EXTRACT_SUBREG (i64 - (LSRd_ri + (S2_lsr_i_p (i64 - (MPYU64_acc + (M2_dpmpyuu_acc_s0 (i64 - (MPYU64_acc + (M2_dpmpyuu_acc_s0 (i64 - (COMBINE_rr (TFRI 0), + (A2_combinew (A2_tfrsi 0), (i32 (EXTRACT_SUBREG (i64 - (LSRd_ri + (S2_lsr_i_p (i64 - (MPYU64 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), + (M2_dpmpyuu_s0 + (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg)), (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_loreg)))), 32)), @@ -2681,25 +4609,26 @@ def : Pat <(mulhu (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)), // Multiply 64-bit signed and use upper result. def : Pat <(mulhs (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)), (i64 - (MPY64_acc + (M2_dpmpyss_acc_s0 (i64 - (COMBINE_rr (TFRI 0), + (A2_combinew (A2_tfrsi 0), (i32 (EXTRACT_SUBREG (i64 - (LSRd_ri + (S2_lsr_i_p (i64 - (MPY64_acc + (M2_dpmpyss_acc_s0 (i64 - (MPY64_acc + (M2_dpmpyss_acc_s0 (i64 - (COMBINE_rr (TFRI 0), + (A2_combinew (A2_tfrsi 0), (i32 (EXTRACT_SUBREG (i64 - (LSRd_ri + (S2_lsr_i_p (i64 - (MPYU64 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), + (M2_dpmpyuu_s0 + (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg)), (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_loreg)))), 32)), @@ -2744,83 +4673,470 @@ def : Pat<(HexagonWrapperJT tjumptable:$dst), (i32 (CONST32_set_jt tjumptable:$dst))>; // XTYPE/SHIFT - -// Multi-class for logical operators : +// +//===----------------------------------------------------------------------===// +// Template Class // Shift by immediate/register and accumulate/logical -multiclass xtype_imm<string OpcStr, SDNode OpNode1, SDNode OpNode2> { - def _ri : SInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u5Imm:$src3), - !strconcat("$dst ", !strconcat(OpcStr, "($src2, #$src3)")), - [(set (i32 IntRegs:$dst), - (OpNode2 (i32 IntRegs:$src1), - (OpNode1 (i32 IntRegs:$src2), - u5ImmPred:$src3)))], - "$src1 = $dst">; - - def d_ri : SInst_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2, u6Imm:$src3), - !strconcat("$dst ", !strconcat(OpcStr, "($src2, #$src3)")), - [(set (i64 DoubleRegs:$dst), (OpNode2 (i64 DoubleRegs:$src1), - (OpNode1 (i64 DoubleRegs:$src2), u6ImmPred:$src3)))], - "$src1 = $dst">; -} - -// Multi-class for logical operators : -// Shift by register and accumulate/logical (32/64 bits) -multiclass xtype_reg<string OpcStr, SDNode OpNode1, SDNode OpNode2> { - def _rr : SInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3), - !strconcat("$dst ", !strconcat(OpcStr, "($src2, $src3)")), - [(set (i32 IntRegs:$dst), - (OpNode2 (i32 IntRegs:$src1), - (OpNode1 (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">; +//===----------------------------------------------------------------------===// + +// Rx[+-&|]=asr(Rs,#u5) +// Rx[+-&|^]=lsr(Rs,#u5) +// Rx[+-&|^]=asl(Rs,#u5) + +let hasNewValue = 1, opNewValue = 0 in +class T_shift_imm_acc_r <string opc1, string opc2, SDNode OpNode1, + SDNode OpNode2, bits<3> majOp, bits<2> minOp> + : SInst_acc<(outs IntRegs:$Rx), + (ins IntRegs:$src1, IntRegs:$Rs, u5Imm:$u5), + "$Rx "#opc2#opc1#"($Rs, #$u5)", + [(set (i32 IntRegs:$Rx), + (OpNode2 (i32 IntRegs:$src1), + (OpNode1 (i32 IntRegs:$Rs), u5ImmPred:$u5)))], + "$src1 = $Rx", S_2op_tc_2_SLOT23> { + bits<5> Rx; + bits<5> Rs; + bits<5> u5; + + let IClass = 0b1000; + + let Inst{27-24} = 0b1110; + let Inst{23-22} = majOp{2-1}; + let Inst{13} = 0b0; + let Inst{7} = majOp{0}; + let Inst{6-5} = minOp; + let Inst{4-0} = Rx; + let Inst{20-16} = Rs; + let Inst{12-8} = u5; + } + +// Rx[+-&|]=asr(Rs,Rt) +// Rx[+-&|^]=lsr(Rs,Rt) +// Rx[+-&|^]=asl(Rs,Rt) + +let hasNewValue = 1, opNewValue = 0 in +class T_shift_reg_acc_r <string opc1, string opc2, SDNode OpNode1, + SDNode OpNode2, bits<2> majOp, bits<2> minOp> + : SInst_acc<(outs IntRegs:$Rx), + (ins IntRegs:$src1, IntRegs:$Rs, IntRegs:$Rt), + "$Rx "#opc2#opc1#"($Rs, $Rt)", + [(set (i32 IntRegs:$Rx), + (OpNode2 (i32 IntRegs:$src1), + (OpNode1 (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))], + "$src1 = $Rx", S_3op_tc_2_SLOT23 > { + bits<5> Rx; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1100; + + let Inst{27-24} = 0b1100; + let Inst{23-22} = majOp; + let Inst{7-6} = minOp; + let Inst{4-0} = Rx; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + } - def d_rr : SInst_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3), - !strconcat("$dst ", !strconcat(OpcStr, "($src2, $src3)")), - [(set (i64 DoubleRegs:$dst), - (OpNode2 (i64 DoubleRegs:$src1), - (OpNode1 (i64 DoubleRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">; +// Rxx[+-&|]=asr(Rss,#u6) +// Rxx[+-&|^]=lsr(Rss,#u6) +// Rxx[+-&|^]=asl(Rss,#u6) + +class T_shift_imm_acc_p <string opc1, string opc2, SDNode OpNode1, + SDNode OpNode2, bits<3> majOp, bits<2> minOp> + : SInst_acc<(outs DoubleRegs:$Rxx), + (ins DoubleRegs:$src1, DoubleRegs:$Rss, u6Imm:$u6), + "$Rxx "#opc2#opc1#"($Rss, #$u6)", + [(set (i64 DoubleRegs:$Rxx), + (OpNode2 (i64 DoubleRegs:$src1), + (OpNode1 (i64 DoubleRegs:$Rss), u6ImmPred:$u6)))], + "$src1 = $Rxx", S_2op_tc_2_SLOT23> { + bits<5> Rxx; + bits<5> Rss; + bits<6> u6; + + let IClass = 0b1000; + + let Inst{27-24} = 0b0010; + let Inst{23-22} = majOp{2-1}; + let Inst{7} = majOp{0}; + let Inst{6-5} = minOp; + let Inst{4-0} = Rxx; + let Inst{20-16} = Rss; + let Inst{13-8} = u6; + } + + +// Rxx[+-&|]=asr(Rss,Rt) +// Rxx[+-&|^]=lsr(Rss,Rt) +// Rxx[+-&|^]=asl(Rss,Rt) +// Rxx[+-&|^]=lsl(Rss,Rt) + +class T_shift_reg_acc_p <string opc1, string opc2, SDNode OpNode1, + SDNode OpNode2, bits<3> majOp, bits<2> minOp> + : SInst_acc<(outs DoubleRegs:$Rxx), + (ins DoubleRegs:$src1, DoubleRegs:$Rss, IntRegs:$Rt), + "$Rxx "#opc2#opc1#"($Rss, $Rt)", + [(set (i64 DoubleRegs:$Rxx), + (OpNode2 (i64 DoubleRegs:$src1), + (OpNode1 (i64 DoubleRegs:$Rss), (i32 IntRegs:$Rt))))], + "$src1 = $Rxx", S_3op_tc_2_SLOT23> { + bits<5> Rxx; + bits<5> Rss; + bits<5> Rt; + + let IClass = 0b1100; + + let Inst{27-24} = 0b1011; + let Inst{23-21} = majOp; + let Inst{20-16} = Rss; + let Inst{12-8} = Rt; + let Inst{7-6} = minOp; + let Inst{4-0} = Rxx; + } + +//===----------------------------------------------------------------------===// +// Multi-class for the shift instructions with logical/arithmetic operators. +//===----------------------------------------------------------------------===// +multiclass xtype_imm_base<string OpcStr1, string OpcStr2, SDNode OpNode1, + SDNode OpNode2, bits<3> majOp, bits<2> minOp > { + def _i_r#NAME : T_shift_imm_acc_r< OpcStr1, OpcStr2, OpNode1, + OpNode2, majOp, minOp >; + def _i_p#NAME : T_shift_imm_acc_p< OpcStr1, OpcStr2, OpNode1, + OpNode2, majOp, minOp >; } -multiclass basic_xtype_imm<string OpcStr, SDNode OpNode> { -let AddedComplexity = 100 in - defm _ADD : xtype_imm< !strconcat("+= ", OpcStr), OpNode, add>; - defm _SUB : xtype_imm< !strconcat("-= ", OpcStr), OpNode, sub>; - defm _AND : xtype_imm< !strconcat("&= ", OpcStr), OpNode, and>; - defm _OR : xtype_imm< !strconcat("|= ", OpcStr), OpNode, or>; +multiclass xtype_imm_acc<string opc1, SDNode OpNode, bits<2>minOp> { + let AddedComplexity = 100 in + defm _acc : xtype_imm_base< opc1, "+= ", OpNode, add, 0b001, minOp>; + + defm _nac : xtype_imm_base< opc1, "-= ", OpNode, sub, 0b000, minOp>; + defm _and : xtype_imm_base< opc1, "&= ", OpNode, and, 0b010, minOp>; + defm _or : xtype_imm_base< opc1, "|= ", OpNode, or, 0b011, minOp>; } -multiclass basic_xtype_reg<string OpcStr, SDNode OpNode> { +multiclass xtype_xor_imm_acc<string opc1, SDNode OpNode, bits<2>minOp> { let AddedComplexity = 100 in - defm _ADD : xtype_reg< !strconcat("+= ", OpcStr), OpNode, add>; - defm _SUB : xtype_reg< !strconcat("-= ", OpcStr), OpNode, sub>; - defm _AND : xtype_reg< !strconcat("&= ", OpcStr), OpNode, and>; - defm _OR : xtype_reg< !strconcat("|= ", OpcStr), OpNode, or>; + defm _xacc : xtype_imm_base< opc1, "^= ", OpNode, xor, 0b100, minOp>; } -multiclass xtype_xor_imm<string OpcStr, SDNode OpNode> { -let AddedComplexity = 100 in - defm _XOR : xtype_imm< !strconcat("^= ", OpcStr), OpNode, xor>; +let isCodeGenOnly = 0 in { +defm S2_asr : xtype_imm_acc<"asr", sra, 0b00>; + +defm S2_lsr : xtype_imm_acc<"lsr", srl, 0b01>, + xtype_xor_imm_acc<"lsr", srl, 0b01>; + +defm S2_asl : xtype_imm_acc<"asl", shl, 0b10>, + xtype_xor_imm_acc<"asl", shl, 0b10>; } -defm ASL : basic_xtype_imm<"asl", shl>, basic_xtype_reg<"asl", shl>, - xtype_xor_imm<"asl", shl>; +multiclass xtype_reg_acc_r<string opc1, SDNode OpNode, bits<2>minOp> { + let AddedComplexity = 100 in + def _acc : T_shift_reg_acc_r <opc1, "+= ", OpNode, add, 0b11, minOp>; -defm LSR : basic_xtype_imm<"lsr", srl>, basic_xtype_reg<"lsr", srl>, - xtype_xor_imm<"lsr", srl>; + def _nac : T_shift_reg_acc_r <opc1, "-= ", OpNode, sub, 0b10, minOp>; + def _and : T_shift_reg_acc_r <opc1, "&= ", OpNode, and, 0b01, minOp>; + def _or : T_shift_reg_acc_r <opc1, "|= ", OpNode, or, 0b00, minOp>; +} -defm ASR : basic_xtype_imm<"asr", sra>, basic_xtype_reg<"asr", sra>; -defm LSL : basic_xtype_reg<"lsl", shl>; +multiclass xtype_reg_acc_p<string opc1, SDNode OpNode, bits<2>minOp> { + let AddedComplexity = 100 in + def _acc : T_shift_reg_acc_p <opc1, "+= ", OpNode, add, 0b110, minOp>; + + def _nac : T_shift_reg_acc_p <opc1, "-= ", OpNode, sub, 0b100, minOp>; + def _and : T_shift_reg_acc_p <opc1, "&= ", OpNode, and, 0b010, minOp>; + def _or : T_shift_reg_acc_p <opc1, "|= ", OpNode, or, 0b000, minOp>; + def _xor : T_shift_reg_acc_p <opc1, "^= ", OpNode, xor, 0b011, minOp>; +} + +multiclass xtype_reg_acc<string OpcStr, SDNode OpNode, bits<2> minOp > { + defm _r_r : xtype_reg_acc_r <OpcStr, OpNode, minOp>; + defm _r_p : xtype_reg_acc_p <OpcStr, OpNode, minOp>; +} + +let isCodeGenOnly = 0 in { +defm S2_asl : xtype_reg_acc<"asl", shl, 0b10>; +defm S2_asr : xtype_reg_acc<"asr", sra, 0b00>; +defm S2_lsr : xtype_reg_acc<"lsr", srl, 0b01>; +defm S2_lsl : xtype_reg_acc<"lsl", shl, 0b11>; +} + +//===----------------------------------------------------------------------===// +let hasSideEffects = 0 in +class T_S3op_1 <string mnemonic, RegisterClass RC, bits<2> MajOp, bits<3> MinOp, + bit SwapOps, bit isSat = 0, bit isRnd = 0, bit hasShift = 0> + : SInst <(outs RC:$dst), + (ins DoubleRegs:$src1, DoubleRegs:$src2), + "$dst = "#mnemonic#"($src1, $src2)"#!if(isRnd, ":rnd", "") + #!if(hasShift,":>>1","") + #!if(isSat, ":sat", ""), + [], "", S_3op_tc_2_SLOT23 > { + bits<5> dst; + bits<5> src1; + bits<5> src2; + + let IClass = 0b1100; + + let Inst{27-24} = 0b0001; + let Inst{23-22} = MajOp; + let Inst{20-16} = !if (SwapOps, src2, src1); + let Inst{12-8} = !if (SwapOps, src1, src2); + let Inst{7-5} = MinOp; + let Inst{4-0} = dst; + } + +class T_S3op_64 <string mnemonic, bits<2> MajOp, bits<3> MinOp, bit SwapOps, + bit isSat = 0, bit isRnd = 0, bit hasShift = 0 > + : T_S3op_1 <mnemonic, DoubleRegs, MajOp, MinOp, SwapOps, + isSat, isRnd, hasShift>; + +let isCodeGenOnly = 0 in +def S2_lfsp : T_S3op_64 < "lfs", 0b10, 0b110, 0>; + +//===----------------------------------------------------------------------===// +// Template class used by vector shift, vector rotate, vector neg, +// 32-bit shift, 64-bit shifts, etc. +//===----------------------------------------------------------------------===// + +let hasSideEffects = 0 in +class T_S3op_3 <string mnemonic, RegisterClass RC, bits<2> MajOp, + bits<2> MinOp, bit isSat = 0, list<dag> pattern = [] > + : SInst <(outs RC:$dst), + (ins RC:$src1, IntRegs:$src2), + "$dst = "#mnemonic#"($src1, $src2)"#!if(isSat, ":sat", ""), + pattern, "", S_3op_tc_1_SLOT23> { + bits<5> dst; + bits<5> src1; + bits<5> src2; + + let IClass = 0b1100; + + let Inst{27-24} = !if(!eq(!cast<string>(RC), "IntRegs"), 0b0110, 0b0011); + let Inst{23-22} = MajOp; + let Inst{20-16} = src1; + let Inst{12-8} = src2; + let Inst{7-6} = MinOp; + let Inst{4-0} = dst; + } + +let hasNewValue = 1 in +class T_S3op_shift32 <string mnemonic, SDNode OpNode, bits<2> MinOp> + : T_S3op_3 <mnemonic, IntRegs, 0b01, MinOp, 0, + [(set (i32 IntRegs:$dst), (OpNode (i32 IntRegs:$src1), + (i32 IntRegs:$src2)))]>; + +let hasNewValue = 1, Itinerary = S_3op_tc_2_SLOT23 in +class T_S3op_shift32_Sat <string mnemonic, bits<2> MinOp> + : T_S3op_3 <mnemonic, IntRegs, 0b00, MinOp, 1, []>; + + +class T_S3op_shift64 <string mnemonic, SDNode OpNode, bits<2> MinOp> + : T_S3op_3 <mnemonic, DoubleRegs, 0b10, MinOp, 0, + [(set (i64 DoubleRegs:$dst), (OpNode (i64 DoubleRegs:$src1), + (i32 IntRegs:$src2)))]>; + + +class T_S3op_shiftVect <string mnemonic, bits<2> MajOp, bits<2> MinOp> + : T_S3op_3 <mnemonic, DoubleRegs, MajOp, MinOp, 0, []>; + + +// Shift by register +// Rdd=[asr|lsr|asl|lsl](Rss,Rt) + +let isCodeGenOnly = 0 in { +def S2_asr_r_p : T_S3op_shift64 < "asr", sra, 0b00>; +def S2_lsr_r_p : T_S3op_shift64 < "lsr", srl, 0b01>; +def S2_asl_r_p : T_S3op_shift64 < "asl", shl, 0b10>; +def S2_lsl_r_p : T_S3op_shift64 < "lsl", shl, 0b11>; +} + +// Rd=[asr|lsr|asl|lsl](Rs,Rt) + +let isCodeGenOnly = 0 in { +def S2_asr_r_r : T_S3op_shift32<"asr", sra, 0b00>; +def S2_lsr_r_r : T_S3op_shift32<"lsr", srl, 0b01>; +def S2_asl_r_r : T_S3op_shift32<"asl", shl, 0b10>; +def S2_lsl_r_r : T_S3op_shift32<"lsl", shl, 0b11>; +} + +// Shift by register with saturation +// Rd=asr(Rs,Rt):sat +// Rd=asl(Rs,Rt):sat + +let Defs = [USR_OVF], isCodeGenOnly = 0 in { + def S2_asr_r_r_sat : T_S3op_shift32_Sat<"asr", 0b00>; + def S2_asl_r_r_sat : T_S3op_shift32_Sat<"asl", 0b10>; +} + +//===----------------------------------------------------------------------===// +// Template class for 'insert bitfield' instructions +//===----------------------------------------------------------------------===// +let hasSideEffects = 0 in +class T_S3op_insert <string mnemonic, RegisterClass RC> + : SInst <(outs RC:$dst), + (ins RC:$src1, RC:$src2, DoubleRegs:$src3), + "$dst = "#mnemonic#"($src2, $src3)" , + [], "$src1 = $dst", S_3op_tc_1_SLOT23 > { + bits<5> dst; + bits<5> src2; + bits<5> src3; + + let IClass = 0b1100; + + let Inst{27-26} = 0b10; + let Inst{25-24} = !if(!eq(!cast<string>(RC), "IntRegs"), 0b00, 0b10); + let Inst{23} = 0b0; + let Inst{20-16} = src2; + let Inst{12-8} = src3; + let Inst{4-0} = dst; + } + +let hasSideEffects = 0 in +class T_S2op_insert <bits<4> RegTyBits, RegisterClass RC, Operand ImmOp> + : SInst <(outs RC:$dst), (ins RC:$dst2, RC:$src1, ImmOp:$src2, ImmOp:$src3), + "$dst = insert($src1, #$src2, #$src3)", + [], "$dst2 = $dst", S_2op_tc_2_SLOT23> { + bits<5> dst; + bits<5> src1; + bits<6> src2; + bits<6> src3; + bit bit23; + bit bit13; + string ImmOpStr = !cast<string>(ImmOp); + + let bit23 = !if (!eq(ImmOpStr, "u6Imm"), src3{5}, 0); + let bit13 = !if (!eq(ImmOpStr, "u6Imm"), src2{5}, 0); + + let IClass = 0b1000; + + let Inst{27-24} = RegTyBits; + let Inst{23} = bit23; + let Inst{22-21} = src3{4-3}; + let Inst{20-16} = src1; + let Inst{13} = bit13; + let Inst{12-8} = src2{4-0}; + let Inst{7-5} = src3{2-0}; + let Inst{4-0} = dst; + } + +// Rx=insert(Rs,Rtt) +// Rx=insert(Rs,#u5,#U5) +let hasNewValue = 1, isCodeGenOnly = 0 in { + def S2_insert_rp : T_S3op_insert <"insert", IntRegs>; + def S2_insert : T_S2op_insert <0b1111, IntRegs, u5Imm>; +} + +// Rxx=insert(Rss,Rtt) +// Rxx=insert(Rss,#u6,#U6) +let isCodeGenOnly = 0 in { +def S2_insertp_rp : T_S3op_insert<"insert", DoubleRegs>; +def S2_insertp : T_S2op_insert <0b0011, DoubleRegs, u6Imm>; +} + +//===----------------------------------------------------------------------===// +// Template class for 'extract bitfield' instructions +//===----------------------------------------------------------------------===// +let hasNewValue = 1, hasSideEffects = 0 in +class T_S3op_extract <string mnemonic, bits<2> MinOp> + : SInst <(outs IntRegs:$Rd), (ins IntRegs:$Rs, DoubleRegs:$Rtt), + "$Rd = "#mnemonic#"($Rs, $Rtt)", + [], "", S_3op_tc_2_SLOT23 > { + bits<5> Rd; + bits<5> Rs; + bits<5> Rtt; + + let IClass = 0b1100; + + let Inst{27-22} = 0b100100; + let Inst{20-16} = Rs; + let Inst{12-8} = Rtt; + let Inst{7-6} = MinOp; + let Inst{4-0} = Rd; + } + +let hasSideEffects = 0 in +class T_S2op_extract <string mnemonic, bits<4> RegTyBits, + RegisterClass RC, Operand ImmOp> + : SInst <(outs RC:$dst), (ins RC:$src1, ImmOp:$src2, ImmOp:$src3), + "$dst = "#mnemonic#"($src1, #$src2, #$src3)", + [], "", S_2op_tc_2_SLOT23> { + bits<5> dst; + bits<5> src1; + bits<6> src2; + bits<6> src3; + bit bit23; + bit bit13; + string ImmOpStr = !cast<string>(ImmOp); + + let bit23 = !if (!eq(ImmOpStr, "u6Imm"), src3{5}, + !if (!eq(mnemonic, "extractu"), 0, 1)); + + let bit13 = !if (!eq(ImmOpStr, "u6Imm"), src2{5}, 0); + + let IClass = 0b1000; + + let Inst{27-24} = RegTyBits; + let Inst{23} = bit23; + let Inst{22-21} = src3{4-3}; + let Inst{20-16} = src1; + let Inst{13} = bit13; + let Inst{12-8} = src2{4-0}; + let Inst{7-5} = src3{2-0}; + let Inst{4-0} = dst; + } + +// Extract bitfield + +// Rdd=extractu(Rss,Rtt) +// Rdd=extractu(Rss,#u6,#U6) +let isCodeGenOnly = 0 in { +def S2_extractup_rp : T_S3op_64 < "extractu", 0b00, 0b000, 0>; +def S2_extractup : T_S2op_extract <"extractu", 0b0001, DoubleRegs, u6Imm>; +} + +// Rd=extractu(Rs,Rtt) +// Rd=extractu(Rs,#u5,#U5) +let hasNewValue = 1, isCodeGenOnly = 0 in { + def S2_extractu_rp : T_S3op_extract<"extractu", 0b00>; + def S2_extractu : T_S2op_extract <"extractu", 0b1101, IntRegs, u5Imm>; +} + +//===----------------------------------------------------------------------===// +// :raw for of tableindx[bdhw] insns +//===----------------------------------------------------------------------===// + +let hasSideEffects = 0, hasNewValue = 1, opNewValue = 0 in +class tableidxRaw<string OpStr, bits<2>MinOp> + : SInst <(outs IntRegs:$Rx), + (ins IntRegs:$_dst_, IntRegs:$Rs, u4Imm:$u4, s6Imm:$S6), + "$Rx = "#OpStr#"($Rs, #$u4, #$S6):raw", + [], "$Rx = $_dst_" > { + bits<5> Rx; + bits<5> Rs; + bits<4> u4; + bits<6> S6; + + let IClass = 0b1000; + + let Inst{27-24} = 0b0111; + let Inst{23-22} = MinOp; + let Inst{21} = u4{3}; + let Inst{20-16} = Rs; + let Inst{13-8} = S6; + let Inst{7-5} = u4{2-0}; + let Inst{4-0} = Rx; + } + +let isCodeGenOnly = 0 in { +def S2_tableidxb : tableidxRaw<"tableidxb", 0b00>; +def S2_tableidxh : tableidxRaw<"tableidxh", 0b01>; +def S2_tableidxw : tableidxRaw<"tableidxw", 0b10>; +def S2_tableidxd : tableidxRaw<"tableidxd", 0b11>; +} // Change the sign of the immediate for Rd=-mpyi(Rs,#u8) def : Pat <(mul (i32 IntRegs:$src1), (ineg n8ImmPred:$src2)), - (i32 (MPYI_rin (i32 IntRegs:$src1), u8ImmPred:$src2))>; + (i32 (M2_mpysin (i32 IntRegs:$src1), u8ImmPred:$src2))>; //===----------------------------------------------------------------------===// // V3 Instructions + diff --git a/lib/Target/Hexagon/HexagonInstrInfoV3.td b/lib/Target/Hexagon/HexagonInstrInfoV3.td index 7e75554e7fcd..8e9147600fa6 100644 --- a/lib/Target/Hexagon/HexagonInstrInfoV3.td +++ b/lib/Target/Hexagon/HexagonInstrInfoV3.td @@ -21,13 +21,52 @@ def callv3nr : SDNode<"HexagonISD::CALLv3nr", SDT_SPCall, // J + //===----------------------------------------------------------------------===// // Call subroutine. -let isCall = 1, neverHasSideEffects = 1, - Defs = [D0, D1, D2, D3, D4, D5, D6, D7, R28, R31, - P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { - def CALLv3 : JInst<(outs), (ins calltarget:$dst), - "call $dst", []>, Requires<[HasV3T]>; +let isCall = 1, hasSideEffects = 1, validSubTargets = HasV3SubT, + Defs = VolatileV3.Regs, isPredicable = 1, + isExtended = 0, isExtendable = 1, opExtendable = 0, + isExtentSigned = 1, opExtentBits = 24, opExtentAlign = 2 in +class T_Call<string ExtStr> + : JInst<(outs), (ins calltarget:$dst), + "call " # ExtStr # "$dst", [], "", J_tc_2early_SLOT23> { + let BaseOpcode = "call"; + bits<24> dst; + + let IClass = 0b0101; + let Inst{27-25} = 0b101; + let Inst{24-16,13-1} = dst{23-2}; + let Inst{0} = 0b0; +} + +let isCall = 1, hasSideEffects = 1, validSubTargets = HasV3SubT, + Defs = VolatileV3.Regs, isPredicated = 1, + isExtended = 0, isExtendable = 1, opExtendable = 1, + isExtentSigned = 1, opExtentBits = 17, opExtentAlign = 2 in +class T_CallPred<bit IfTrue, string ExtStr> + : JInst<(outs), (ins PredRegs:$Pu, calltarget:$dst), + CondStr<"$Pu", IfTrue, 0>.S # "call " # ExtStr # "$dst", + [], "", J_tc_2early_SLOT23> { + let BaseOpcode = "call"; + let isPredicatedFalse = !if(IfTrue,0,1); + bits<2> Pu; + bits<17> dst; + + let IClass = 0b0101; + let Inst{27-24} = 0b1101; + let Inst{23-22,20-16,13,7-1} = dst{16-2}; + let Inst{21} = !if(IfTrue,0,1); + let Inst{11} = 0b0; + let Inst{9-8} = Pu; +} + +multiclass T_Calls<string ExtStr> { + def NAME : T_Call<ExtStr>; + def t : T_CallPred<1, ExtStr>; + def f : T_CallPred<0, ExtStr>; } +let isCodeGenOnly = 0 in +defm J2_call: T_Calls<"">, PredRel; + //===----------------------------------------------------------------------===// // J - //===----------------------------------------------------------------------===// @@ -37,7 +76,7 @@ let isCall = 1, neverHasSideEffects = 1, // JR + //===----------------------------------------------------------------------===// // Call subroutine from register. -let isCall = 1, neverHasSideEffects = 1, +let isCall = 1, hasSideEffects = 0, Defs = [D0, D1, D2, D3, D4, D5, D6, D7, R28, R31, P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { def CALLRv3 : JRInst<(outs), (ins IntRegs:$dst), @@ -53,27 +92,69 @@ let isCall = 1, neverHasSideEffects = 1, // ALU64/ALU + //===----------------------------------------------------------------------===// -let AddedComplexity = 200 in -def MAXw_dd : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = max($src2, $src1)", - [(set (i64 DoubleRegs:$dst), - (i64 (select (i1 (setlt (i64 DoubleRegs:$src2), - (i64 DoubleRegs:$src1))), - (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2))))]>, -Requires<[HasV3T]>; - -let AddedComplexity = 200 in -def MINw_dd : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, - DoubleRegs:$src2), - "$dst = min($src2, $src1)", - [(set (i64 DoubleRegs:$dst), - (i64 (select (i1 (setgt (i64 DoubleRegs:$src2), - (i64 DoubleRegs:$src1))), - (i64 DoubleRegs:$src1), - (i64 DoubleRegs:$src2))))]>, -Requires<[HasV3T]>; + +let Defs = [USR_OVF], Itinerary = ALU64_tc_2_SLOT23, + validSubTargets = HasV3SubT, isCodeGenOnly = 0 in +def A2_addpsat : T_ALU64_arith<"add", 0b011, 0b101, 1, 0, 1>; + +class T_ALU64_addsp_hl<string suffix, bits<3> MinOp> + : T_ALU64_rr<"add", suffix, 0b0011, 0b011, MinOp, 0, 0, "">; + +let isCodeGenOnly = 0 in { +def A2_addspl : T_ALU64_addsp_hl<":raw:lo", 0b110>; +def A2_addsph : T_ALU64_addsp_hl<":raw:hi", 0b111>; +} + +let hasSideEffects = 0, isCodeGenOnly = 0 in +def A2_addsp : ALU64_rr<(outs DoubleRegs:$Rd), + (ins IntRegs:$Rs, DoubleRegs:$Rt), "$Rd = add($Rs, $Rt)", + [(set (i64 DoubleRegs:$Rd), (i64 (add (i64 (sext (i32 IntRegs:$Rs))), + (i64 DoubleRegs:$Rt))))], + "", ALU64_tc_1_SLOT23>; + + +let hasSideEffects = 0 in +class T_XTYPE_MIN_MAX_P<bit isMax, bit isUnsigned> + : ALU64Inst<(outs DoubleRegs:$Rd), (ins DoubleRegs:$Rt, DoubleRegs:$Rs), + "$Rd = "#!if(isMax,"max","min")#!if(isUnsigned,"u","") + #"($Rt, $Rs)", [], "", ALU64_tc_2_SLOT23> { + bits<5> Rd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1101; + + let Inst{27-23} = 0b00111; + let Inst{22-21} = !if(isMax, 0b10, 0b01); + let Inst{20-16} = !if(isMax, Rt, Rs); + let Inst{12-8} = !if(isMax, Rs, Rt); + let Inst{7} = 0b1; + let Inst{6} = !if(isMax, 0b0, 0b1); + let Inst{5} = isUnsigned; + let Inst{4-0} = Rd; +} + +let isCodeGenOnly = 0 in { +def A2_minp : T_XTYPE_MIN_MAX_P<0, 0>; +def A2_minup : T_XTYPE_MIN_MAX_P<0, 1>; +def A2_maxp : T_XTYPE_MIN_MAX_P<1, 0>; +def A2_maxup : T_XTYPE_MIN_MAX_P<1, 1>; +} + +multiclass MinMax_pats_p<PatFrag Op, InstHexagon Inst, InstHexagon SwapInst> { + defm: T_MinMax_pats<Op, DoubleRegs, i64, Inst, SwapInst>; +} + +let AddedComplexity = 200 in { + defm: MinMax_pats_p<setge, A2_maxp, A2_minp>; + defm: MinMax_pats_p<setgt, A2_maxp, A2_minp>; + defm: MinMax_pats_p<setle, A2_minp, A2_maxp>; + defm: MinMax_pats_p<setlt, A2_minp, A2_maxp>; + defm: MinMax_pats_p<setuge, A2_maxup, A2_minup>; + defm: MinMax_pats_p<setugt, A2_maxup, A2_minup>; + defm: MinMax_pats_p<setule, A2_minup, A2_maxup>; + defm: MinMax_pats_p<setult, A2_minup, A2_maxup>; +} //===----------------------------------------------------------------------===// // ALU64/ALU - @@ -100,8 +181,8 @@ Requires<[HasV3T]>; // Map call instruction def : Pat<(call (i32 IntRegs:$dst)), - (CALLRv3 (i32 IntRegs:$dst))>, Requires<[HasV3T]>; + (J2_call (i32 IntRegs:$dst))>, Requires<[HasV3T]>; def : Pat<(call tglobaladdr:$dst), - (CALLv3 tglobaladdr:$dst)>, Requires<[HasV3T]>; + (J2_call tglobaladdr:$dst)>, Requires<[HasV3T]>; def : Pat<(call texternalsym:$dst), - (CALLv3 texternalsym:$dst)>, Requires<[HasV3T]>; + (J2_call texternalsym:$dst)>, Requires<[HasV3T]>; diff --git a/lib/Target/Hexagon/HexagonInstrInfoV4.td b/lib/Target/Hexagon/HexagonInstrInfoV4.td index db5b7eaa68f8..08bfd676fed8 100644 --- a/lib/Target/Hexagon/HexagonInstrInfoV4.td +++ b/lib/Target/Hexagon/HexagonInstrInfoV4.td @@ -11,15 +11,32 @@ // //===----------------------------------------------------------------------===// -let neverHasSideEffects = 1 in -class T_Immext<dag ins> : - EXTENDERInst<(outs), ins, "immext(#$imm)", []>, - Requires<[HasV4T]>; +let hasSideEffects = 0 in +class T_Immext<Operand ImmType> + : EXTENDERInst<(outs), (ins ImmType:$imm), + "immext(#$imm)", []> { + bits<32> imm; + let IClass = 0b0000; + + let Inst{27-16} = imm{31-20}; + let Inst{13-0} = imm{19-6}; + } + +def A4_ext : T_Immext<u26_6Imm>; +let isCodeGenOnly = 1 in { + let isBranch = 1 in + def A4_ext_b : T_Immext<brtarget>; + let isCall = 1 in + def A4_ext_c : T_Immext<calltarget>; + def A4_ext_g : T_Immext<globaladdress>; +} -def IMMEXT_b : T_Immext<(ins brtarget:$imm)>; -def IMMEXT_c : T_Immext<(ins calltarget:$imm)>; -def IMMEXT_g : T_Immext<(ins globaladdress:$imm)>; -def IMMEXT_i : T_Immext<(ins u26_6Imm:$imm)>; +def BITPOS32 : SDNodeXForm<imm, [{ + // Return the bit position we will set [0-31]. + // As an SDNode. + int32_t imm = N->getSExtValue(); + return XformMskToBitPosU5Imm(imm); +}]>; // Fold (add (CONST32 tglobaladdr:$addr) <offset>) into a global address. def FoldGlobalAddr : ComplexPattern<i32, 1, "foldGlobalAddress", [], []>; @@ -95,63 +112,152 @@ def NumUsesBelowThresCONST32 : PatFrag<(ops node:$addr), //===----------------------------------------------------------------------===// // ALU32 + //===----------------------------------------------------------------------===// -// Generate frame index addresses. -let neverHasSideEffects = 1, isReMaterializable = 1, -isExtended = 1, opExtendable = 2, validSubTargets = HasV4SubT in -def TFR_FI_immext_V4 : ALU32_ri<(outs IntRegs:$dst), - (ins IntRegs:$src1, s32Imm:$offset), - "$dst = add($src1, ##$offset)", - []>, - Requires<[HasV4T]>; -// Rd=cmp.eq(Rs,#s8) -let validSubTargets = HasV4SubT, isExtendable = 1, opExtendable = 2, -isExtentSigned = 1, opExtentBits = 8 in -def V4_A4_rcmpeqi : ALU32_ri<(outs IntRegs:$Rd), - (ins IntRegs:$Rs, s8Ext:$s8), - "$Rd = cmp.eq($Rs, #$s8)", - [(set (i32 IntRegs:$Rd), - (i32 (zext (i1 (seteq (i32 IntRegs:$Rs), - s8ExtPred:$s8)))))]>, - Requires<[HasV4T]>; - -// Preserve the TSTBIT generation -def : Pat <(i32 (zext (i1 (setne (i32 (and (i32 (shl 1, (i32 IntRegs:$src2))), - (i32 IntRegs:$src1))), 0)))), - (i32 (MUX_ii (i1 (TSTBIT_rr (i32 IntRegs:$src1), (i32 IntRegs:$src2))), - 1, 0))>; - -// Interfered with tstbit generation, above pattern preserves, see : tstbit.ll -// Rd=cmp.ne(Rs,#s8) -let validSubTargets = HasV4SubT, isExtendable = 1, opExtendable = 2, -isExtentSigned = 1, opExtentBits = 8 in -def V4_A4_rcmpneqi : ALU32_ri<(outs IntRegs:$Rd), - (ins IntRegs:$Rs, s8Ext:$s8), - "$Rd = !cmp.eq($Rs, #$s8)", - [(set (i32 IntRegs:$Rd), - (i32 (zext (i1 (setne (i32 IntRegs:$Rs), - s8ExtPred:$s8)))))]>, - Requires<[HasV4T]>; - -// Rd=cmp.eq(Rs,Rt) -let validSubTargets = HasV4SubT in -def V4_A4_rcmpeq : ALU32_ri<(outs IntRegs:$Rd), - (ins IntRegs:$Rs, IntRegs:$Rt), - "$Rd = cmp.eq($Rs, $Rt)", - [(set (i32 IntRegs:$Rd), - (i32 (zext (i1 (seteq (i32 IntRegs:$Rs), - IntRegs:$Rt)))))]>, - Requires<[HasV4T]>; +class T_ALU32_3op_not<string mnemonic, bits<3> MajOp, bits<3> MinOp, + bit OpsRev> + : T_ALU32_3op<mnemonic, MajOp, MinOp, OpsRev, 0> { + let AsmString = "$Rd = "#mnemonic#"($Rs, ~$Rt)"; +} + +let BaseOpcode = "andn_rr", CextOpcode = "andn", isCodeGenOnly = 0 in +def A4_andn : T_ALU32_3op_not<"and", 0b001, 0b100, 1>; +let BaseOpcode = "orn_rr", CextOpcode = "orn", isCodeGenOnly = 0 in +def A4_orn : T_ALU32_3op_not<"or", 0b001, 0b101, 1>; + +let CextOpcode = "rcmp.eq", isCodeGenOnly = 0 in +def A4_rcmpeq : T_ALU32_3op<"cmp.eq", 0b011, 0b010, 0, 1>; +let CextOpcode = "!rcmp.eq", isCodeGenOnly = 0 in +def A4_rcmpneq : T_ALU32_3op<"!cmp.eq", 0b011, 0b011, 0, 1>; + +let isCodeGenOnly = 0 in { +def C4_cmpneq : T_ALU32_3op_cmp<"!cmp.eq", 0b00, 1, 1>; +def C4_cmplte : T_ALU32_3op_cmp<"!cmp.gt", 0b10, 1, 0>; +def C4_cmplteu : T_ALU32_3op_cmp<"!cmp.gtu", 0b11, 1, 0>; +} + +// Pats for instruction selection. + +// A class to embed the usual comparison patfrags within a zext to i32. +// The seteq/setne frags use "lhs" and "rhs" as operands, so use the same +// names, or else the frag's "body" won't match the operands. +class CmpInReg<PatFrag Op> + : PatFrag<(ops node:$lhs, node:$rhs),(i32 (zext (i1 Op.Fragment)))>; + +def: T_cmp32_rr_pat<A4_rcmpeq, CmpInReg<seteq>, i32>; +def: T_cmp32_rr_pat<A4_rcmpneq, CmpInReg<setne>, i32>; + +class T_CMP_rrbh<string mnemonic, bits<3> MinOp, bit IsComm> + : SInst<(outs PredRegs:$Pd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Pd = "#mnemonic#"($Rs, $Rt)", [], "", S_3op_tc_2early_SLOT23>, + ImmRegRel { + let validSubTargets = HasV4SubT; + let InputType = "reg"; + let CextOpcode = mnemonic; + let isCompare = 1; + let isCommutable = IsComm; + let hasSideEffects = 0; + + bits<2> Pd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1100; + let Inst{27-21} = 0b0111110; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{7-5} = MinOp; + let Inst{1-0} = Pd; +} + +let isCodeGenOnly = 0 in { +def A4_cmpbeq : T_CMP_rrbh<"cmpb.eq", 0b110, 1>; +def A4_cmpbgt : T_CMP_rrbh<"cmpb.gt", 0b010, 0>; +def A4_cmpbgtu : T_CMP_rrbh<"cmpb.gtu", 0b111, 0>; +def A4_cmpheq : T_CMP_rrbh<"cmph.eq", 0b011, 1>; +def A4_cmphgt : T_CMP_rrbh<"cmph.gt", 0b100, 0>; +def A4_cmphgtu : T_CMP_rrbh<"cmph.gtu", 0b101, 0>; +} + +class T_CMP_ribh<string mnemonic, bits<2> MajOp, bit IsHalf, bit IsComm, + Operand ImmType, bit IsImmExt, bit IsImmSigned, int ImmBits> + : ALU64Inst<(outs PredRegs:$Pd), (ins IntRegs:$Rs, ImmType:$Imm), + "$Pd = "#mnemonic#"($Rs, #$Imm)", [], "", ALU64_tc_2early_SLOT23>, + ImmRegRel { + let validSubTargets = HasV4SubT; + let InputType = "imm"; + let CextOpcode = mnemonic; + let isCompare = 1; + let isCommutable = IsComm; + let hasSideEffects = 0; + let isExtendable = IsImmExt; + let opExtendable = !if (IsImmExt, 2, 0); + let isExtentSigned = IsImmSigned; + let opExtentBits = ImmBits; + + bits<2> Pd; + bits<5> Rs; + bits<8> Imm; + + let IClass = 0b1101; + let Inst{27-24} = 0b1101; + let Inst{22-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{12-5} = Imm; + let Inst{4} = 0b0; + let Inst{3} = IsHalf; + let Inst{1-0} = Pd; +} + +let isCodeGenOnly = 0 in { +def A4_cmpbeqi : T_CMP_ribh<"cmpb.eq", 0b00, 0, 1, u8Imm, 0, 0, 8>; +def A4_cmpbgti : T_CMP_ribh<"cmpb.gt", 0b01, 0, 0, s8Imm, 0, 1, 8>; +def A4_cmpbgtui : T_CMP_ribh<"cmpb.gtu", 0b10, 0, 0, u7Ext, 1, 0, 7>; +def A4_cmpheqi : T_CMP_ribh<"cmph.eq", 0b00, 1, 1, s8Ext, 1, 1, 8>; +def A4_cmphgti : T_CMP_ribh<"cmph.gt", 0b01, 1, 0, s8Ext, 1, 1, 8>; +def A4_cmphgtui : T_CMP_ribh<"cmph.gtu", 0b10, 1, 0, u7Ext, 1, 0, 7>; +} +class T_RCMP_EQ_ri<string mnemonic, bit IsNeg> + : ALU32_ri<(outs IntRegs:$Rd), (ins IntRegs:$Rs, s8Ext:$s8), + "$Rd = "#mnemonic#"($Rs, #$s8)", [], "", ALU32_2op_tc_1_SLOT0123>, + ImmRegRel { + let validSubTargets = HasV4SubT; + let InputType = "imm"; + let CextOpcode = !if (IsNeg, "!rcmp.eq", "rcmp.eq"); + let isExtendable = 1; + let opExtendable = 2; + let isExtentSigned = 1; + let opExtentBits = 8; + let hasNewValue = 1; + + bits<5> Rd; + bits<5> Rs; + bits<8> s8; + + let IClass = 0b0111; + let Inst{27-24} = 0b0011; + let Inst{22} = 0b1; + let Inst{21} = IsNeg; + let Inst{20-16} = Rs; + let Inst{13} = 0b1; + let Inst{12-5} = s8; + let Inst{4-0} = Rd; +} + +let isCodeGenOnly = 0 in { +def A4_rcmpeqi : T_RCMP_EQ_ri<"cmp.eq", 0>; +def A4_rcmpneqi : T_RCMP_EQ_ri<"!cmp.eq", 1>; +} + +def: Pat<(i32 (zext (i1 (seteq (i32 IntRegs:$Rs), s8ExtPred:$s8)))), + (A4_rcmpeqi IntRegs:$Rs, s8ExtPred:$s8)>; +def: Pat<(i32 (zext (i1 (setne (i32 IntRegs:$Rs), s8ExtPred:$s8)))), + (A4_rcmpneqi IntRegs:$Rs, s8ExtPred:$s8)>; + +// Preserve the S2_tstbit_r generation +def: Pat<(i32 (zext (i1 (setne (i32 (and (i32 (shl 1, (i32 IntRegs:$src2))), + (i32 IntRegs:$src1))), 0)))), + (C2_muxii (S2_tstbit_r IntRegs:$src1, IntRegs:$src2), 1, 0)>; -// Rd=cmp.ne(Rs,Rt) -let validSubTargets = HasV4SubT in -def V4_A4_rcmpneq : ALU32_ri<(outs IntRegs:$Rd), - (ins IntRegs:$Rs, IntRegs:$Rt), - "$Rd = !cmp.eq($Rs, $Rt)", - [(set (i32 IntRegs:$Rd), - (i32 (zext (i1 (setne (i32 IntRegs:$Rs), - IntRegs:$Rt)))))]>, - Requires<[HasV4T]>; //===----------------------------------------------------------------------===// // ALU32 - @@ -162,24 +268,31 @@ def V4_A4_rcmpneq : ALU32_ri<(outs IntRegs:$Rd), // ALU32/PERM + //===----------------------------------------------------------------------===// -// Combine -// Rdd=combine(Rs, #s8) -let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8, - neverHasSideEffects = 1, validSubTargets = HasV4SubT in -def COMBINE_rI_V4 : ALU32_ri<(outs DoubleRegs:$dst), - (ins IntRegs:$src1, s8Ext:$src2), - "$dst = combine($src1, #$src2)", - []>, - Requires<[HasV4T]>; +// Combine a word and an immediate into a register pair. +let hasSideEffects = 0, isExtentSigned = 1, isExtendable = 1, + opExtentBits = 8 in +class T_Combine1 <bits<2> MajOp, dag ins, string AsmStr> + : ALU32Inst <(outs DoubleRegs:$Rdd), ins, AsmStr> { + bits<5> Rdd; + bits<5> Rs; + bits<8> s8; + + let IClass = 0b0111; + let Inst{27-24} = 0b0011; + let Inst{22-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{13} = 0b1; + let Inst{12-5} = s8; + let Inst{4-0} = Rdd; + } -// Rdd=combine(#s8, Rs) -let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 8, - neverHasSideEffects = 1, validSubTargets = HasV4SubT in -def COMBINE_Ir_V4 : ALU32_ir<(outs DoubleRegs:$dst), - (ins s8Ext:$src1, IntRegs:$src2), - "$dst = combine(#$src1, $src2)", - []>, - Requires<[HasV4T]>; +let opExtendable = 2, isCodeGenOnly = 0 in +def A4_combineri : T_Combine1<0b00, (ins IntRegs:$Rs, s8Ext:$s8), + "$Rdd = combine($Rs, #$s8)">; + +let opExtendable = 1, isCodeGenOnly = 0 in +def A4_combineir : T_Combine1<0b01, (ins s8Ext:$s8, IntRegs:$Rs), + "$Rdd = combine(#$s8, $Rs)">; def HexagonWrapperCombineRI_V4 : SDNode<"HexagonISD::WrapperCombineRI_V4", SDTHexagonI64I32I32>; @@ -187,23 +300,31 @@ def HexagonWrapperCombineIR_V4 : SDNode<"HexagonISD::WrapperCombineIR_V4", SDTHexagonI64I32I32>; def : Pat <(HexagonWrapperCombineRI_V4 IntRegs:$r, s8ExtPred:$i), - (COMBINE_rI_V4 IntRegs:$r, s8ExtPred:$i)>, + (A4_combineri IntRegs:$r, s8ExtPred:$i)>, Requires<[HasV4T]>; def : Pat <(HexagonWrapperCombineIR_V4 s8ExtPred:$i, IntRegs:$r), - (COMBINE_Ir_V4 s8ExtPred:$i, IntRegs:$r)>, + (A4_combineir s8ExtPred:$i, IntRegs:$r)>, Requires<[HasV4T]>; -let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 6, - neverHasSideEffects = 1, validSubTargets = HasV4SubT in -def COMBINE_iI_V4 : ALU32_ii<(outs DoubleRegs:$dst), - (ins s8Imm:$src1, u6Ext:$src2), - "$dst = combine(#$src1, #$src2)", - []>, - Requires<[HasV4T]>; +// A4_combineii: Set two small immediates. +let hasSideEffects = 0, isExtendable = 1, opExtentBits = 6, opExtendable = 2 in +def A4_combineii: ALU32Inst<(outs DoubleRegs:$Rdd), (ins s8Imm:$s8, u6Ext:$U6), + "$Rdd = combine(#$s8, #$U6)"> { + bits<5> Rdd; + bits<8> s8; + bits<6> U6; + + let IClass = 0b0111; + let Inst{27-23} = 0b11001; + let Inst{20-16} = U6{5-1}; + let Inst{13} = U6{0}; + let Inst{12-5} = s8; + let Inst{4-0} = Rdd; + } //===----------------------------------------------------------------------===// -// ALU32/PERM + +// ALU32/PERM - //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// @@ -212,7 +333,7 @@ def COMBINE_iI_V4 : ALU32_ii<(outs DoubleRegs:$dst), //===----------------------------------------------------------------------===// // Template class for load instructions with Absolute set addressing mode. //===----------------------------------------------------------------------===// -let isExtended = 1, opExtendable = 2, neverHasSideEffects = 1, +let isExtended = 1, opExtendable = 2, hasSideEffects = 0, validSubTargets = HasV4SubT, addrMode = AbsoluteSet in class T_LD_abs_set<string mnemonic, RegisterClass RC>: LDInst2<(outs RC:$dst1, IntRegs:$dst2), @@ -228,112 +349,152 @@ def LDrih_abs_set_V4 : T_LD_abs_set <"memh", IntRegs>; def LDriw_abs_set_V4 : T_LD_abs_set <"memw", IntRegs>; def LDriuh_abs_set_V4 : T_LD_abs_set <"memuh", IntRegs>; +//===----------------------------------------------------------------------===// +// Template classes for the non-predicated load instructions with +// base + register offset addressing mode +//===----------------------------------------------------------------------===// +class T_load_rr <string mnemonic, RegisterClass RC, bits<3> MajOp>: + LDInst<(outs RC:$dst), (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$u2), + "$dst = "#mnemonic#"($src1 + $src2<<#$u2)", + [], "", V4LDST_tc_ld_SLOT01>, ImmRegShl, AddrModeRel { + bits<5> dst; + bits<5> src1; + bits<5> src2; + bits<2> u2; -// multiclass for load instructions with base + register offset -// addressing mode -multiclass ld_idxd_shl_pbase<string mnemonic, RegisterClass RC, bit isNot, - bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : LDInst2<(outs RC:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$offset), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#"$dst = "#mnemonic#"($src2+$src3<<#$offset)", - []>, Requires<[HasV4T]>; -} + let IClass = 0b0011; -multiclass ld_idxd_shl_pred<string mnemonic, RegisterClass RC, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 0>; - // Predicate new - defm _cdn#NAME : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 1>; + let Inst{27-24} = 0b1010; + let Inst{23-21} = MajOp; + let Inst{20-16} = src1; + let Inst{12-8} = src2; + let Inst{13} = u2{1}; + let Inst{7} = u2{0}; + let Inst{4-0} = dst; } -} -let neverHasSideEffects = 1 in -multiclass ld_idxd_shl<string mnemonic, string CextOp, RegisterClass RC> { - let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in { +//===----------------------------------------------------------------------===// +// Template classes for the predicated load instructions with +// base + register offset addressing mode +//===----------------------------------------------------------------------===// +let isPredicated = 1 in +class T_pload_rr <string mnemonic, RegisterClass RC, bits<3> MajOp, + bit isNot, bit isPredNew>: + LDInst <(outs RC:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$u2), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#"$dst = "#mnemonic#"($src2+$src3<<#$u2)", + [], "", V4LDST_tc_ld_SLOT01>, AddrModeRel { + bits<5> dst; + bits<2> src1; + bits<5> src2; + bits<5> src3; + bits<2> u2; + + let isPredicatedFalse = isNot; + let isPredicatedNew = isPredNew; + + let IClass = 0b0011; + + let Inst{27-26} = 0b00; + let Inst{25} = isPredNew; + let Inst{24} = isNot; + let Inst{23-21} = MajOp; + let Inst{20-16} = src2; + let Inst{12-8} = src3; + let Inst{13} = u2{1}; + let Inst{7} = u2{0}; + let Inst{6-5} = src1; + let Inst{4-0} = dst; + } + +//===----------------------------------------------------------------------===// +// multiclass for load instructions with base + register offset +// addressing mode +//===----------------------------------------------------------------------===// +let hasSideEffects = 0, addrMode = BaseRegOffset in +multiclass ld_idxd_shl <string mnemonic, string CextOp, RegisterClass RC, + bits<3> MajOp > { + let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl, + InputType = "reg" in { let isPredicable = 1 in - def NAME#_V4 : LDInst2<(outs RC:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), - "$dst = "#mnemonic#"($src1+$src2<<#$offset)", - []>, Requires<[HasV4T]>; - - let isPredicated = 1 in { - defm Pt_V4 : ld_idxd_shl_pred<mnemonic, RC, 0 >; - defm NotPt_V4 : ld_idxd_shl_pred<mnemonic, RC, 1>; - } + def L4_#NAME#_rr : T_load_rr <mnemonic, RC, MajOp>; + + // Predicated + def L4_p#NAME#t_rr : T_pload_rr <mnemonic, RC, MajOp, 0, 0>; + def L4_p#NAME#f_rr : T_pload_rr <mnemonic, RC, MajOp, 1, 0>; + + // Predicated new + def L4_p#NAME#tnew_rr : T_pload_rr <mnemonic, RC, MajOp, 0, 1>; + def L4_p#NAME#fnew_rr : T_pload_rr <mnemonic, RC, MajOp, 1, 1>; } } -let addrMode = BaseRegOffset in { - let accessSize = ByteAccess in { - defm LDrib_indexed_shl: ld_idxd_shl<"memb", "LDrib", IntRegs>, - AddrModeRel; - defm LDriub_indexed_shl: ld_idxd_shl<"memub", "LDriub", IntRegs>, - AddrModeRel; - } - let accessSize = HalfWordAccess in { - defm LDrih_indexed_shl: ld_idxd_shl<"memh", "LDrih", IntRegs>, AddrModeRel; - defm LDriuh_indexed_shl: ld_idxd_shl<"memuh", "LDriuh", IntRegs>, - AddrModeRel; - } - let accessSize = WordAccess in - defm LDriw_indexed_shl: ld_idxd_shl<"memw", "LDriw", IntRegs>, AddrModeRel; +let hasNewValue = 1, accessSize = ByteAccess, isCodeGenOnly = 0 in { + defm loadrb : ld_idxd_shl<"memb", "LDrib", IntRegs, 0b000>; + defm loadrub : ld_idxd_shl<"memub", "LDriub", IntRegs, 0b001>; +} - let accessSize = DoubleWordAccess in - defm LDrid_indexed_shl: ld_idxd_shl<"memd", "LDrid", DoubleRegs>, - AddrModeRel; +let hasNewValue = 1, accessSize = HalfWordAccess, isCodeGenOnly = 0 in { + defm loadrh : ld_idxd_shl<"memh", "LDrih", IntRegs, 0b010>; + defm loadruh : ld_idxd_shl<"memuh", "LDriuh", IntRegs, 0b011>; } +let hasNewValue = 1, accessSize = WordAccess, isCodeGenOnly = 0 in +defm loadri : ld_idxd_shl<"memw", "LDriw", IntRegs, 0b100>; + +let accessSize = DoubleWordAccess, isCodeGenOnly = 0 in +defm loadrd : ld_idxd_shl<"memd", "LDrid", DoubleRegs, 0b110>; + // 'def pats' for load instructions with base + register offset and non-zero // immediate value. Immediate value is used to left-shift the second // register operand. let AddedComplexity = 40 in { def : Pat <(i32 (sextloadi8 (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$offset)))), - (LDrib_indexed_shl_V4 IntRegs:$src1, + (L4_loadrb_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; def : Pat <(i32 (zextloadi8 (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$offset)))), - (LDriub_indexed_shl_V4 IntRegs:$src1, + (L4_loadrub_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; def : Pat <(i32 (extloadi8 (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$offset)))), - (LDriub_indexed_shl_V4 IntRegs:$src1, + (L4_loadrub_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; def : Pat <(i32 (sextloadi16 (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$offset)))), - (LDrih_indexed_shl_V4 IntRegs:$src1, + (L4_loadrh_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; def : Pat <(i32 (zextloadi16 (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$offset)))), - (LDriuh_indexed_shl_V4 IntRegs:$src1, + (L4_loadruh_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; def : Pat <(i32 (extloadi16 (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$offset)))), - (LDriuh_indexed_shl_V4 IntRegs:$src1, + (L4_loadruh_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; def : Pat <(i32 (load (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$offset)))), - (LDriw_indexed_shl_V4 IntRegs:$src1, + (L4_loadri_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; def : Pat <(i64 (load (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$offset)))), - (LDrid_indexed_shl_V4 IntRegs:$src1, + (L4_loadrd_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; } @@ -343,114 +504,114 @@ def : Pat <(i64 (load (add IntRegs:$src1, // zero immediate value. let AddedComplexity = 10 in { def : Pat <(i64 (load (add IntRegs:$src1, IntRegs:$src2))), - (LDrid_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, + (L4_loadrd_rr IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; def : Pat <(i32 (sextloadi8 (add IntRegs:$src1, IntRegs:$src2))), - (LDrib_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, + (L4_loadrb_rr IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; def : Pat <(i32 (zextloadi8 (add IntRegs:$src1, IntRegs:$src2))), - (LDriub_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, + (L4_loadrub_rr IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; def : Pat <(i32 (extloadi8 (add IntRegs:$src1, IntRegs:$src2))), - (LDriub_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, + (L4_loadrub_rr IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; def : Pat <(i32 (sextloadi16 (add IntRegs:$src1, IntRegs:$src2))), - (LDrih_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, + (L4_loadrh_rr IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; def : Pat <(i32 (zextloadi16 (add IntRegs:$src1, IntRegs:$src2))), - (LDriuh_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, + (L4_loadruh_rr IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; def : Pat <(i32 (extloadi16 (add IntRegs:$src1, IntRegs:$src2))), - (LDriuh_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, + (L4_loadruh_rr IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; def : Pat <(i32 (load (add IntRegs:$src1, IntRegs:$src2))), - (LDriw_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, + (L4_loadri_rr IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; } // zext i1->i64 def : Pat <(i64 (zext (i1 PredRegs:$src1))), - (i64 (COMBINE_Ir_V4 0, (MUX_ii (i1 PredRegs:$src1), 1, 0)))>, + (i64 (A4_combineir 0, (C2_muxii (i1 PredRegs:$src1), 1, 0)))>, Requires<[HasV4T]>; // zext i32->i64 def : Pat <(i64 (zext (i32 IntRegs:$src1))), - (i64 (COMBINE_Ir_V4 0, (i32 IntRegs:$src1)))>, + (i64 (A4_combineir 0, (i32 IntRegs:$src1)))>, Requires<[HasV4T]>; // zext i8->i64 def: Pat <(i64 (zextloadi8 ADDRriS11_0:$src1)), - (i64 (COMBINE_Ir_V4 0, (LDriub ADDRriS11_0:$src1)))>, + (i64 (A4_combineir 0, (L2_loadrub_io AddrFI:$src1, 0)))>, Requires<[HasV4T]>; let AddedComplexity = 20 in def: Pat <(i64 (zextloadi8 (add (i32 IntRegs:$src1), s11_0ExtPred:$offset))), - (i64 (COMBINE_Ir_V4 0, (LDriub_indexed IntRegs:$src1, + (i64 (A4_combineir 0, (L2_loadrub_io IntRegs:$src1, s11_0ExtPred:$offset)))>, Requires<[HasV4T]>; // zext i1->i64 def: Pat <(i64 (zextloadi1 ADDRriS11_0:$src1)), - (i64 (COMBINE_Ir_V4 0, (LDriub ADDRriS11_0:$src1)))>, + (i64 (A4_combineir 0, (L2_loadrub_io AddrFI:$src1, 0)))>, Requires<[HasV4T]>; let AddedComplexity = 20 in def: Pat <(i64 (zextloadi1 (add (i32 IntRegs:$src1), s11_0ExtPred:$offset))), - (i64 (COMBINE_Ir_V4 0, (LDriub_indexed IntRegs:$src1, + (i64 (A4_combineir 0, (L2_loadrub_io IntRegs:$src1, s11_0ExtPred:$offset)))>, Requires<[HasV4T]>; // zext i16->i64 def: Pat <(i64 (zextloadi16 ADDRriS11_1:$src1)), - (i64 (COMBINE_Ir_V4 0, (LDriuh ADDRriS11_1:$src1)))>, + (i64 (A4_combineir 0, (L2_loadruh_io AddrFI:$src1, 0)))>, Requires<[HasV4T]>; let AddedComplexity = 20 in def: Pat <(i64 (zextloadi16 (add (i32 IntRegs:$src1), s11_1ExtPred:$offset))), - (i64 (COMBINE_Ir_V4 0, (LDriuh_indexed IntRegs:$src1, + (i64 (A4_combineir 0, (L2_loadruh_io IntRegs:$src1, s11_1ExtPred:$offset)))>, Requires<[HasV4T]>; // anyext i16->i64 def: Pat <(i64 (extloadi16 ADDRriS11_2:$src1)), - (i64 (COMBINE_Ir_V4 0, (LDrih ADDRriS11_2:$src1)))>, + (i64 (A4_combineir 0, (L2_loadrh_io AddrFI:$src1, 0)))>, Requires<[HasV4T]>; let AddedComplexity = 20 in def: Pat <(i64 (extloadi16 (add (i32 IntRegs:$src1), s11_1ExtPred:$offset))), - (i64 (COMBINE_Ir_V4 0, (LDrih_indexed IntRegs:$src1, + (i64 (A4_combineir 0, (L2_loadrh_io IntRegs:$src1, s11_1ExtPred:$offset)))>, Requires<[HasV4T]>; // zext i32->i64 def: Pat <(i64 (zextloadi32 ADDRriS11_2:$src1)), - (i64 (COMBINE_Ir_V4 0, (LDriw ADDRriS11_2:$src1)))>, + (i64 (A4_combineir 0, (L2_loadri_io AddrFI:$src1, 0)))>, Requires<[HasV4T]>; let AddedComplexity = 100 in def: Pat <(i64 (zextloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))), - (i64 (COMBINE_Ir_V4 0, (LDriw_indexed IntRegs:$src1, + (i64 (A4_combineir 0, (L2_loadri_io IntRegs:$src1, s11_2ExtPred:$offset)))>, Requires<[HasV4T]>; // anyext i32->i64 def: Pat <(i64 (extloadi32 ADDRriS11_2:$src1)), - (i64 (COMBINE_Ir_V4 0, (LDriw ADDRriS11_2:$src1)))>, + (i64 (A4_combineir 0, (L2_loadri_io AddrFI:$src1, 0)))>, Requires<[HasV4T]>; let AddedComplexity = 100 in def: Pat <(i64 (extloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))), - (i64 (COMBINE_Ir_V4 0, (LDriw_indexed IntRegs:$src1, + (i64 (A4_combineir 0, (L2_loadri_io IntRegs:$src1, s11_2ExtPred:$offset)))>, Requires<[HasV4T]>; @@ -482,124 +643,209 @@ def STrih_abs_set_V4 : T_ST_abs_set <"memh", IntRegs>; def STriw_abs_set_V4 : T_ST_abs_set <"memw", IntRegs>; //===----------------------------------------------------------------------===// -// multiclass for store instructions with base + register offset addressing -// mode +// Template classes for the non-predicated store instructions with +// base + register offset addressing mode //===----------------------------------------------------------------------===// -multiclass ST_Idxd_shl_Pbase<string mnemonic, RegisterClass RC, bit isNot, - bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - RC:$src5), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; -} +let isPredicable = 1 in +class T_store_rr <string mnemonic, RegisterClass RC, bits<3> MajOp, bit isH> + : STInst < (outs ), (ins IntRegs:$Rs, IntRegs:$Ru, u2Imm:$u2, RC:$Rt), + mnemonic#"($Rs + $Ru<<#$u2) = $Rt"#!if(isH, ".h",""), + [],"",V4LDST_tc_st_SLOT01>, ImmRegShl, AddrModeRel { -multiclass ST_Idxd_shl_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 0>; - // Predicate new - defm _cdn#NAME : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 1>; + bits<5> Rs; + bits<5> Ru; + bits<2> u2; + bits<5> Rt; + + let IClass = 0b0011; + + let Inst{27-24} = 0b1011; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{12-8} = Ru; + let Inst{13} = u2{1}; + let Inst{7} = u2{0}; + let Inst{4-0} = Rt; + } + +//===----------------------------------------------------------------------===// +// Template classes for the predicated store instructions with +// base + register offset addressing mode +//===----------------------------------------------------------------------===// +let isPredicated = 1 in +class T_pstore_rr <string mnemonic, RegisterClass RC, bits<3> MajOp, + bit isNot, bit isPredNew, bit isH> + : STInst <(outs), + (ins PredRegs:$Pv, IntRegs:$Rs, IntRegs:$Ru, u2Imm:$u2, RC:$Rt), + + !if(isNot, "if (!$Pv", "if ($Pv")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($Rs+$Ru<<#$u2) = $Rt"#!if(isH, ".h",""), + [], "", V4LDST_tc_st_SLOT01> , AddrModeRel{ + bits<2> Pv; + bits<5> Rs; + bits<5> Ru; + bits<2> u2; + bits<5> Rt; + + let isPredicatedFalse = isNot; + let isPredicatedNew = isPredNew; + + let IClass = 0b0011; + + let Inst{27-26} = 0b01; + let Inst{25} = isPredNew; + let Inst{24} = isNot; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{12-8} = Ru; + let Inst{13} = u2{1}; + let Inst{7} = u2{0}; + let Inst{6-5} = Pv; + let Inst{4-0} = Rt; + } + +//===----------------------------------------------------------------------===// +// Template classes for the new-value store instructions with +// base + register offset addressing mode +//===----------------------------------------------------------------------===// +let isPredicable = 1, isNewValue = 1, opNewValue = 3 in +class T_store_new_rr <string mnemonic, bits<2> MajOp> : + NVInst < (outs ), (ins IntRegs:$Rs, IntRegs:$Ru, u2Imm:$u2, IntRegs:$Nt), + mnemonic#"($Rs + $Ru<<#$u2) = $Nt.new", + [],"",V4LDST_tc_st_SLOT0>, ImmRegShl, AddrModeRel { + + bits<5> Rs; + bits<5> Ru; + bits<2> u2; + bits<3> Nt; + + let IClass = 0b0011; + + let Inst{27-21} = 0b1011101; + let Inst{20-16} = Rs; + let Inst{12-8} = Ru; + let Inst{13} = u2{1}; + let Inst{7} = u2{0}; + let Inst{4-3} = MajOp; + let Inst{2-0} = Nt; } -} +//===----------------------------------------------------------------------===// +// Template classes for the predicated new-value store instructions with +// base + register offset addressing mode +//===----------------------------------------------------------------------===// +let isPredicated = 1, isNewValue = 1, opNewValue = 4 in +class T_pstore_new_rr <string mnemonic, bits<2> MajOp, bit isNot, bit isPredNew> + : NVInst<(outs), + (ins PredRegs:$Pv, IntRegs:$Rs, IntRegs:$Ru, u2Imm:$u2, IntRegs:$Nt), + !if(isNot, "if (!$Pv", "if ($Pv")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($Rs+$Ru<<#$u2) = $Nt.new", + [], "", V4LDST_tc_st_SLOT0>, AddrModeRel { + bits<2> Pv; + bits<5> Rs; + bits<5> Ru; + bits<2> u2; + bits<3> Nt; + + let isPredicatedFalse = isNot; + let isPredicatedNew = isPredNew; + + let IClass = 0b0011; + let Inst{27-26} = 0b01; + let Inst{25} = isPredNew; + let Inst{24} = isNot; + let Inst{23-21} = 0b101; + let Inst{20-16} = Rs; + let Inst{12-8} = Ru; + let Inst{13} = u2{1}; + let Inst{7} = u2{0}; + let Inst{6-5} = Pv; + let Inst{4-3} = MajOp; + let Inst{2-0} = Nt; + } + +//===----------------------------------------------------------------------===// +// multiclass for store instructions with base + register offset addressing +// mode +//===----------------------------------------------------------------------===// let isNVStorable = 1 in -multiclass ST_Idxd_shl<string mnemonic, string CextOp, RegisterClass RC> { +multiclass ST_Idxd_shl<string mnemonic, string CextOp, RegisterClass RC, + bits<3> MajOp, bit isH = 0> { let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in { - let isPredicable = 1 in - def NAME#_V4 : STInst2<(outs), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, RC:$src4), - mnemonic#"($src1+$src2<<#$src3) = $src4", - []>, - Requires<[HasV4T]>; + def S4_#NAME#_rr : T_store_rr <mnemonic, RC, MajOp, isH>; - let isPredicated = 1 in { - defm Pt_V4 : ST_Idxd_shl_Pred<mnemonic, RC, 0 >; - defm NotPt_V4 : ST_Idxd_shl_Pred<mnemonic, RC, 1>; - } + // Predicated + def S4_p#NAME#t_rr : T_pstore_rr <mnemonic, RC, MajOp, 0, 0, isH>; + def S4_p#NAME#f_rr : T_pstore_rr <mnemonic, RC, MajOp, 1, 0, isH>; + + // Predicated new + def S4_p#NAME#tnew_rr : T_pstore_rr <mnemonic, RC, MajOp, 0, 1, isH>; + def S4_p#NAME#fnew_rr : T_pstore_rr <mnemonic, RC, MajOp, 1, 1, isH>; } } +//===----------------------------------------------------------------------===// // multiclass for new-value store instructions with base + register offset // addressing mode. -multiclass ST_Idxd_shl_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot, - bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME#_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - RC:$src5), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"($src2+$src3<<#$src4) = $src5.new", - []>, - Requires<[HasV4T]>; -} - -multiclass ST_Idxd_shl_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 0>; - // Predicate new - defm _cdn#NAME : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 1>; - } -} - +//===----------------------------------------------------------------------===// let mayStore = 1, isNVStore = 1 in -multiclass ST_Idxd_shl_nv<string mnemonic, string CextOp, RegisterClass RC> { +multiclass ST_Idxd_shl_nv <string mnemonic, string CextOp, RegisterClass RC, + bits<2> MajOp> { let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in { - let isPredicable = 1 in - def NAME#_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, RC:$src4), - mnemonic#"($src1+$src2<<#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; + def S4_#NAME#new_rr : T_store_new_rr<mnemonic, MajOp>; - let isPredicated = 1 in { - defm Pt : ST_Idxd_shl_Pred_nv<mnemonic, RC, 0 >; - defm NotPt : ST_Idxd_shl_Pred_nv<mnemonic, RC, 1>; - } + // Predicated + def S4_p#NAME#newt_rr : T_pstore_new_rr <mnemonic, MajOp, 0, 0>; + def S4_p#NAME#newf_rr : T_pstore_new_rr <mnemonic, MajOp, 1, 0>; + + // Predicated new + def S4_p#NAME#newtnew_rr : T_pstore_new_rr <mnemonic, MajOp, 0, 1>; + def S4_p#NAME#newfnew_rr : T_pstore_new_rr <mnemonic, MajOp, 1, 1>; } } -let addrMode = BaseRegOffset, neverHasSideEffects = 1, -validSubTargets = HasV4SubT in { +let addrMode = BaseRegOffset, InputType = "reg", hasSideEffects = 0, + isCodeGenOnly = 0 in { let accessSize = ByteAccess in - defm STrib_indexed_shl: ST_Idxd_shl<"memb", "STrib", IntRegs>, - ST_Idxd_shl_nv<"memb", "STrib", IntRegs>, AddrModeRel; + defm storerb: ST_Idxd_shl<"memb", "STrib", IntRegs, 0b000>, + ST_Idxd_shl_nv<"memb", "STrib", IntRegs, 0b00>; let accessSize = HalfWordAccess in - defm STrih_indexed_shl: ST_Idxd_shl<"memh", "STrih", IntRegs>, - ST_Idxd_shl_nv<"memh", "STrih", IntRegs>, AddrModeRel; + defm storerh: ST_Idxd_shl<"memh", "STrih", IntRegs, 0b010>, + ST_Idxd_shl_nv<"memh", "STrih", IntRegs, 0b01>; let accessSize = WordAccess in - defm STriw_indexed_shl: ST_Idxd_shl<"memw", "STriw", IntRegs>, - ST_Idxd_shl_nv<"memw", "STriw", IntRegs>, AddrModeRel; + defm storeri: ST_Idxd_shl<"memw", "STriw", IntRegs, 0b100>, + ST_Idxd_shl_nv<"memw", "STriw", IntRegs, 0b10>; let isNVStorable = 0, accessSize = DoubleWordAccess in - defm STrid_indexed_shl: ST_Idxd_shl<"memd", "STrid", DoubleRegs>, AddrModeRel; + defm storerd: ST_Idxd_shl<"memd", "STrid", DoubleRegs, 0b110>; + + let isNVStorable = 0, accessSize = HalfWordAccess in + defm storerf: ST_Idxd_shl<"memh", "STrif", IntRegs, 0b011, 1>; } let Predicates = [HasV4T], AddedComplexity = 10 in { def : Pat<(truncstorei8 (i32 IntRegs:$src4), (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$src3))), - (STrib_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, + (S4_storerb_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$src3, IntRegs:$src4)>; def : Pat<(truncstorei16 (i32 IntRegs:$src4), (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$src3))), - (STrih_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, + (S4_storerh_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$src3, IntRegs:$src4)>; def : Pat<(store (i32 IntRegs:$src4), (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$src3))), - (STriw_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, + (S4_storeri_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$src3, IntRegs:$src4)>; def : Pat<(store (i64 DoubleRegs:$src4), (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$src3))), - (STrid_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, + (S4_storerd_rr IntRegs:$src1, IntRegs:$src2, u2ImmPred:$src3, DoubleRegs:$src4)>; } @@ -668,74 +914,123 @@ defm : T_ST_LOff_Pats<STrih_shl_V4, IntRegs, i32, truncstorei16>; // TODO: needs to be implemented. //===----------------------------------------------------------------------===// +// Template class +//===----------------------------------------------------------------------===// +let isPredicable = 1, isExtendable = 1, isExtentSigned = 1, opExtentBits = 8, + opExtendable = 2 in +class T_StoreImm <string mnemonic, Operand OffsetOp, bits<2> MajOp > + : STInst <(outs ), (ins IntRegs:$Rs, OffsetOp:$offset, s8Ext:$S8), + mnemonic#"($Rs+#$offset)=#$S8", + [], "", V4LDST_tc_st_SLOT01>, + ImmRegRel, PredNewRel { + bits<5> Rs; + bits<8> S8; + bits<8> offset; + bits<6> offsetBits; + + string OffsetOpStr = !cast<string>(OffsetOp); + let offsetBits = !if (!eq(OffsetOpStr, "u6_2Imm"), offset{7-2}, + !if (!eq(OffsetOpStr, "u6_1Imm"), offset{6-1}, + /* u6_0Imm */ offset{5-0})); + + let IClass = 0b0011; + + let Inst{27-25} = 0b110; + let Inst{22-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{12-7} = offsetBits; + let Inst{13} = S8{7}; + let Inst{6-0} = S8{6-0}; + } + +let isPredicated = 1, isExtendable = 1, isExtentSigned = 1, opExtentBits = 6, + opExtendable = 3 in +class T_StoreImm_pred <string mnemonic, Operand OffsetOp, bits<2> MajOp, + bit isPredNot, bit isPredNew > + : STInst <(outs ), + (ins PredRegs:$Pv, IntRegs:$Rs, OffsetOp:$offset, s6Ext:$S6), + !if(isPredNot, "if (!$Pv", "if ($Pv")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($Rs+#$offset)=#$S6", + [], "", V4LDST_tc_st_SLOT01>, + ImmRegRel, PredNewRel { + bits<2> Pv; + bits<5> Rs; + bits<6> S6; + bits<8> offset; + bits<6> offsetBits; + + string OffsetOpStr = !cast<string>(OffsetOp); + let offsetBits = !if (!eq(OffsetOpStr, "u6_2Imm"), offset{7-2}, + !if (!eq(OffsetOpStr, "u6_1Imm"), offset{6-1}, + /* u6_0Imm */ offset{5-0})); + let isPredicatedNew = isPredNew; + let isPredicatedFalse = isPredNot; + + let IClass = 0b0011; + + let Inst{27-25} = 0b100; + let Inst{24} = isPredNew; + let Inst{23} = isPredNot; + let Inst{22-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{13} = S6{5}; + let Inst{12-7} = offsetBits; + let Inst{6-5} = Pv; + let Inst{4-0} = S6{4-0}; + } + + +//===----------------------------------------------------------------------===// // multiclass for store instructions with base + immediate offset // addressing mode and immediate stored value. // mem[bhw](Rx++#s4:3)=#s8 // if ([!]Pv[.new]) mem[bhw](Rx++#s4:3)=#s6 //===----------------------------------------------------------------------===// -multiclass ST_Imm_Pbase<string mnemonic, Operand OffsetOp, bit isNot, - bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, OffsetOp:$src3, s6Ext:$src4), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; -} -multiclass ST_Imm_Pred<string mnemonic, Operand OffsetOp, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 0>; - // Predicate new - defm _cdn#NAME : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 1>; - } +multiclass ST_Imm_Pred <string mnemonic, Operand OffsetOp, bits<2> MajOp, + bit PredNot> { + def _io : T_StoreImm_pred <mnemonic, OffsetOp, MajOp, PredNot, 0>; + // Predicate new + def new_io : T_StoreImm_pred <mnemonic, OffsetOp, MajOp, PredNot, 1>; } -let isExtendable = 1, isExtentSigned = 1, neverHasSideEffects = 1 in -multiclass ST_Imm<string mnemonic, string CextOp, Operand OffsetOp> { +multiclass ST_Imm <string mnemonic, string CextOp, Operand OffsetOp, + bits<2> MajOp> { let CextOpcode = CextOp, BaseOpcode = CextOp#_imm in { - let opExtendable = 2, opExtentBits = 8, isPredicable = 1 in - def NAME#_V4 : STInst2<(outs), - (ins IntRegs:$src1, OffsetOp:$src2, s8Ext:$src3), - mnemonic#"($src1+#$src2) = #$src3", - []>, - Requires<[HasV4T]>; + def _io : T_StoreImm <mnemonic, OffsetOp, MajOp>; - let opExtendable = 3, opExtentBits = 6, isPredicated = 1 in { - defm Pt_V4 : ST_Imm_Pred<mnemonic, OffsetOp, 0>; - defm NotPt_V4 : ST_Imm_Pred<mnemonic, OffsetOp, 1 >; - } + defm t : ST_Imm_Pred <mnemonic, OffsetOp, MajOp, 0>; + defm f : ST_Imm_Pred <mnemonic, OffsetOp, MajOp, 1>; } } -let addrMode = BaseImmOffset, InputType = "imm", -validSubTargets = HasV4SubT in { +let hasSideEffects = 0, validSubTargets = HasV4SubT, addrMode = BaseImmOffset, + InputType = "imm", isCodeGenOnly = 0 in { let accessSize = ByteAccess in - defm STrib_imm : ST_Imm<"memb", "STrib", u6_0Imm>, ImmRegRel, PredNewRel; + defm S4_storeirb : ST_Imm<"memb", "STrib", u6_0Imm, 0b00>; let accessSize = HalfWordAccess in - defm STrih_imm : ST_Imm<"memh", "STrih", u6_1Imm>, ImmRegRel, PredNewRel; + defm S4_storeirh : ST_Imm<"memh", "STrih", u6_1Imm, 0b01>; let accessSize = WordAccess in - defm STriw_imm : ST_Imm<"memw", "STriw", u6_2Imm>, ImmRegRel, PredNewRel; + defm S4_storeiri : ST_Imm<"memw", "STriw", u6_2Imm, 0b10>; } let Predicates = [HasV4T], AddedComplexity = 10 in { def: Pat<(truncstorei8 s8ExtPred:$src3, (add IntRegs:$src1, u6_0ImmPred:$src2)), - (STrib_imm_V4 IntRegs:$src1, u6_0ImmPred:$src2, s8ExtPred:$src3)>; + (S4_storeirb_io IntRegs:$src1, u6_0ImmPred:$src2, s8ExtPred:$src3)>; def: Pat<(truncstorei16 s8ExtPred:$src3, (add IntRegs:$src1, u6_1ImmPred:$src2)), - (STrih_imm_V4 IntRegs:$src1, u6_1ImmPred:$src2, s8ExtPred:$src3)>; + (S4_storeirh_io IntRegs:$src1, u6_1ImmPred:$src2, s8ExtPred:$src3)>; def: Pat<(store s8ExtPred:$src3, (add IntRegs:$src1, u6_2ImmPred:$src2)), - (STriw_imm_V4 IntRegs:$src1, u6_2ImmPred:$src2, s8ExtPred:$src3)>; + (S4_storeiri_io IntRegs:$src1, u6_2ImmPred:$src2, s8ExtPred:$src3)>; } let AddedComplexity = 6 in def : Pat <(truncstorei8 s8ExtPred:$src2, (i32 IntRegs:$src1)), - (STrib_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>, + (S4_storeirb_io IntRegs:$src1, 0, s8ExtPred:$src2)>, Requires<[HasV4T]>; // memb(Rx++#s4:0:circ(Mu))=Rt @@ -751,7 +1046,7 @@ def : Pat <(truncstorei8 s8ExtPred:$src2, (i32 IntRegs:$src1)), // memh(Rs+#s11:1)=Rt.H let AddedComplexity = 6 in def : Pat <(truncstorei16 s8ExtPred:$src2, (i32 IntRegs:$src1)), - (STrih_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>, + (S4_storeirh_io IntRegs:$src1, 0, s8ExtPred:$src2)>, Requires<[HasV4T]>; // memh(Rs+Ru<<#u2)=Rt.H @@ -782,7 +1077,7 @@ def : Pat <(truncstorei16 s8ExtPred:$src2, (i32 IntRegs:$src1)), // TODO: Needs to be implemented. // Store predicate: -let neverHasSideEffects = 1 in +let hasSideEffects = 0 in def STriw_pred_V4 : STInst2<(outs), (ins MEMri:$addr, PredRegs:$src1), "Error; should not emit", @@ -791,7 +1086,7 @@ def STriw_pred_V4 : STInst2<(outs), let AddedComplexity = 6 in def : Pat <(store s8ExtPred:$src2, (i32 IntRegs:$src1)), - (STriw_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>, + (S4_storeiri_io IntRegs:$src1, 0, s8ExtPred:$src2)>, Requires<[HasV4T]>; // memw(Rx++#s4:2)=Rt @@ -809,170 +1104,249 @@ def : Pat <(store s8ExtPred:$src2, (i32 IntRegs:$src1)), // NV/ST + //===----------------------------------------------------------------------===// -// multiclass for new-value store instructions with base + immediate offset. -// -multiclass ST_Idxd_Pbase_nv<string mnemonic, RegisterClass RC, - Operand predImmOp, bit isNot, bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME#_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC: $src4), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; -} +let opNewValue = 2, opExtendable = 1, isExtentSigned = 1, isPredicable = 1 in +class T_store_io_nv <string mnemonic, RegisterClass RC, + Operand ImmOp, bits<2>MajOp> + : NVInst_V4 <(outs), + (ins IntRegs:$src1, ImmOp:$src2, RC:$src3), + mnemonic#"($src1+#$src2) = $src3.new", + [],"",ST_tc_st_SLOT0> { + bits<5> src1; + bits<13> src2; // Actual address offset + bits<3> src3; + bits<11> offsetBits; // Represents offset encoding + + let opExtentBits = !if (!eq(mnemonic, "memb"), 11, + !if (!eq(mnemonic, "memh"), 12, + !if (!eq(mnemonic, "memw"), 13, 0))); + + let opExtentAlign = !if (!eq(mnemonic, "memb"), 0, + !if (!eq(mnemonic, "memh"), 1, + !if (!eq(mnemonic, "memw"), 2, 0))); + + let offsetBits = !if (!eq(mnemonic, "memb"), src2{10-0}, + !if (!eq(mnemonic, "memh"), src2{11-1}, + !if (!eq(mnemonic, "memw"), src2{12-2}, 0))); + + let IClass = 0b1010; + + let Inst{27} = 0b0; + let Inst{26-25} = offsetBits{10-9}; + let Inst{24-21} = 0b1101; + let Inst{20-16} = src1; + let Inst{13} = offsetBits{8}; + let Inst{12-11} = MajOp; + let Inst{10-8} = src3; + let Inst{7-0} = offsetBits{7-0}; + } -multiclass ST_Idxd_Pred_nv<string mnemonic, RegisterClass RC, Operand predImmOp, - bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 0>; - // Predicate new - defm _cdn#NAME : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 1>; +let opExtendable = 2, opNewValue = 3, isPredicated = 1 in +class T_pstore_io_nv <string mnemonic, RegisterClass RC, Operand predImmOp, + bits<2>MajOp, bit PredNot, bit isPredNew> + : NVInst_V4 <(outs), + (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC:$src4), + !if(PredNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($src2+#$src3) = $src4.new", + [],"",V2LDST_tc_st_SLOT0> { + bits<2> src1; + bits<5> src2; + bits<9> src3; + bits<3> src4; + bits<6> offsetBits; // Represents offset encoding + + let isPredicatedNew = isPredNew; + let isPredicatedFalse = PredNot; + let opExtentBits = !if (!eq(mnemonic, "memb"), 6, + !if (!eq(mnemonic, "memh"), 7, + !if (!eq(mnemonic, "memw"), 8, 0))); + + let opExtentAlign = !if (!eq(mnemonic, "memb"), 0, + !if (!eq(mnemonic, "memh"), 1, + !if (!eq(mnemonic, "memw"), 2, 0))); + + let offsetBits = !if (!eq(mnemonic, "memb"), src3{5-0}, + !if (!eq(mnemonic, "memh"), src3{6-1}, + !if (!eq(mnemonic, "memw"), src3{7-2}, 0))); + + let IClass = 0b0100; + + let Inst{27} = 0b0; + let Inst{26} = PredNot; + let Inst{25} = isPredNew; + let Inst{24-21} = 0b0101; + let Inst{20-16} = src2; + let Inst{13} = offsetBits{5}; + let Inst{12-11} = MajOp; + let Inst{10-8} = src4; + let Inst{7-3} = offsetBits{4-0}; + let Inst{2} = 0b0; + let Inst{1-0} = src1; } -} -let mayStore = 1, isNVStore = 1, neverHasSideEffects = 1, isExtendable = 1 in +// multiclass for new-value store instructions with base + immediate offset. +// +let mayStore = 1, isNVStore = 1, isNewValue = 1, hasSideEffects = 0, + isExtendable = 1 in multiclass ST_Idxd_nv<string mnemonic, string CextOp, RegisterClass RC, - Operand ImmOp, Operand predImmOp, bits<5> ImmBits, - bits<5> PredImmBits> { + Operand ImmOp, Operand predImmOp, bits<2> MajOp> { let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in { - let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, - isPredicable = 1 in - def NAME#_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, ImmOp:$src2, RC:$src3), - mnemonic#"($src1+#$src2) = $src3.new", - []>, - Requires<[HasV4T]>; - - let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits, - isPredicated = 1 in { - defm Pt : ST_Idxd_Pred_nv<mnemonic, RC, predImmOp, 0>; - defm NotPt : ST_Idxd_Pred_nv<mnemonic, RC, predImmOp, 1>; - } + def S2_#NAME#new_io : T_store_io_nv <mnemonic, RC, ImmOp, MajOp>; + // Predicated + def S2_p#NAME#newt_io :T_pstore_io_nv <mnemonic, RC, predImmOp, MajOp, 0, 0>; + def S2_p#NAME#newf_io :T_pstore_io_nv <mnemonic, RC, predImmOp, MajOp, 1, 0>; + // Predicated new + def S4_p#NAME#newtnew_io :T_pstore_io_nv <mnemonic, RC, predImmOp, + MajOp, 0, 1>; + def S4_p#NAME#newfnew_io :T_pstore_io_nv <mnemonic, RC, predImmOp, + MajOp, 1, 1>; } } -let addrMode = BaseImmOffset, validSubTargets = HasV4SubT in { +let addrMode = BaseImmOffset, InputType = "imm", isCodeGenOnly = 0 in { let accessSize = ByteAccess in - defm STrib_indexed: ST_Idxd_nv<"memb", "STrib", IntRegs, s11_0Ext, - u6_0Ext, 11, 6>, AddrModeRel; + defm storerb: ST_Idxd_nv<"memb", "STrib", IntRegs, s11_0Ext, + u6_0Ext, 0b00>, AddrModeRel; - let accessSize = HalfWordAccess in - defm STrih_indexed: ST_Idxd_nv<"memh", "STrih", IntRegs, s11_1Ext, - u6_1Ext, 12, 7>, AddrModeRel; + let accessSize = HalfWordAccess, opExtentAlign = 1 in + defm storerh: ST_Idxd_nv<"memh", "STrih", IntRegs, s11_1Ext, + u6_1Ext, 0b01>, AddrModeRel; - let accessSize = WordAccess in - defm STriw_indexed: ST_Idxd_nv<"memw", "STriw", IntRegs, s11_2Ext, - u6_2Ext, 13, 8>, AddrModeRel; + let accessSize = WordAccess, opExtentAlign = 2 in + defm storeri: ST_Idxd_nv<"memw", "STriw", IntRegs, s11_2Ext, + u6_2Ext, 0b10>, AddrModeRel; } -// multiclass for new-value store instructions with base + immediate offset. -// and MEMri operand. -multiclass ST_MEMri_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot, - bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME#_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, RC: $src2), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"($addr) = $src2.new", - []>, - Requires<[HasV4T]>; -} - -multiclass ST_MEMri_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ST_MEMri_Pbase_nv<mnemonic, RC, PredNot, 0>; +//===----------------------------------------------------------------------===// +// Template class for non-predicated post increment .new stores +// mem[bhwd](Rx++#s4:[0123])=Nt.new +//===----------------------------------------------------------------------===// +let isPredicable = 1, hasSideEffects = 0, validSubTargets = HasV4SubT, + addrMode = PostInc, isNVStore = 1, isNewValue = 1, opNewValue = 3 in +class T_StorePI_nv <string mnemonic, Operand ImmOp, bits<2> MajOp > + : NVInstPI_V4 <(outs IntRegs:$_dst_), + (ins IntRegs:$src1, ImmOp:$offset, IntRegs:$src2), + mnemonic#"($src1++#$offset) = $src2.new", + [], "$src1 = $_dst_">, + AddrModeRel { + bits<5> src1; + bits<3> src2; + bits<7> offset; + bits<4> offsetBits; + + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "s4_2Imm"), offset{5-2}, + !if (!eq(ImmOpStr, "s4_1Imm"), offset{4-1}, + /* s4_0Imm */ offset{3-0})); + let IClass = 0b1010; + + let Inst{27-21} = 0b1011101; + let Inst{20-16} = src1; + let Inst{13} = 0b0; + let Inst{12-11} = MajOp; + let Inst{10-8} = src2; + let Inst{7} = 0b0; + let Inst{6-3} = offsetBits; + let Inst{1} = 0b0; + } - // Predicate new - defm _cdn#NAME : ST_MEMri_Pbase_nv<mnemonic, RC, PredNot, 1>; +//===----------------------------------------------------------------------===// +// Template class for predicated post increment .new stores +// if([!]Pv[.new]) mem[bhwd](Rx++#s4:[0123])=Nt.new +//===----------------------------------------------------------------------===// +let isPredicated = 1, hasSideEffects = 0, validSubTargets = HasV4SubT, + addrMode = PostInc, isNVStore = 1, isNewValue = 1, opNewValue = 4 in +class T_StorePI_nv_pred <string mnemonic, Operand ImmOp, + bits<2> MajOp, bit isPredNot, bit isPredNew > + : NVInstPI_V4 <(outs IntRegs:$_dst_), + (ins PredRegs:$src1, IntRegs:$src2, + ImmOp:$offset, IntRegs:$src3), + !if(isPredNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($src2++#$offset) = $src3.new", + [], "$src2 = $_dst_">, + AddrModeRel { + bits<2> src1; + bits<5> src2; + bits<3> src3; + bits<7> offset; + bits<4> offsetBits; + + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "s4_2Imm"), offset{5-2}, + !if (!eq(ImmOpStr, "s4_1Imm"), offset{4-1}, + /* s4_0Imm */ offset{3-0})); + let isPredicatedNew = isPredNew; + let isPredicatedFalse = isPredNot; + + let IClass = 0b1010; + + let Inst{27-21} = 0b1011101; + let Inst{20-16} = src2; + let Inst{13} = 0b1; + let Inst{12-11} = MajOp; + let Inst{10-8} = src3; + let Inst{7} = isPredNew; + let Inst{6-3} = offsetBits; + let Inst{2} = isPredNot; + let Inst{1-0} = src1; } -} -let mayStore = 1, isNVStore = 1, isExtendable = 1, neverHasSideEffects = 1 in -multiclass ST_MEMri_nv<string mnemonic, string CextOp, RegisterClass RC, - bits<5> ImmBits, bits<5> PredImmBits> { +multiclass ST_PostInc_Pred_nv<string mnemonic, Operand ImmOp, + bits<2> MajOp, bit PredNot> { + def _pi : T_StorePI_nv_pred <mnemonic, ImmOp, MajOp, PredNot, 0>; - let CextOpcode = CextOp, BaseOpcode = CextOp in { - let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, - isPredicable = 1 in - def NAME#_nv_V4 : NVInst_V4<(outs), - (ins MEMri:$addr, RC:$src), - mnemonic#"($addr) = $src.new", - []>, - Requires<[HasV4T]>; + // Predicate new + def new_pi : T_StorePI_nv_pred <mnemonic, ImmOp, MajOp, PredNot, 1>; +} - let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits, - neverHasSideEffects = 1, isPredicated = 1 in { - defm Pt : ST_MEMri_Pred_nv<mnemonic, RC, 0>; - defm NotPt : ST_MEMri_Pred_nv<mnemonic, RC, 1>; - } +multiclass ST_PostInc_nv<string mnemonic, string BaseOp, Operand ImmOp, + bits<2> MajOp> { + let BaseOpcode = "POST_"#BaseOp in { + def S2_#NAME#_pi : T_StorePI_nv <mnemonic, ImmOp, MajOp>; + + // Predicated + defm S2_p#NAME#t : ST_PostInc_Pred_nv <mnemonic, ImmOp, MajOp, 0>; + defm S2_p#NAME#f : ST_PostInc_Pred_nv <mnemonic, ImmOp, MajOp, 1>; } } -let addrMode = BaseImmOffset, isMEMri = "true", validSubTargets = HasV4SubT, -mayStore = 1 in { - let accessSize = ByteAccess in - defm STrib: ST_MEMri_nv<"memb", "STrib", IntRegs, 11, 6>, AddrModeRel; +let accessSize = ByteAccess, isCodeGenOnly = 0 in +defm storerbnew: ST_PostInc_nv <"memb", "STrib", s4_0Imm, 0b00>; - let accessSize = HalfWordAccess in - defm STrih: ST_MEMri_nv<"memh", "STrih", IntRegs, 12, 7>, AddrModeRel; +let accessSize = HalfWordAccess, isCodeGenOnly = 0 in +defm storerhnew: ST_PostInc_nv <"memh", "STrih", s4_1Imm, 0b01>; - let accessSize = WordAccess in - defm STriw: ST_MEMri_nv<"memw", "STriw", IntRegs, 13, 8>, AddrModeRel; -} +let accessSize = WordAccess, isCodeGenOnly = 0 in +defm storerinew: ST_PostInc_nv <"memw", "STriw", s4_2Imm, 0b10>; //===----------------------------------------------------------------------===// -// Post increment store -// mem[bhwd](Rx++#s4:[0123])=Nt.new +// Template class for post increment .new stores with register offset //===----------------------------------------------------------------------===// - -multiclass ST_PostInc_Pbase_nv<string mnemonic, RegisterClass RC, Operand ImmOp, - bit isNot, bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME#_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset, RC:$src3), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"($src2++#$offset) = $src3.new", - [], - "$src2 = $dst">, - Requires<[HasV4T]>; -} - -multiclass ST_PostInc_Pred_nv<string mnemonic, RegisterClass RC, - Operand ImmOp, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ST_PostInc_Pbase_nv<mnemonic, RC, ImmOp, PredNot, 0>; - // Predicate new - let Predicates = [HasV4T], validSubTargets = HasV4SubT in - defm _cdn#NAME : ST_PostInc_Pbase_nv<mnemonic, RC, ImmOp, PredNot, 1>; - } -} - -let hasCtrlDep = 1, isNVStore = 1, neverHasSideEffects = 1 in -multiclass ST_PostInc_nv<string mnemonic, string BaseOp, RegisterClass RC, - Operand ImmOp> { - - let BaseOpcode = "POST_"#BaseOp in { - let isPredicable = 1 in - def NAME#_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins IntRegs:$src1, ImmOp:$offset, RC:$src2), - mnemonic#"($src1++#$offset) = $src2.new", - [], - "$src1 = $dst">, - Requires<[HasV4T]>; - - let isPredicated = 1 in { - defm Pt : ST_PostInc_Pred_nv<mnemonic, RC, ImmOp, 0 >; - defm NotPt : ST_PostInc_Pred_nv<mnemonic, RC, ImmOp, 1 >; - } +let isNewValue = 1, mayStore = 1, isNVStore = 1, opNewValue = 3 in +class T_StorePI_RegNV <string mnemonic, bits<2> MajOp, MemAccessSize AccessSz> + : NVInstPI_V4 <(outs IntRegs:$_dst_), + (ins IntRegs:$src1, ModRegs:$src2, IntRegs:$src3), + #mnemonic#"($src1++$src2) = $src3.new", + [], "$src1 = $_dst_"> { + bits<5> src1; + bits<1> src2; + bits<3> src3; + let accessSize = AccessSz; + + let IClass = 0b1010; + + let Inst{27-21} = 0b1101101; + let Inst{20-16} = src1; + let Inst{13} = src2; + let Inst{12-11} = MajOp; + let Inst{10-8} = src3; + let Inst{7} = 0b0; } -} -let addrMode = PostInc, validSubTargets = HasV4SubT in { -defm POST_STbri: ST_PostInc_nv <"memb", "STrib", IntRegs, s4_0Imm>, AddrModeRel; -defm POST_SThri: ST_PostInc_nv <"memh", "STrih", IntRegs, s4_1Imm>, AddrModeRel; -defm POST_STwri: ST_PostInc_nv <"memw", "STriw", IntRegs, s4_2Imm>, AddrModeRel; +let isCodeGenOnly = 0 in { +def S2_storerbnew_pr : T_StorePI_RegNV<"memb", 0b00, ByteAccess>; +def S2_storerhnew_pr : T_StorePI_RegNV<"memh", 0b01, HalfWordAccess>; +def S2_storerinew_pr : T_StorePI_RegNV<"memw", 0b10, WordAccess>; } // memb(Rx++#s4:0:circ(Mu))=Nt.new @@ -1002,7 +1376,8 @@ defm POST_STwri: ST_PostInc_nv <"memw", "STriw", IntRegs, s4_2Imm>, AddrModeRel; // operands. //===----------------------------------------------------------------------===// -let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 11 in +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 11, + opExtentAlign = 2 in class NVJrr_template<string mnemonic, bits<3> majOp, bit NvOpNum, bit isNegCond, bit isTak> : NVInst_V4<(outs), @@ -1010,8 +1385,7 @@ class NVJrr_template<string mnemonic, bits<3> majOp, bit NvOpNum, "if ("#!if(isNegCond, "!","")#mnemonic# "($src1"#!if(!eq(NvOpNum, 0),".new, ",", ")# "$src2"#!if(!eq(NvOpNum, 1),".new))","))")#" jump:" - #!if(isTak, "t","nt")#" $offset", - []>, Requires<[HasV4T]> { + #!if(isTak, "t","nt")#" $offset", []> { bits<5> src1; bits<5> src2; @@ -1020,8 +1394,8 @@ class NVJrr_template<string mnemonic, bits<3> majOp, bit NvOpNum, bits<11> offset; let isTaken = isTak; - let isBrTaken = !if(isTaken, "true", "false"); let isPredicatedFalse = isNegCond; + let opNewValue{0} = NvOpNum; let Ns = !if(!eq(NvOpNum, 0), src1{2-0}, src2{2-0}); let RegOp = !if(!eq(NvOpNum, 0), src2, src1); @@ -1064,7 +1438,8 @@ multiclass NVJrr_base<string mnemonic, string BaseOp, bits<3> majOp, // if ([!]cmp.gtu(Rt,Ns.new)) jump:[n]t #r9:2 let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator = 1, - Defs = [PC], neverHasSideEffects = 1, validSubTargets = HasV4SubT in { + Defs = [PC], hasSideEffects = 0, validSubTargets = HasV4SubT, + isCodeGenOnly = 0 in { defm CMPEQrr : NVJrr_base<"cmp.eq", "CMPEQ", 0b000, 0>, PredRel; defm CMPGTrr : NVJrr_base<"cmp.gt", "CMPGT", 0b001, 0>, PredRel; defm CMPGTUrr : NVJrr_base<"cmp.gtu", "CMPGTU", 0b010, 0>, PredRel; @@ -1077,18 +1452,18 @@ let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator = 1, // with a register and an unsigned immediate (U5) operand. //===----------------------------------------------------------------------===// -let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 11 in +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 11, + opExtentAlign = 2 in class NVJri_template<string mnemonic, bits<3> majOp, bit isNegCond, bit isTak> : NVInst_V4<(outs), (ins IntRegs:$src1, u5Imm:$src2, brtarget:$offset), "if ("#!if(isNegCond, "!","")#mnemonic#"($src1.new, #$src2)) jump:" - #!if(isTak, "t","nt")#" $offset", - []>, Requires<[HasV4T]> { + #!if(isTak, "t","nt")#" $offset", []> { let isTaken = isTak; let isPredicatedFalse = isNegCond; - let isBrTaken = !if(isTaken, "true", "false"); + let isTaken = isTak; bits<3> src1; bits<5> src2; @@ -1124,7 +1499,8 @@ multiclass NVJri_base<string mnemonic, string BaseOp, bits<3> majOp> { // if ([!]cmp.gtu(Ns.new,#U5)) jump:[n]t #r9:2 let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator = 1, - Defs = [PC], neverHasSideEffects = 1, validSubTargets = HasV4SubT in { + Defs = [PC], hasSideEffects = 0, validSubTargets = HasV4SubT, + isCodeGenOnly = 0 in { defm CMPEQri : NVJri_base<"cmp.eq", "CMPEQ", 0b000>, PredRel; defm CMPGTri : NVJri_base<"cmp.gt", "CMPGT", 0b001>, PredRel; defm CMPGTUri : NVJri_base<"cmp.gtu", "CMPGTU", 0b010>, PredRel; @@ -1135,19 +1511,19 @@ let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator = 1, // with a register and an hardcoded 0/-1 immediate value. //===----------------------------------------------------------------------===// -let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 11 in +let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 11, + opExtentAlign = 2 in class NVJ_ConstImm_template<string mnemonic, bits<3> majOp, string ImmVal, bit isNegCond, bit isTak> : NVInst_V4<(outs), (ins IntRegs:$src1, brtarget:$offset), "if ("#!if(isNegCond, "!","")#mnemonic #"($src1.new, #"#ImmVal#")) jump:" - #!if(isTak, "t","nt")#" $offset", - []>, Requires<[HasV4T]> { + #!if(isTak, "t","nt")#" $offset", []> { let isTaken = isTak; let isPredicatedFalse = isNegCond; - let isBrTaken = !if(isTaken, "true", "false"); + let isTaken = isTak; bits<3> src1; bits<11> offset; @@ -1172,8 +1548,8 @@ multiclass NVJ_ConstImm_cond<string mnemonic, bits<3> majOp, string ImmVal, multiclass NVJ_ConstImm_base<string mnemonic, string BaseOp, bits<3> majOp, string ImmVal> { let BaseOpcode = BaseOp#_NVJ_ConstImm in { - defm _t_Jumpnv : NVJ_ConstImm_cond<mnemonic, majOp, ImmVal, 0>; // True cond - defm _f_Jumpnv : NVJ_ConstImm_cond<mnemonic, majOp, ImmVal, 1>; // False Cond + defm _t_Jumpnv : NVJ_ConstImm_cond<mnemonic, majOp, ImmVal, 0>; // True + defm _f_Jumpnv : NVJ_ConstImm_cond<mnemonic, majOp, ImmVal, 1>; // False } } @@ -1182,266 +1558,328 @@ multiclass NVJ_ConstImm_base<string mnemonic, string BaseOp, bits<3> majOp, // if ([!]cmp.gt(Ns.new,#-1)) jump:[n]t #r9:2 let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator=1, - Defs = [PC], neverHasSideEffects = 1 in { + Defs = [PC], hasSideEffects = 0, isCodeGenOnly = 0 in { defm TSTBIT0 : NVJ_ConstImm_base<"tstbit", "TSTBIT", 0b011, "0">, PredRel; defm CMPEQn1 : NVJ_ConstImm_base<"cmp.eq", "CMPEQ", 0b100, "-1">, PredRel; defm CMPGTn1 : NVJ_ConstImm_base<"cmp.gt", "CMPGT", 0b101, "-1">, PredRel; } +// J4_hintjumpr: Hint indirect conditional jump. +let isBranch = 1, isIndirectBranch = 1, hasSideEffects = 0, isCodeGenOnly = 0 in +def J4_hintjumpr: JRInst < + (outs), + (ins IntRegs:$Rs), + "hintjr($Rs)"> { + bits<5> Rs; + let IClass = 0b0101; + let Inst{27-21} = 0b0010101; + let Inst{20-16} = Rs; + } + //===----------------------------------------------------------------------===// -// XTYPE/ALU + +// NV/J - //===----------------------------------------------------------------------===// -// Add and accumulate. -// Rd=add(Rs,add(Ru,#s6)) -let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 6, -validSubTargets = HasV4SubT in -def ADDr_ADDri_V4 : MInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, s6Ext:$src3), - "$dst = add($src1, add($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (add (i32 IntRegs:$src1), (add (i32 IntRegs:$src2), - s6_16ExtPred:$src3)))]>, - Requires<[HasV4T]>; +//===----------------------------------------------------------------------===// +// CR + +//===----------------------------------------------------------------------===// -// Rd=add(Rs,sub(#s6,Ru)) -let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 6, -validSubTargets = HasV4SubT in -def ADDr_SUBri_V4 : MInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, s6Ext:$src2, IntRegs:$src3), - "$dst = add($src1, sub(#$src2, $src3))", - [(set (i32 IntRegs:$dst), - (add (i32 IntRegs:$src1), (sub s6_10ExtPred:$src2, - (i32 IntRegs:$src3))))]>, - Requires<[HasV4T]>; +// PC-relative add +let hasNewValue = 1, isExtendable = 1, opExtendable = 1, + isExtentSigned = 0, opExtentBits = 6, hasSideEffects = 0, + Uses = [PC], validSubTargets = HasV4SubT in +def C4_addipc : CRInst <(outs IntRegs:$Rd), (ins u6Ext:$u6), + "$Rd = add(pc, #$u6)", [], "", CR_tc_2_SLOT3 > { + bits<5> Rd; + bits<6> u6; + + let IClass = 0b0110; + let Inst{27-16} = 0b101001001001; + let Inst{12-7} = u6; + let Inst{4-0} = Rd; + } -// Generates the same instruction as ADDr_SUBri_V4 but matches different -// pattern. -// Rd=add(Rs,sub(#s6,Ru)) -let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 6, -validSubTargets = HasV4SubT in -def ADDri_SUBr_V4 : MInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, s6Ext:$src2, IntRegs:$src3), - "$dst = add($src1, sub(#$src2, $src3))", - [(set (i32 IntRegs:$dst), - (sub (add (i32 IntRegs:$src1), s6_10ExtPred:$src2), - (i32 IntRegs:$src3)))]>, - Requires<[HasV4T]>; -// Add or subtract doublewords with carry. -//TODO: -// Rdd=add(Rss,Rtt,Px):carry -//TODO: -// Rdd=sub(Rss,Rtt,Px):carry +let hasSideEffects = 0 in +class T_LOGICAL_3OP<string MnOp1, string MnOp2, bits<2> OpBits, bit IsNeg> + : CRInst<(outs PredRegs:$Pd), + (ins PredRegs:$Ps, PredRegs:$Pt, PredRegs:$Pu), + "$Pd = " # MnOp1 # "($Ps, " # MnOp2 # "($Pt, " # + !if (IsNeg,"!","") # "$Pu))", + [], "", CR_tc_2early_SLOT23> { + bits<2> Pd; + bits<2> Ps; + bits<2> Pt; + bits<2> Pu; + + let IClass = 0b0110; + let Inst{27-24} = 0b1011; + let Inst{23} = IsNeg; + let Inst{22-21} = OpBits; + let Inst{20} = 0b1; + let Inst{17-16} = Ps; + let Inst{13} = 0b0; + let Inst{9-8} = Pt; + let Inst{7-6} = Pu; + let Inst{1-0} = Pd; +} +let isCodeGenOnly = 0 in { +def C4_and_and : T_LOGICAL_3OP<"and", "and", 0b00, 0>; +def C4_and_or : T_LOGICAL_3OP<"and", "or", 0b01, 0>; +def C4_or_and : T_LOGICAL_3OP<"or", "and", 0b10, 0>; +def C4_or_or : T_LOGICAL_3OP<"or", "or", 0b11, 0>; +def C4_and_andn : T_LOGICAL_3OP<"and", "and", 0b00, 1>; +def C4_and_orn : T_LOGICAL_3OP<"and", "or", 0b01, 1>; +def C4_or_andn : T_LOGICAL_3OP<"or", "and", 0b10, 1>; +def C4_or_orn : T_LOGICAL_3OP<"or", "or", 0b11, 1>; +} -// Logical doublewords. -// Rdd=and(Rtt,~Rss) -let validSubTargets = HasV4SubT in -def ANDd_NOTd_V4 : MInst<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2), - "$dst = and($src1, ~$src2)", - [(set (i64 DoubleRegs:$dst), (and (i64 DoubleRegs:$src1), - (not (i64 DoubleRegs:$src2))))]>, - Requires<[HasV4T]>; +//===----------------------------------------------------------------------===// +// CR - +//===----------------------------------------------------------------------===// -// Rdd=or(Rtt,~Rss) -let validSubTargets = HasV4SubT in -def ORd_NOTd_V4 : MInst<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2), - "$dst = or($src1, ~$src2)", - [(set (i64 DoubleRegs:$dst), - (or (i64 DoubleRegs:$src1), (not (i64 DoubleRegs:$src2))))]>, - Requires<[HasV4T]>; +//===----------------------------------------------------------------------===// +// XTYPE/ALU + +//===----------------------------------------------------------------------===// +// Logical with-not instructions. +let validSubTargets = HasV4SubT, isCodeGenOnly = 0 in { + def A4_andnp : T_ALU64_logical<"and", 0b001, 1, 0, 1>; + def A4_ornp : T_ALU64_logical<"or", 0b011, 1, 0, 1>; +} -// Logical-logical doublewords. -// Rxx^=xor(Rss,Rtt) -let validSubTargets = HasV4SubT in -def XORd_XORdd: MInst_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2, DoubleRegs:$src3), - "$dst ^= xor($src2, $src3)", - [(set (i64 DoubleRegs:$dst), - (xor (i64 DoubleRegs:$src1), (xor (i64 DoubleRegs:$src2), - (i64 DoubleRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +let hasNewValue = 1, hasSideEffects = 0, isCodeGenOnly = 0 in +def S4_parity: ALU64Inst<(outs IntRegs:$Rd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = parity($Rs, $Rt)", [], "", ALU64_tc_2_SLOT23> { + bits<5> Rd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1101; + let Inst{27-21} = 0b0101111; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{4-0} = Rd; +} +// Add and accumulate. +// Rd=add(Rs,add(Ru,#s6)) +let isExtentSigned = 1, hasNewValue = 1, isExtendable = 1, opExtentBits = 6, + opExtendable = 3, isCodeGenOnly = 0 in +def S4_addaddi : ALU64Inst <(outs IntRegs:$Rd), + (ins IntRegs:$Rs, IntRegs:$Ru, s6Ext:$s6), + "$Rd = add($Rs, add($Ru, #$s6))" , + [(set (i32 IntRegs:$Rd), (add (i32 IntRegs:$Rs), + (add (i32 IntRegs:$Ru), s6_16ExtPred:$s6)))], + "", ALU64_tc_2_SLOT23> { + bits<5> Rd; + bits<5> Rs; + bits<5> Ru; + bits<6> s6; + + let IClass = 0b1101; + + let Inst{27-23} = 0b10110; + let Inst{22-21} = s6{5-4}; + let Inst{20-16} = Rs; + let Inst{13} = s6{3}; + let Inst{12-8} = Rd; + let Inst{7-5} = s6{2-0}; + let Inst{4-0} = Ru; + } +let isExtentSigned = 1, hasSideEffects = 0, hasNewValue = 1, isExtendable = 1, + opExtentBits = 6, opExtendable = 2, isCodeGenOnly = 0 in +def S4_subaddi: ALU64Inst <(outs IntRegs:$Rd), + (ins IntRegs:$Rs, s6Ext:$s6, IntRegs:$Ru), + "$Rd = add($Rs, sub(#$s6, $Ru))", + [], "", ALU64_tc_2_SLOT23> { + bits<5> Rd; + bits<5> Rs; + bits<6> s6; + bits<5> Ru; + + let IClass = 0b1101; + + let Inst{27-23} = 0b10111; + let Inst{22-21} = s6{5-4}; + let Inst{20-16} = Rs; + let Inst{13} = s6{3}; + let Inst{12-8} = Rd; + let Inst{7-5} = s6{2-0}; + let Inst{4-0} = Ru; + } + +// Extract bitfield +// Rdd=extract(Rss,#u6,#U6) +// Rdd=extract(Rss,Rtt) +// Rd=extract(Rs,Rtt) +// Rd=extract(Rs,#u5,#U5) + +let isCodeGenOnly = 0 in { +def S4_extractp_rp : T_S3op_64 < "extract", 0b11, 0b100, 0>; +def S4_extractp : T_S2op_extract <"extract", 0b1010, DoubleRegs, u6Imm>; +} -// Logical-logical words. -// Rx=or(Ru,and(Rx,#s10)) -let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 10, -validSubTargets = HasV4SubT in -def ORr_ANDri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, s10Ext:$src3), - "$dst = or($src1, and($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - s10ExtPred:$src3)))], - "$src2 = $dst">, - Requires<[HasV4T]>; +let hasNewValue = 1, isCodeGenOnly = 0 in { + def S4_extract_rp : T_S3op_extract<"extract", 0b01>; + def S4_extract : T_S2op_extract <"extract", 0b1101, IntRegs, u5Imm>; +} -// Rx[&|^]=and(Rs,Rt) -// Rx&=and(Rs,Rt) -let validSubTargets = HasV4SubT in -def ANDr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst &= and($src2, $src3)", - [(set (i32 IntRegs:$dst), - (and (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +let Itinerary = M_tc_3x_SLOT23, Defs = [USR_OVF], isCodeGenOnly = 0 in { + def M4_mac_up_s1_sat: T_MType_acc_rr<"+= mpy", 0b011, 0b000, 0, [], 0, 1, 1>; + def M4_nac_up_s1_sat: T_MType_acc_rr<"-= mpy", 0b011, 0b001, 0, [], 0, 1, 1>; +} -// Rx|=and(Rs,Rt) -let validSubTargets = HasV4SubT, CextOpcode = "ORr_ANDr", InputType = "reg" in -def ORr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst |= and($src2, $src3)", - [(set (i32 IntRegs:$dst), - (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>, ImmRegRel; +// Logical xor with xor accumulation. +// Rxx^=xor(Rss,Rtt) +let hasSideEffects = 0, isCodeGenOnly = 0 in +def M4_xor_xacc + : SInst <(outs DoubleRegs:$Rxx), + (ins DoubleRegs:$dst2, DoubleRegs:$Rss, DoubleRegs:$Rtt), + "$Rxx ^= xor($Rss, $Rtt)", + [(set (i64 DoubleRegs:$Rxx), + (xor (i64 DoubleRegs:$dst2), (xor (i64 DoubleRegs:$Rss), + (i64 DoubleRegs:$Rtt))))], + "$dst2 = $Rxx", S_3op_tc_1_SLOT23> { + bits<5> Rxx; + bits<5> Rss; + bits<5> Rtt; + + let IClass = 0b1100; + + let Inst{27-23} = 0b10101; + let Inst{20-16} = Rss; + let Inst{12-8} = Rtt; + let Inst{4-0} = Rxx; + } + +// Split bitfield +let isCodeGenOnly = 0 in +def A4_bitspliti : T_S2op_2_di <"bitsplit", 0b110, 0b100>; -// Rx^=and(Rs,Rt) -let validSubTargets = HasV4SubT in -def XORr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst ^= and($src2, $src3)", - [(set (i32 IntRegs:$dst), - (xor (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +// Arithmetic/Convergent round +let isCodeGenOnly = 0 in +def A4_cround_ri : T_S2op_2_ii <"cround", 0b111, 0b000>; -// Rx[&|^]=and(Rs,~Rt) -// Rx&=and(Rs,~Rt) -let validSubTargets = HasV4SubT in -def ANDr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst &= and($src2, ~$src3)", - [(set (i32 IntRegs:$dst), - (and (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - (not (i32 IntRegs:$src3)))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +let isCodeGenOnly = 0 in +def A4_round_ri : T_S2op_2_ii <"round", 0b111, 0b100>; -// Rx|=and(Rs,~Rt) -let validSubTargets = HasV4SubT in -def ORr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst |= and($src2, ~$src3)", - [(set (i32 IntRegs:$dst), - (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - (not (i32 IntRegs:$src3)))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +let Defs = [USR_OVF], isCodeGenOnly = 0 in +def A4_round_ri_sat : T_S2op_2_ii <"round", 0b111, 0b110, 1>; -// Rx^=and(Rs,~Rt) -let validSubTargets = HasV4SubT in -def XORr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst ^= and($src2, ~$src3)", - [(set (i32 IntRegs:$dst), - (xor (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - (not (i32 IntRegs:$src3)))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +// Logical-logical words. +// Compound or-and -- Rx=or(Ru,and(Rx,#s10)) +let isExtentSigned = 1, hasNewValue = 1, isExtendable = 1, opExtentBits = 10, + opExtendable = 3, isCodeGenOnly = 0 in +def S4_or_andix: + ALU64Inst<(outs IntRegs:$Rx), + (ins IntRegs:$Ru, IntRegs:$_src_, s10Ext:$s10), + "$Rx = or($Ru, and($_src_, #$s10))" , + [(set (i32 IntRegs:$Rx), + (or (i32 IntRegs:$Ru), (and (i32 IntRegs:$_src_), s10ExtPred:$s10)))] , + "$_src_ = $Rx", ALU64_tc_2_SLOT23> { + bits<5> Rx; + bits<5> Ru; + bits<10> s10; + + let IClass = 0b1101; + + let Inst{27-22} = 0b101001; + let Inst{20-16} = Rx; + let Inst{21} = s10{9}; + let Inst{13-5} = s10{8-0}; + let Inst{4-0} = Ru; + } -// Rx[&|^]=or(Rs,Rt) -// Rx&=or(Rs,Rt) -let validSubTargets = HasV4SubT in -def ANDr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst &= or($src2, $src3)", - [(set (i32 IntRegs:$dst), - (and (i32 IntRegs:$src1), (or (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +// Miscellaneous ALU64 instructions. +// +let hasNewValue = 1, hasSideEffects = 0, isCodeGenOnly = 0 in +def A4_modwrapu: ALU64Inst<(outs IntRegs:$Rd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = modwrap($Rs, $Rt)", [], "", ALU64_tc_2_SLOT23> { + bits<5> Rd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1101; + let Inst{27-21} = 0b0011111; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{7-5} = 0b111; + let Inst{4-0} = Rd; +} -// Rx|=or(Rs,Rt) -let validSubTargets = HasV4SubT, CextOpcode = "ORr_ORr", InputType = "reg" in -def ORr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst |= or($src2, $src3)", - [(set (i32 IntRegs:$dst), - (or (i32 IntRegs:$src1), (or (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>, ImmRegRel; +let hasSideEffects = 0, isCodeGenOnly = 0 in +def A4_bitsplit: ALU64Inst<(outs DoubleRegs:$Rd), + (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = bitsplit($Rs, $Rt)", [], "", ALU64_tc_1_SLOT23> { + bits<5> Rd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1101; + let Inst{27-24} = 0b0100; + let Inst{21} = 0b1; + let Inst{20-16} = Rs; + let Inst{12-8} = Rt; + let Inst{4-0} = Rd; +} -// Rx^=or(Rs,Rt) -let validSubTargets = HasV4SubT in -def XORr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst ^= or($src2, $src3)", - [(set (i32 IntRegs:$dst), - (xor (i32 IntRegs:$src1), (or (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +let isCodeGenOnly = 0 in { +// Rx[&|]=xor(Rs,Rt) +def M4_or_xor : T_MType_acc_rr < "|= xor", 0b110, 0b001, 0>; +def M4_and_xor : T_MType_acc_rr < "&= xor", 0b010, 0b010, 0>; -// Rx[&|^]=xor(Rs,Rt) -// Rx&=xor(Rs,Rt) -let validSubTargets = HasV4SubT in -def ANDr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst &= xor($src2, $src3)", - [(set (i32 IntRegs:$dst), - (and (i32 IntRegs:$src1), (xor (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +// Rx[&|^]=or(Rs,Rt) +def M4_xor_or : T_MType_acc_rr < "^= or", 0b110, 0b011, 0>; -// Rx|=xor(Rs,Rt) -let validSubTargets = HasV4SubT in -def ORr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst |= xor($src2, $src3)", - [(set (i32 IntRegs:$dst), - (and (i32 IntRegs:$src1), (xor (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +let CextOpcode = "ORr_ORr" in +def M4_or_or : T_MType_acc_rr < "|= or", 0b110, 0b000, 0>; +def M4_and_or : T_MType_acc_rr < "&= or", 0b010, 0b001, 0>; -// Rx^=xor(Rs,Rt) -let validSubTargets = HasV4SubT in -def XORr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), - "$dst ^= xor($src2, $src3)", - [(set (i32 IntRegs:$dst), - (and (i32 IntRegs:$src1), (xor (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +// Rx[&|^]=and(Rs,Rt) +def M4_xor_and : T_MType_acc_rr < "^= and", 0b110, 0b010, 0>; -// Rx|=and(Rs,#s10) -let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 10, -validSubTargets = HasV4SubT, CextOpcode = "ORr_ANDr", InputType = "imm" in -def ORr_ANDri2_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, s10Ext:$src3), - "$dst |= and($src2, #$src3)", - [(set (i32 IntRegs:$dst), - (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - s10ExtPred:$src3)))], - "$src1 = $dst">, - Requires<[HasV4T]>, ImmRegRel; +let CextOpcode = "ORr_ANDr" in +def M4_or_and : T_MType_acc_rr < "|= and", 0b010, 0b011, 0>; +def M4_and_and : T_MType_acc_rr < "&= and", 0b010, 0b000, 0>; -// Rx|=or(Rs,#s10) -let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 10, -validSubTargets = HasV4SubT, CextOpcode = "ORr_ORr", InputType = "imm" in -def ORr_ORri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, s10Ext:$src3), - "$dst |= or($src2, #$src3)", - [(set (i32 IntRegs:$dst), - (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - s10ExtPred:$src3)))], - "$src1 = $dst">, - Requires<[HasV4T]>, ImmRegRel; +// Rx[&|^]=and(Rs,~Rt) +def M4_xor_andn : T_MType_acc_rr < "^= and", 0b001, 0b010, 0, [], 1>; +def M4_or_andn : T_MType_acc_rr < "|= and", 0b001, 0b000, 0, [], 1>; +def M4_and_andn : T_MType_acc_rr < "&= and", 0b001, 0b001, 0, [], 1>; +} + +// Compound or-or and or-and +let isExtentSigned = 1, InputType = "imm", hasNewValue = 1, isExtendable = 1, + opExtentBits = 10, opExtendable = 3 in +class T_CompOR <string mnemonic, bits<2> MajOp, SDNode OpNode> + : MInst_acc <(outs IntRegs:$Rx), + (ins IntRegs:$src1, IntRegs:$Rs, s10Ext:$s10), + "$Rx |= "#mnemonic#"($Rs, #$s10)", + [(set (i32 IntRegs:$Rx), (or (i32 IntRegs:$src1), + (OpNode (i32 IntRegs:$Rs), s10ExtPred:$s10)))], + "$src1 = $Rx", ALU64_tc_2_SLOT23>, ImmRegRel { + bits<5> Rx; + bits<5> Rs; + bits<10> s10; + + let IClass = 0b1101; + + let Inst{27-24} = 0b1010; + let Inst{23-22} = MajOp; + let Inst{20-16} = Rs; + let Inst{21} = s10{9}; + let Inst{13-5} = s10{8-0}; + let Inst{4-0} = Rx; + } +let CextOpcode = "ORr_ANDr", isCodeGenOnly = 0 in +def S4_or_andi : T_CompOR <"and", 0b00, and>; + +let CextOpcode = "ORr_ORr", isCodeGenOnly = 0 in +def S4_or_ori : T_CompOR <"or", 0b10, or>; // Modulo wrap // Rd=modwrap(Rs,Rt) @@ -1480,79 +1918,229 @@ def ORr_ORri_V4 : MInst_acc<(outs IntRegs:$dst), // XTYPE/ALU - //===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// XTYPE/BIT + +//===----------------------------------------------------------------------===// + +// Bit reverse +let isCodeGenOnly = 0 in +def S2_brevp : T_S2op_3 <"brev", 0b11, 0b110>; + +// Bit count +let isCodeGenOnly = 0 in { +def S2_ct0p : T_COUNT_LEADING_64<"ct0", 0b111, 0b010>; +def S2_ct1p : T_COUNT_LEADING_64<"ct1", 0b111, 0b100>; +def S4_clbpnorm : T_COUNT_LEADING_64<"normamt", 0b011, 0b000>; +} + +def: Pat<(i32 (trunc (cttz (i64 DoubleRegs:$Rss)))), + (S2_ct0p (i64 DoubleRegs:$Rss))>; +def: Pat<(i32 (trunc (cttz (not (i64 DoubleRegs:$Rss))))), + (S2_ct1p (i64 DoubleRegs:$Rss))>; + +let hasSideEffects = 0, hasNewValue = 1, isCodeGenOnly = 0 in +def S4_clbaddi : SInst<(outs IntRegs:$Rd), (ins IntRegs:$Rs, s6Imm:$s6), + "$Rd = add(clb($Rs), #$s6)", [], "", S_2op_tc_2_SLOT23> { + bits<5> Rs; + bits<5> Rd; + bits<6> s6; + let IClass = 0b1000; + let Inst{27-24} = 0b1100; + let Inst{23-21} = 0b001; + let Inst{20-16} = Rs; + let Inst{13-8} = s6; + let Inst{7-5} = 0b000; + let Inst{4-0} = Rd; +} + +let hasSideEffects = 0, hasNewValue = 1, isCodeGenOnly = 0 in +def S4_clbpaddi : SInst<(outs IntRegs:$Rd), (ins DoubleRegs:$Rs, s6Imm:$s6), + "$Rd = add(clb($Rs), #$s6)", [], "", S_2op_tc_2_SLOT23> { + bits<5> Rs; + bits<5> Rd; + bits<6> s6; + let IClass = 0b1000; + let Inst{27-24} = 0b1000; + let Inst{23-21} = 0b011; + let Inst{20-16} = Rs; + let Inst{13-8} = s6; + let Inst{7-5} = 0b010; + let Inst{4-0} = Rd; +} + + +// Bit test/set/clear +let isCodeGenOnly = 0 in { +def S4_ntstbit_i : T_TEST_BIT_IMM<"!tstbit", 0b001>; +def S4_ntstbit_r : T_TEST_BIT_REG<"!tstbit", 1>; +} + +let AddedComplexity = 20 in { // Complexity greater than cmp reg-imm. + def: Pat<(i1 (seteq (and (shl 1, u5ImmPred:$u5), (i32 IntRegs:$Rs)), 0)), + (S4_ntstbit_i (i32 IntRegs:$Rs), u5ImmPred:$u5)>; + def: Pat<(i1 (seteq (and (shl 1, (i32 IntRegs:$Rt)), (i32 IntRegs:$Rs)), 0)), + (S4_ntstbit_r (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))>; +} + +// Add extra complexity to prefer these instructions over bitsset/bitsclr. +// The reason is that tstbit/ntstbit can be folded into a compound instruction: +// if ([!]tstbit(...)) jump ... +let AddedComplexity = 100 in +def: Pat<(i1 (setne (and (i32 IntRegs:$Rs), (i32 Set5ImmPred:$u5)), (i32 0))), + (S2_tstbit_i (i32 IntRegs:$Rs), (BITPOS32 Set5ImmPred:$u5))>; + +let AddedComplexity = 100 in +def: Pat<(i1 (seteq (and (i32 IntRegs:$Rs), (i32 Set5ImmPred:$u5)), (i32 0))), + (S4_ntstbit_i (i32 IntRegs:$Rs), (BITPOS32 Set5ImmPred:$u5))>; + +let isCodeGenOnly = 0 in { +def C4_nbitsset : T_TEST_BITS_REG<"!bitsset", 0b01, 1>; +def C4_nbitsclr : T_TEST_BITS_REG<"!bitsclr", 0b10, 1>; +def C4_nbitsclri : T_TEST_BITS_IMM<"!bitsclr", 0b10, 1>; +} + +// Do not increase complexity of these patterns. In the DAG, "cmp i8" may be +// represented as a compare against "value & 0xFF", which is an exact match +// for cmpb (same for cmph). The patterns below do not contain any additional +// complexity that would make them preferable, and if they were actually used +// instead of cmpb/cmph, they would result in a compare against register that +// is loaded with the byte/half mask (i.e. 0xFF or 0xFFFF). +def: Pat<(i1 (setne (and I32:$Rs, u6ImmPred:$u6), 0)), + (C4_nbitsclri I32:$Rs, u6ImmPred:$u6)>; +def: Pat<(i1 (setne (and I32:$Rs, I32:$Rt), 0)), + (C4_nbitsclr I32:$Rs, I32:$Rt)>; +def: Pat<(i1 (setne (and I32:$Rs, I32:$Rt), I32:$Rt)), + (C4_nbitsset I32:$Rs, I32:$Rt)>; + +//===----------------------------------------------------------------------===// +// XTYPE/BIT - +//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // XTYPE/MPY + //===----------------------------------------------------------------------===// -// Multiply and user lower result. -// Rd=add(#u6,mpyi(Rs,#U6)) -let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 6, -validSubTargets = HasV4SubT in -def ADDi_MPYri_V4 : MInst<(outs IntRegs:$dst), - (ins u6Ext:$src1, IntRegs:$src2, u6Imm:$src3), - "$dst = add(#$src1, mpyi($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (add (mul (i32 IntRegs:$src2), u6ImmPred:$src3), - u6ExtPred:$src1))]>, - Requires<[HasV4T]>; +// Rd=add(#u6,mpyi(Rs,#U6)) -- Multiply by immed and add immed. + +let hasNewValue = 1, isExtendable = 1, opExtentBits = 6, opExtendable = 1, + isCodeGenOnly = 0 in +def M4_mpyri_addi : MInst<(outs IntRegs:$Rd), + (ins u6Ext:$u6, IntRegs:$Rs, u6Imm:$U6), + "$Rd = add(#$u6, mpyi($Rs, #$U6))" , + [(set (i32 IntRegs:$Rd), + (add (mul (i32 IntRegs:$Rs), u6ImmPred:$U6), + u6ExtPred:$u6))] ,"",ALU64_tc_3x_SLOT23> { + bits<5> Rd; + bits<6> u6; + bits<5> Rs; + bits<6> U6; + + let IClass = 0b1101; + + let Inst{27-24} = 0b1000; + let Inst{23} = U6{5}; + let Inst{22-21} = u6{5-4}; + let Inst{20-16} = Rs; + let Inst{13} = u6{3}; + let Inst{12-8} = Rd; + let Inst{7-5} = u6{2-0}; + let Inst{4-0} = U6{4-0}; + } + +// Rd=add(#u6,mpyi(Rs,Rt)) +let CextOpcode = "ADD_MPY", InputType = "imm", hasNewValue = 1, + isExtendable = 1, opExtentBits = 6, opExtendable = 1, isCodeGenOnly = 0 in +def M4_mpyrr_addi : MInst <(outs IntRegs:$Rd), + (ins u6Ext:$u6, IntRegs:$Rs, IntRegs:$Rt), + "$Rd = add(#$u6, mpyi($Rs, $Rt))" , + [(set (i32 IntRegs:$Rd), + (add (mul (i32 IntRegs:$Rs), (i32 IntRegs:$Rt)), u6ExtPred:$u6))], + "", ALU64_tc_3x_SLOT23>, ImmRegRel { + bits<5> Rd; + bits<6> u6; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1101; + + let Inst{27-23} = 0b01110; + let Inst{22-21} = u6{5-4}; + let Inst{20-16} = Rs; + let Inst{13} = u6{3}; + let Inst{12-8} = Rt; + let Inst{7-5} = u6{2-0}; + let Inst{4-0} = Rd; + } + +let hasNewValue = 1 in +class T_AddMpy <bit MajOp, PatLeaf ImmPred, dag ins> + : ALU64Inst <(outs IntRegs:$dst), ins, + "$dst = add($src1, mpyi("#!if(MajOp,"$src3, #$src2))", + "#$src2, $src3))"), + [(set (i32 IntRegs:$dst), + (add (i32 IntRegs:$src1), (mul (i32 IntRegs:$src3), ImmPred:$src2)))], + "", ALU64_tc_3x_SLOT23> { + bits<5> dst; + bits<5> src1; + bits<8> src2; + bits<5> src3; + + let IClass = 0b1101; + + bits<6> ImmValue = !if(MajOp, src2{5-0}, src2{7-2}); + + let Inst{27-24} = 0b1111; + let Inst{23} = MajOp; + let Inst{22-21} = ImmValue{5-4}; + let Inst{20-16} = src3; + let Inst{13} = ImmValue{3}; + let Inst{12-8} = dst; + let Inst{7-5} = ImmValue{2-0}; + let Inst{4-0} = src1; + } + +let isCodeGenOnly = 0 in +def M4_mpyri_addr_u2 : T_AddMpy<0b0, u6_2ImmPred, + (ins IntRegs:$src1, u6_2Imm:$src2, IntRegs:$src3)>; + +let isExtendable = 1, opExtentBits = 6, opExtendable = 3, + CextOpcode = "ADD_MPY", InputType = "imm", isCodeGenOnly = 0 in +def M4_mpyri_addr : T_AddMpy<0b1, u6ExtPred, + (ins IntRegs:$src1, IntRegs:$src3, u6Ext:$src2)>, ImmRegRel; + +// Rx=add(Ru,mpyi(Rx,Rs)) +let validSubTargets = HasV4SubT, CextOpcode = "ADD_MPY", InputType = "reg", + hasNewValue = 1, isCodeGenOnly = 0 in +def M4_mpyrr_addr: MInst_acc <(outs IntRegs:$Rx), + (ins IntRegs:$Ru, IntRegs:$_src_, IntRegs:$Rs), + "$Rx = add($Ru, mpyi($_src_, $Rs))", + [(set (i32 IntRegs:$Rx), (add (i32 IntRegs:$Ru), + (mul (i32 IntRegs:$_src_), (i32 IntRegs:$Rs))))], + "$_src_ = $Rx", M_tc_3x_SLOT23>, ImmRegRel { + bits<5> Rx; + bits<5> Ru; + bits<5> Rs; + + let IClass = 0b1110; + + let Inst{27-21} = 0b0011000; + let Inst{12-8} = Rx; + let Inst{4-0} = Ru; + let Inst{20-16} = Rs; + } // Rd=add(##,mpyi(Rs,#U6)) def : Pat <(add (mul (i32 IntRegs:$src2), u6ImmPred:$src3), (HexagonCONST32 tglobaladdr:$src1)), - (i32 (ADDi_MPYri_V4 tglobaladdr:$src1, IntRegs:$src2, + (i32 (M4_mpyri_addi tglobaladdr:$src1, IntRegs:$src2, u6ImmPred:$src3))>; -// Rd=add(#u6,mpyi(Rs,Rt)) -let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 6, -validSubTargets = HasV4SubT, InputType = "imm", CextOpcode = "ADD_MPY" in -def ADDi_MPYrr_V4 : MInst<(outs IntRegs:$dst), - (ins u6Ext:$src1, IntRegs:$src2, IntRegs:$src3), - "$dst = add(#$src1, mpyi($src2, $src3))", - [(set (i32 IntRegs:$dst), - (add (mul (i32 IntRegs:$src2), (i32 IntRegs:$src3)), - u6ExtPred:$src1))]>, - Requires<[HasV4T]>, ImmRegRel; - // Rd=add(##,mpyi(Rs,Rt)) def : Pat <(add (mul (i32 IntRegs:$src2), (i32 IntRegs:$src3)), (HexagonCONST32 tglobaladdr:$src1)), - (i32 (ADDi_MPYrr_V4 tglobaladdr:$src1, IntRegs:$src2, + (i32 (M4_mpyrr_addi tglobaladdr:$src1, IntRegs:$src2, IntRegs:$src3))>; -// Rd=add(Ru,mpyi(#u6:2,Rs)) -let validSubTargets = HasV4SubT in -def ADDr_MPYir_V4 : MInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, u6Imm:$src2, IntRegs:$src3), - "$dst = add($src1, mpyi(#$src2, $src3))", - [(set (i32 IntRegs:$dst), - (add (i32 IntRegs:$src1), (mul (i32 IntRegs:$src3), - u6_2ImmPred:$src2)))]>, - Requires<[HasV4T]>; - -// Rd=add(Ru,mpyi(Rs,#u6)) -let isExtendable = 1, opExtendable = 3, isExtentSigned = 0, opExtentBits = 6, -validSubTargets = HasV4SubT, InputType = "imm", CextOpcode = "ADD_MPY" in -def ADDr_MPYri_V4 : MInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u6Ext:$src3), - "$dst = add($src1, mpyi($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (add (i32 IntRegs:$src1), (mul (i32 IntRegs:$src2), - u6ExtPred:$src3)))]>, - Requires<[HasV4T]>, ImmRegRel; - -// Rx=add(Ru,mpyi(Rx,Rs)) -let validSubTargets = HasV4SubT, InputType = "reg", CextOpcode = "ADD_MPY" in -def ADDr_MPYrr_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "$dst = add($src1, mpyi($src2, $src3))", - [(set (i32 IntRegs:$dst), - (add (i32 IntRegs:$src1), (mul (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))], - "$src2 = $dst">, - Requires<[HasV4T]>, ImmRegRel; - - // Polynomial multiply words // Rdd=pmpyw(Rs,Rt) // Rxx^=pmpyw(Rs,Rt) @@ -1590,159 +2178,115 @@ def ADDr_MPYrr_V4 : MInst_acc<(outs IntRegs:$dst), //===----------------------------------------------------------------------===// // XTYPE/SHIFT + //===----------------------------------------------------------------------===// - -// Shift by immediate and accumulate. -// Rx=add(#u8,asl(Rx,#U5)) -let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, -validSubTargets = HasV4SubT in -def ADDi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), - "$dst = add(#$src1, asl($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (add (shl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ExtPred:$src1))], - "$src2 = $dst">, - Requires<[HasV4T]>; - -// Rx=add(#u8,lsr(Rx,#U5)) -let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, -validSubTargets = HasV4SubT in -def ADDi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), - "$dst = add(#$src1, lsr($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (add (srl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ExtPred:$src1))], - "$src2 = $dst">, - Requires<[HasV4T]>; - -// Rx=sub(#u8,asl(Rx,#U5)) -let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, -validSubTargets = HasV4SubT in -def SUBi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), - "$dst = sub(#$src1, asl($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (sub (shl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ExtPred:$src1))], - "$src2 = $dst">, - Requires<[HasV4T]>; - -// Rx=sub(#u8,lsr(Rx,#U5)) -let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, -validSubTargets = HasV4SubT in -def SUBi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), - "$dst = sub(#$src1, lsr($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (sub (srl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ExtPred:$src1))], - "$src2 = $dst">, - Requires<[HasV4T]>; - - -//Shift by immediate and logical. -//Rx=and(#u8,asl(Rx,#U5)) -let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, -validSubTargets = HasV4SubT in -def ANDi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), - "$dst = and(#$src1, asl($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (and (shl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ExtPred:$src1))], - "$src2 = $dst">, - Requires<[HasV4T]>; - -//Rx=and(#u8,lsr(Rx,#U5)) +// Shift by immediate and accumulate/logical. +// Rx=add(#u8,asl(Rx,#U5)) Rx=add(#u8,lsr(Rx,#U5)) +// Rx=sub(#u8,asl(Rx,#U5)) Rx=sub(#u8,lsr(Rx,#U5)) +// Rx=and(#u8,asl(Rx,#U5)) Rx=and(#u8,lsr(Rx,#U5)) +// Rx=or(#u8,asl(Rx,#U5)) Rx=or(#u8,lsr(Rx,#U5)) let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, -validSubTargets = HasV4SubT in -def ANDi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), - "$dst = and(#$src1, lsr($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (and (srl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ExtPred:$src1))], - "$src2 = $dst">, - Requires<[HasV4T]>; - -//Rx=or(#u8,asl(Rx,#U5)) -let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, -AddedComplexity = 30, validSubTargets = HasV4SubT in -def ORi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), - "$dst = or(#$src1, asl($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (or (shl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ExtPred:$src1))], - "$src2 = $dst">, - Requires<[HasV4T]>; + hasNewValue = 1, opNewValue = 0, validSubTargets = HasV4SubT in +class T_S4_ShiftOperate<string MnOp, string MnSh, SDNode Op, SDNode Sh, + bit asl_lsr, bits<2> MajOp, InstrItinClass Itin> + : MInst_acc<(outs IntRegs:$Rd), (ins u8Ext:$u8, IntRegs:$Rx, u5Imm:$U5), + "$Rd = "#MnOp#"(#$u8, "#MnSh#"($Rx, #$U5))", + [(set (i32 IntRegs:$Rd), + (Op (Sh I32:$Rx, u5ImmPred:$U5), u8ExtPred:$u8))], + "$Rd = $Rx", Itin> { + + bits<5> Rd; + bits<8> u8; + bits<5> Rx; + bits<5> U5; + + let IClass = 0b1101; + let Inst{27-24} = 0b1110; + let Inst{23-21} = u8{7-5}; + let Inst{20-16} = Rd; + let Inst{13} = u8{4}; + let Inst{12-8} = U5; + let Inst{7-5} = u8{3-1}; + let Inst{4} = asl_lsr; + let Inst{3} = u8{0}; + let Inst{2-1} = MajOp; +} -//Rx=or(#u8,lsr(Rx,#U5)) -let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, -AddedComplexity = 30, validSubTargets = HasV4SubT in -def ORi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), - "$dst = or(#$src1, lsr($src2, #$src3))", - [(set (i32 IntRegs:$dst), - (or (srl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ExtPred:$src1))], - "$src2 = $dst">, - Requires<[HasV4T]>; +multiclass T_ShiftOperate<string mnemonic, SDNode Op, bits<2> MajOp, + InstrItinClass Itin> { + def _asl_ri : T_S4_ShiftOperate<mnemonic, "asl", Op, shl, 0, MajOp, Itin>; + def _lsr_ri : T_S4_ShiftOperate<mnemonic, "lsr", Op, srl, 1, MajOp, Itin>; +} +let AddedComplexity = 200, isCodeGenOnly = 0 in { + defm S4_addi : T_ShiftOperate<"add", add, 0b10, ALU64_tc_2_SLOT23>; + defm S4_andi : T_ShiftOperate<"and", and, 0b00, ALU64_tc_2_SLOT23>; +} -//Shift by register. -//Rd=lsl(#s6,Rt) -let validSubTargets = HasV4SubT in { -def LSLi_V4 : MInst<(outs IntRegs:$dst), (ins s6Imm:$src1, IntRegs:$src2), - "$dst = lsl(#$src1, $src2)", - [(set (i32 IntRegs:$dst), (shl s6ImmPred:$src1, - (i32 IntRegs:$src2)))]>, - Requires<[HasV4T]>; +let AddedComplexity = 30, isCodeGenOnly = 0 in +defm S4_ori : T_ShiftOperate<"or", or, 0b01, ALU64_tc_1_SLOT23>; +let isCodeGenOnly = 0 in +defm S4_subi : T_ShiftOperate<"sub", sub, 0b11, ALU64_tc_1_SLOT23>; -//Shift by register and logical. -//Rxx^=asl(Rss,Rt) -def ASLd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3), - "$dst ^= asl($src2, $src3)", - [(set (i64 DoubleRegs:$dst), - (xor (i64 DoubleRegs:$src1), (shl (i64 DoubleRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; -//Rxx^=asr(Rss,Rt) -def ASRd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3), - "$dst ^= asr($src2, $src3)", - [(set (i64 DoubleRegs:$dst), - (xor (i64 DoubleRegs:$src1), (sra (i64 DoubleRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +// Rd=[cround|round](Rs,Rt) +let hasNewValue = 1, Itinerary = S_3op_tc_2_SLOT23, isCodeGenOnly = 0 in { + def A4_cround_rr : T_S3op_3 < "cround", IntRegs, 0b11, 0b00>; + def A4_round_rr : T_S3op_3 < "round", IntRegs, 0b11, 0b10>; +} -//Rxx^=lsl(Rss,Rt) -def LSLd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3), - "$dst ^= lsl($src2, $src3)", - [(set (i64 DoubleRegs:$dst), (xor (i64 DoubleRegs:$src1), - (shl (i64 DoubleRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +// Rd=round(Rs,Rt):sat +let hasNewValue = 1, Defs = [USR_OVF], Itinerary = S_3op_tc_2_SLOT23, + isCodeGenOnly = 0 in +def A4_round_rr_sat : T_S3op_3 < "round", IntRegs, 0b11, 0b11, 1>; + +// Rdd=[add|sub](Rss,Rtt,Px):carry +let isPredicateLate = 1, hasSideEffects = 0 in +class T_S3op_carry <string mnemonic, bits<3> MajOp> + : SInst < (outs DoubleRegs:$Rdd, PredRegs:$Px), + (ins DoubleRegs:$Rss, DoubleRegs:$Rtt, PredRegs:$Pu), + "$Rdd = "#mnemonic#"($Rss, $Rtt, $Pu):carry", + [], "$Px = $Pu", S_3op_tc_1_SLOT23 > { + bits<5> Rdd; + bits<5> Rss; + bits<5> Rtt; + bits<2> Pu; + + let IClass = 0b1100; + + let Inst{27-24} = 0b0010; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rss; + let Inst{12-8} = Rtt; + let Inst{6-5} = Pu; + let Inst{4-0} = Rdd; + } -//Rxx^=lsr(Rss,Rt) -def LSRd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3), - "$dst ^= lsr($src2, $src3)", - [(set (i64 DoubleRegs:$dst), - (xor (i64 DoubleRegs:$src1), (srl (i64 DoubleRegs:$src2), - (i32 IntRegs:$src3))))], - "$src1 = $dst">, - Requires<[HasV4T]>; +let isCodeGenOnly = 0 in { +def A4_addp_c : T_S3op_carry < "add", 0b110 >; +def A4_subp_c : T_S3op_carry < "sub", 0b111 >; } +// Shift an immediate left by register amount. +let hasNewValue = 1, hasSideEffects = 0, isCodeGenOnly = 0 in +def S4_lsli: SInst <(outs IntRegs:$Rd), (ins s6Imm:$s6, IntRegs:$Rt), + "$Rd = lsl(#$s6, $Rt)" , + [(set (i32 IntRegs:$Rd), (shl s6ImmPred:$s6, + (i32 IntRegs:$Rt)))], + "", S_3op_tc_1_SLOT23> { + bits<5> Rd; + bits<6> s6; + bits<5> Rt; + + let IClass = 0b1100; + + let Inst{27-22} = 0b011010; + let Inst{20-16} = s6{5-1}; + let Inst{12-8} = Rt; + let Inst{7-6} = 0b11; + let Inst{4-0} = Rd; + let Inst{5} = s6{0}; + } + //===----------------------------------------------------------------------===// // XTYPE/SHIFT - //===----------------------------------------------------------------------===// @@ -1830,7 +2374,7 @@ class MemOp_rr_base <string opc, bits<2> opcBits, Operand ImmOp, (ins IntRegs:$base, ImmOp:$offset, IntRegs:$delta), opc#"($base+#$offset)"#memOp#"$delta", []>, - Requires<[HasV4T, UseMEMOP]> { + Requires<[UseMEMOP]> { bits<5> base; bits<5> delta; @@ -1841,6 +2385,7 @@ class MemOp_rr_base <string opc, bits<2> opcBits, Operand ImmOp, !if (!eq(opcBits, 0b01), offset{6-1}, !if (!eq(opcBits, 0b10), offset{7-2},0))); + let opExtentAlign = opcBits; let IClass = 0b0011; let Inst{27-24} = 0b1110; let Inst{22-21} = opcBits; @@ -1861,7 +2406,7 @@ class MemOp_ri_base <string opc, bits<2> opcBits, Operand ImmOp, opc#"($base+#$offset)"#memOp#"#$delta" #!if(memOpBits{1},")", ""), // clrbit, setbit - include ')' []>, - Requires<[HasV4T, UseMEMOP]> { + Requires<[UseMEMOP]> { bits<5> base; bits<5> delta; @@ -1872,6 +2417,7 @@ class MemOp_ri_base <string opc, bits<2> opcBits, Operand ImmOp, !if (!eq(opcBits, 0b01), offset{6-1}, !if (!eq(opcBits, 0b10), offset{7-2},0))); + let opExtentAlign = opcBits; let IClass = 0b0011; let Inst{27-24} = 0b1111; let Inst{22-21} = opcBits; @@ -1884,36 +2430,36 @@ class MemOp_ri_base <string opc, bits<2> opcBits, Operand ImmOp, // multiclass to define MemOp instructions with register operand. multiclass MemOp_rr<string opc, bits<2> opcBits, Operand ImmOp> { - def _ADD#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " += ", 0b00>; // add - def _SUB#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " -= ", 0b01>; // sub - def _AND#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " &= ", 0b10>; // and - def _OR#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " |= ", 0b11>; // or + def L4_add#NAME : MemOp_rr_base <opc, opcBits, ImmOp, " += ", 0b00>; // add + def L4_sub#NAME : MemOp_rr_base <opc, opcBits, ImmOp, " -= ", 0b01>; // sub + def L4_and#NAME : MemOp_rr_base <opc, opcBits, ImmOp, " &= ", 0b10>; // and + def L4_or#NAME : MemOp_rr_base <opc, opcBits, ImmOp, " |= ", 0b11>; // or } // multiclass to define MemOp instructions with immediate Operand. multiclass MemOp_ri<string opc, bits<2> opcBits, Operand ImmOp> { - def _ADD#NAME#_V4 : MemOp_ri_base <opc, opcBits, ImmOp, " += ", 0b00 >; - def _SUB#NAME#_V4 : MemOp_ri_base <opc, opcBits, ImmOp, " -= ", 0b01 >; - def _CLRBIT#NAME#_V4 : MemOp_ri_base<opc, opcBits, ImmOp, " =clrbit(", 0b10>; - def _SETBIT#NAME#_V4 : MemOp_ri_base<opc, opcBits, ImmOp, " =setbit(", 0b11>; + def L4_iadd#NAME : MemOp_ri_base <opc, opcBits, ImmOp, " += ", 0b00 >; + def L4_isub#NAME : MemOp_ri_base <opc, opcBits, ImmOp, " -= ", 0b01 >; + def L4_iand#NAME : MemOp_ri_base<opc, opcBits, ImmOp, " = clrbit(", 0b10>; + def L4_ior#NAME : MemOp_ri_base<opc, opcBits, ImmOp, " = setbit(", 0b11>; } multiclass MemOp_base <string opc, bits<2> opcBits, Operand ImmOp> { - defm r : MemOp_rr <opc, opcBits, ImmOp>; - defm i : MemOp_ri <opc, opcBits, ImmOp>; + defm _#NAME : MemOp_rr <opc, opcBits, ImmOp>; + defm _#NAME : MemOp_ri <opc, opcBits, ImmOp>; } // Define MemOp instructions. let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, -validSubTargets =HasV4SubT in { - let opExtentBits = 6, accessSize = ByteAccess in - defm MemOPb : MemOp_base <"memb", 0b00, u6_0Ext>; + validSubTargets =HasV4SubT in { + let opExtentBits = 6, accessSize = ByteAccess, isCodeGenOnly = 0 in + defm memopb_io : MemOp_base <"memb", 0b00, u6_0Ext>; - let opExtentBits = 7, accessSize = HalfWordAccess in - defm MemOPh : MemOp_base <"memh", 0b01, u6_1Ext>; + let opExtentBits = 7, accessSize = HalfWordAccess, isCodeGenOnly = 0 in + defm memoph_io : MemOp_base <"memh", 0b01, u6_1Ext>; - let opExtentBits = 8, accessSize = WordAccess in - defm MemOPw : MemOp_base <"memw", 0b10, u6_2Ext>; + let opExtentBits = 8, accessSize = WordAccess, isCodeGenOnly = 0 in + defm memopw_io : MemOp_base <"memw", 0b10, u6_2Ext>; } //===----------------------------------------------------------------------===// @@ -1946,10 +2492,10 @@ multiclass MemOpi_u5ALUOp<PatFrag ldOp, PatFrag stOp, PatLeaf ExtPred, multiclass MemOpi_u5ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > { // Half Word defm : MemOpi_u5ALUOp <ldOpHalf, truncstorei16, u6_1ExtPred, - MemOPh_ADDi_V4, MemOPh_SUBi_V4>; + L4_iadd_memoph_io, L4_isub_memoph_io>; // Byte defm : MemOpi_u5ALUOp <ldOpByte, truncstorei8, u6ExtPred, - MemOPb_ADDi_V4, MemOPb_SUBi_V4>; + L4_iadd_memopb_io, L4_isub_memopb_io>; } let Predicates = [HasV4T, UseMEMOP] in { @@ -1958,8 +2504,8 @@ let Predicates = [HasV4T, UseMEMOP] in { defm : MemOpi_u5ExtType<extloadi8, extloadi16>; // any extend // Word - defm : MemOpi_u5ALUOp <load, store, u6_2ExtPred, MemOPw_ADDi_V4, - MemOPw_SUBi_V4>; + defm : MemOpi_u5ALUOp <load, store, u6_2ExtPred, L4_iadd_memopw_io, + L4_isub_memopw_io>; } //===----------------------------------------------------------------------===// @@ -1987,10 +2533,10 @@ multiclass MemOpi_m5Pats <PatFrag ldOp, PatFrag stOp, PatLeaf extPred, multiclass MemOpi_m5ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > { // Half Word defm : MemOpi_m5Pats <ldOpHalf, truncstorei16, u6_1ExtPred, m5HImmPred, - ADDRriU6_1, MEMOPIMM_HALF, MemOPh_SUBi_V4>; + ADDRriU6_1, MEMOPIMM_HALF, L4_isub_memoph_io>; // Byte defm : MemOpi_m5Pats <ldOpByte, truncstorei8, u6ExtPred, m5BImmPred, - ADDRriU6_0, MEMOPIMM_BYTE, MemOPb_SUBi_V4>; + ADDRriU6_0, MEMOPIMM_BYTE, L4_isub_memopb_io>; } let Predicates = [HasV4T, UseMEMOP] in { @@ -2000,7 +2546,7 @@ let Predicates = [HasV4T, UseMEMOP] in { // Word defm : MemOpi_m5Pats <load, store, u6_2ExtPred, m5ImmPred, - ADDRriU6_2, MEMOPIMM, MemOPw_SUBi_V4>; + ADDRriU6_2, MEMOPIMM, L4_isub_memopw_io>; } //===----------------------------------------------------------------------===// @@ -2031,16 +2577,16 @@ multiclass MemOpi_bitPats <PatFrag ldOp, PatFrag stOp, PatLeaf immPred, multiclass MemOpi_bitExtType<PatFrag ldOpByte, PatFrag ldOpHalf > { // Byte - clrbit defm : MemOpi_bitPats<ldOpByte, truncstorei8, Clr3ImmPred, u6ExtPred, - ADDRriU6_0, CLRMEMIMM_BYTE, MemOPb_CLRBITi_V4, and>; + ADDRriU6_0, CLRMEMIMM_BYTE, L4_iand_memopb_io, and>; // Byte - setbit defm : MemOpi_bitPats<ldOpByte, truncstorei8, Set3ImmPred, u6ExtPred, - ADDRriU6_0, SETMEMIMM_BYTE, MemOPb_SETBITi_V4, or>; + ADDRriU6_0, SETMEMIMM_BYTE, L4_ior_memopb_io, or>; // Half Word - clrbit defm : MemOpi_bitPats<ldOpHalf, truncstorei16, Clr4ImmPred, u6_1ExtPred, - ADDRriU6_1, CLRMEMIMM_SHORT, MemOPh_CLRBITi_V4, and>; + ADDRriU6_1, CLRMEMIMM_SHORT, L4_iand_memoph_io, and>; // Half Word - setbit defm : MemOpi_bitPats<ldOpHalf, truncstorei16, Set4ImmPred, u6_1ExtPred, - ADDRriU6_1, SETMEMIMM_SHORT, MemOPh_SETBITi_V4, or>; + ADDRriU6_1, SETMEMIMM_SHORT, L4_ior_memoph_io, or>; } let Predicates = [HasV4T, UseMEMOP] in { @@ -2053,9 +2599,9 @@ let Predicates = [HasV4T, UseMEMOP] in { // memw(Rs+#0) = [clrbit|setbit](#U5) // memw(Rs+#u6:2) = [clrbit|setbit](#U5) defm : MemOpi_bitPats<load, store, Clr5ImmPred, u6_2ExtPred, ADDRriU6_2, - CLRMEMIMM, MemOPw_CLRBITi_V4, and>; + CLRMEMIMM, L4_iand_memopw_io, and>; defm : MemOpi_bitPats<load, store, Set5ImmPred, u6_2ExtPred, ADDRriU6_2, - SETMEMIMM, MemOPw_SETBITi_V4, or>; + SETMEMIMM, L4_ior_memopw_io, or>; } //===----------------------------------------------------------------------===// @@ -2096,12 +2642,12 @@ multiclass MemOPr_ALUOp<PatFrag ldOp, PatFrag stOp, multiclass MemOPr_ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > { // Half Word defm : MemOPr_ALUOp <ldOpHalf, truncstorei16, ADDRriU6_1, u6_1ExtPred, - MemOPh_ADDr_V4, MemOPh_SUBr_V4, - MemOPh_ANDr_V4, MemOPh_ORr_V4>; + L4_add_memoph_io, L4_sub_memoph_io, + L4_and_memoph_io, L4_or_memoph_io>; // Byte defm : MemOPr_ALUOp <ldOpByte, truncstorei8, ADDRriU6_0, u6ExtPred, - MemOPb_ADDr_V4, MemOPb_SUBr_V4, - MemOPb_ANDr_V4, MemOPb_ORr_V4>; + L4_add_memopb_io, L4_sub_memopb_io, + L4_and_memopb_io, L4_or_memopb_io>; } // Define 'def Pats' for MemOps with register addend. @@ -2111,8 +2657,8 @@ let Predicates = [HasV4T, UseMEMOP] in { defm : MemOPr_ExtType<sextloadi8, sextloadi16>; // sign extend defm : MemOPr_ExtType<extloadi8, extloadi16>; // any extend // Word - defm : MemOPr_ALUOp <load, store, ADDRriU6_2, u6_2ExtPred, MemOPw_ADDr_V4, - MemOPw_SUBr_V4, MemOPw_ANDr_V4, MemOPw_ORr_V4 >; + defm : MemOPr_ALUOp <load, store, ADDRriU6_2, u6_2ExtPred, L4_add_memopw_io, + L4_sub_memopw_io, L4_and_memopw_io, L4_or_memopw_io >; } //===----------------------------------------------------------------------===// @@ -2130,6 +2676,42 @@ let Predicates = [HasV4T, UseMEMOP] in { // incorrect code for negative numbers. // Pd=cmpb.eq(Rs,#u8) +let isCompare = 1, isExtendable = 1, opExtendable = 2, hasSideEffects = 0, + validSubTargets = HasV4SubT in +class CMP_NOT_REG_IMM<string OpName, bits<2> op, Operand ImmOp, + list<dag> Pattern> + : ALU32Inst <(outs PredRegs:$dst), (ins IntRegs:$src1, ImmOp:$src2), + "$dst = !cmp."#OpName#"($src1, #$src2)", + Pattern, + "", ALU32_2op_tc_2early_SLOT0123> { + bits<2> dst; + bits<5> src1; + bits<10> src2; + + let IClass = 0b0111; + let Inst{27-24} = 0b0101; + let Inst{23-22} = op; + let Inst{20-16} = src1; + let Inst{21} = !if (!eq(OpName, "gtu"), 0b0, src2{9}); + let Inst{13-5} = src2{8-0}; + let Inst{4-2} = 0b100; + let Inst{1-0} = dst; +} + +let opExtentBits = 10, isExtentSigned = 1 in { +def C4_cmpneqi : CMP_NOT_REG_IMM <"eq", 0b00, s10Ext, [(set (i1 PredRegs:$dst), + (setne (i32 IntRegs:$src1), s10ExtPred:$src2))]>; + +def C4_cmpltei : CMP_NOT_REG_IMM <"gt", 0b01, s10Ext, [(set (i1 PredRegs:$dst), + (not (setgt (i32 IntRegs:$src1), s10ExtPred:$src2)))]>; + +} +let opExtentBits = 9 in +def C4_cmplteui : CMP_NOT_REG_IMM <"gtu", 0b10, u9Ext, [(set (i1 PredRegs:$dst), + (not (setugt (i32 IntRegs:$src1), u9ExtPred:$src2)))]>; + + + // p=!cmp.eq(r1,r2) let isCompare = 1, validSubTargets = HasV4SubT in def CMPnotEQ_rr : ALU32_rr<(outs PredRegs:$dst), @@ -2139,15 +2721,6 @@ def CMPnotEQ_rr : ALU32_rr<(outs PredRegs:$dst), (setne (i32 IntRegs:$src1), (i32 IntRegs:$src2)))]>, Requires<[HasV4T]>; -// p=!cmp.eq(r1,#s10) -let isCompare = 1, validSubTargets = HasV4SubT in -def CMPnotEQ_ri : ALU32_ri<(outs PredRegs:$dst), - (ins IntRegs:$src1, s10Ext:$src2), - "$dst = !cmp.eq($src1, #$src2)", - [(set (i1 PredRegs:$dst), - (setne (i32 IntRegs:$src1), s10ImmPred:$src2))]>, - Requires<[HasV4T]>; - // p=!cmp.gt(r1,r2) let isCompare = 1, validSubTargets = HasV4SubT in def CMPnotGT_rr : ALU32_rr<(outs PredRegs:$dst), @@ -2157,14 +2730,6 @@ def CMPnotGT_rr : ALU32_rr<(outs PredRegs:$dst), (not (setgt (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>, Requires<[HasV4T]>; -// p=!cmp.gt(r1,#s10) -let isCompare = 1, validSubTargets = HasV4SubT in -def CMPnotGT_ri : ALU32_ri<(outs PredRegs:$dst), - (ins IntRegs:$src1, s10Ext:$src2), - "$dst = !cmp.gt($src1, #$src2)", - [(set (i1 PredRegs:$dst), - (not (setgt (i32 IntRegs:$src1), s10ImmPred:$src2)))]>, - Requires<[HasV4T]>; // p=!cmp.gtu(r1,r2) let isCompare = 1, validSubTargets = HasV4SubT in @@ -2175,15 +2740,6 @@ def CMPnotGTU_rr : ALU32_rr<(outs PredRegs:$dst), (not (setugt (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>, Requires<[HasV4T]>; -// p=!cmp.gtu(r1,#u9) -let isCompare = 1, validSubTargets = HasV4SubT in -def CMPnotGTU_ri : ALU32_ri<(outs PredRegs:$dst), - (ins IntRegs:$src1, u9Ext:$src2), - "$dst = !cmp.gtu($src1, #$src2)", - [(set (i1 PredRegs:$dst), - (not (setugt (i32 IntRegs:$src1), u9ImmPred:$src2)))]>, - Requires<[HasV4T]>; - let isCompare = 1, validSubTargets = HasV4SubT in def CMPbEQri_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u8Imm:$src2), @@ -2194,7 +2750,7 @@ def CMPbEQri_V4 : MInst<(outs PredRegs:$dst), def : Pat <(brcond (i1 (setne (and (i32 IntRegs:$src1), 255), u8ImmPred:$src2)), bb:$offset), - (JMP_f (CMPbEQri_V4 (i32 IntRegs:$src1), u8ImmPred:$src2), + (J2_jumpf (CMPbEQri_V4 (i32 IntRegs:$src1), u8ImmPred:$src2), bb:$offset)>, Requires<[HasV4T]>; @@ -2331,7 +2887,7 @@ def : Pat <(i32 (zext (i1 (setugt (i32 (and (i32 IntRegs:$Rs), 254)), // if (!Pd.new) Rd=#0 // cmp.ltu(Rs, Rt) -> cmp.gtu(Rt, Rs) def : Pat <(i32 (zext (i1 (setult (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), - (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rt), + (i32 (TFR_condset_ii (i1 (C2_cmpgtu (i32 IntRegs:$Rt), (i32 IntRegs:$Rs))), 1, 0))>, Requires<[HasV4T]>; @@ -2344,7 +2900,7 @@ def : Pat <(i32 (zext (i1 (setult (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), // if (!Pd.new) Rd=#0 // cmp.lt(Rs, Rt) -> cmp.gt(Rt, Rs) def : Pat <(i32 (zext (i1 (setlt (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), - (i32 (TFR_condset_ii (i1 (CMPGTrr (i32 IntRegs:$Rt), + (i32 (TFR_condset_ii (i1 (C2_cmpgt (i32 IntRegs:$Rt), (i32 IntRegs:$Rs))), 1, 0))>, Requires<[HasV4T]>; @@ -2356,7 +2912,7 @@ def : Pat <(i32 (zext (i1 (setlt (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), // if (Pd.new) Rd=#1 // if (!Pd.new) Rd=#0 def : Pat <(i32 (zext (i1 (setugt (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), - (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rs), + (i32 (TFR_condset_ii (i1 (C2_cmpgtu (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))), 1, 0))>, Requires<[HasV4T]>; @@ -2378,7 +2934,7 @@ def : Pat <(i32 (zext (i1 (setugt (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), // if (!Pd.new) Rd=#1 // cmp.ltu(Rs, Rt) -> cmp.gtu(Rt, Rs) def : Pat <(i32 (zext (i1 (setuge (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), - (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rt), + (i32 (TFR_condset_ii (i1 (C2_cmpgtu (i32 IntRegs:$Rt), (i32 IntRegs:$Rs))), 0, 1))>, Requires<[HasV4T]>; @@ -2391,7 +2947,7 @@ def : Pat <(i32 (zext (i1 (setuge (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), // if (!Pd.new) Rd=#1 // cmp.lt(Rs, Rt) -> cmp.gt(Rt, Rs) def : Pat <(i32 (zext (i1 (setge (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), - (i32 (TFR_condset_ii (i1 (CMPGTrr (i32 IntRegs:$Rt), + (i32 (TFR_condset_ii (i1 (C2_cmpgt (i32 IntRegs:$Rt), (i32 IntRegs:$Rs))), 0, 1))>, Requires<[HasV4T]>; @@ -2403,7 +2959,7 @@ def : Pat <(i32 (zext (i1 (setge (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), // if (Pd.new) Rd=#0 // if (!Pd.new) Rd=#1 def : Pat <(i32 (zext (i1 (setule (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), - (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rs), + (i32 (TFR_condset_ii (i1 (C2_cmpgtu (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))), 0, 1))>, Requires<[HasV4T]>; @@ -2415,7 +2971,7 @@ def : Pat <(i32 (zext (i1 (setule (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), // if (Pd.new) Rd=#0 // if (!Pd.new) Rd=#1 def : Pat <(i32 (zext (i1 (setle (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), - (i32 (TFR_condset_ii (i1 (CMPGTrr (i32 IntRegs:$Rs), + (i32 (TFR_condset_ii (i1 (C2_cmpgt (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))), 0, 1))>, Requires<[HasV4T]>; @@ -2439,7 +2995,7 @@ def : Pat <(i32 (zext (i1 (setle (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), let AddedComplexity = 139 in def : Pat <(i32 (zext (i1 (setult (i32 (and (i32 IntRegs:$src1), 255)), u7StrictPosImmPred:$src2)))), - (i32 (MUX_ii (i1 (CMPbGTUri_V4 (i32 IntRegs:$src1), + (i32 (C2_muxii (i1 (CMPbGTUri_V4 (i32 IntRegs:$src1), (DEC_CONST_BYTE u7StrictPosImmPred:$src2))), 0, 1))>, Requires<[HasV4T]>; @@ -2566,17 +3122,61 @@ def NTSTBIT_ri : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), // XTYPE/PRED - //===----------------------------------------------------------------------===// -//Deallocate frame and return. -// dealloc_return -let isReturn = 1, isTerminator = 1, isBarrier = 1, isPredicable = 1, - Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1 in { -let validSubTargets = HasV4SubT in - def DEALLOC_RET_V4 : LD0Inst<(outs), (ins), - "dealloc_return", - []>, - Requires<[HasV4T]>; +//===----------------------------------------------------------------------===// +// Multiclass for DeallocReturn +//===----------------------------------------------------------------------===// +class L4_RETURN<string mnemonic, bit isNot, bit isPredNew, bit isTak> + : LD0Inst<(outs), (ins PredRegs:$src), + !if(isNot, "if (!$src", "if ($src")# + !if(isPredNew, ".new) ", ") ")#mnemonic# + !if(isPredNew, #!if(isTak,":t", ":nt"),""), + [], "", LD_tc_3or4stall_SLOT0> { + + bits<2> src; + let BaseOpcode = "L4_RETURN"; + let isPredicatedFalse = isNot; + let isPredicatedNew = isPredNew; + let isTaken = isTak; + let IClass = 0b1001; + + let Inst{27-16} = 0b011000011110; + + let Inst{13} = isNot; + let Inst{12} = isTak; + let Inst{11} = isPredNew; + let Inst{10} = 0b0; + let Inst{9-8} = src; + let Inst{4-0} = 0b11110; + } + +// Produce all predicated forms, p, !p, p.new, !p.new, :t, :nt +multiclass L4_RETURN_PRED<string mnemonic, bit PredNot> { + let isPredicated = 1 in { + def _#NAME# : L4_RETURN <mnemonic, PredNot, 0, 1>; + def _#NAME#new_pnt : L4_RETURN <mnemonic, PredNot, 1, 0>; + def _#NAME#new_pt : L4_RETURN <mnemonic, PredNot, 1, 1>; + } +} + +multiclass LD_MISC_L4_RETURN<string mnemonic> { + let isBarrier = 1, isPredicable = 1 in + def NAME : LD0Inst <(outs), (ins), mnemonic, [], "", + LD_tc_3or4stall_SLOT0> { + let BaseOpcode = "L4_RETURN"; + let IClass = 0b1001; + let Inst{27-16} = 0b011000011110; + let Inst{13-10} = 0b0000; + let Inst{4-0} = 0b11110; + } + defm t : L4_RETURN_PRED<mnemonic, 0 >; + defm f : L4_RETURN_PRED<mnemonic, 1 >; } +let isReturn = 1, isTerminator = 1, + Defs = [R29, R30, R31, PC], Uses = [R30], hasSideEffects = 0, + validSubTargets = HasV4SubT, isCodeGenOnly = 0 in +defm L4_return: LD_MISC_L4_RETURN <"dealloc_return">, PredNewRel; + // Restore registers and dealloc return function call. let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1, Defs = [R29, R30, R31, PC] in { @@ -2609,454 +3209,579 @@ let isCall = 1, isBarrier = 1, Requires<[HasV4T]>; } -// if (Ps) dealloc_return -let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, - isPredicated = 1 in { -let validSubTargets = HasV4SubT in - def DEALLOC_RET_cPt_V4 : LD0Inst<(outs), - (ins PredRegs:$src1), - "if ($src1) dealloc_return", - []>, - Requires<[HasV4T]>; -} +//===----------------------------------------------------------------------===// +// Template class for non predicated store instructions with +// GP-Relative or absolute addressing. +//===----------------------------------------------------------------------===// +let hasSideEffects = 0, isPredicable = 1, isNVStorable = 1 in +class T_StoreAbsGP <string mnemonic, RegisterClass RC, Operand ImmOp, + bits<2>MajOp, Operand AddrOp, bit isAbs, bit isHalf> + : STInst<(outs), (ins AddrOp:$addr, RC:$src), + mnemonic # !if(isAbs, "(##", "(#")#"$addr) = $src"#!if(isHalf, ".h",""), + [], "", V2LDST_tc_st_SLOT01> { + bits<19> addr; + bits<5> src; + bits<16> offsetBits; + + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "u16_3Imm"), addr{18-3}, + !if (!eq(ImmOpStr, "u16_2Imm"), addr{17-2}, + !if (!eq(ImmOpStr, "u16_1Imm"), addr{16-1}, + /* u16_0Imm */ addr{15-0}))); + let IClass = 0b0100; + let Inst{27} = 1; + let Inst{26-25} = offsetBits{15-14}; + let Inst{24} = 0b0; + let Inst{23-22} = MajOp; + let Inst{21} = isHalf; + let Inst{20-16} = offsetBits{13-9}; + let Inst{13} = offsetBits{8}; + let Inst{12-8} = src; + let Inst{7-0} = offsetBits{7-0}; + } -// if (!Ps) dealloc_return -let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, - isPredicated = 1, isPredicatedFalse = 1 in { -let validSubTargets = HasV4SubT in - def DEALLOC_RET_cNotPt_V4 : LD0Inst<(outs), (ins PredRegs:$src1), - "if (!$src1) dealloc_return", - []>, - Requires<[HasV4T]>; -} +//===----------------------------------------------------------------------===// +// Template class for predicated store instructions with +// GP-Relative or absolute addressing. +//===----------------------------------------------------------------------===// +let hasSideEffects = 0, isPredicated = 1, isNVStorable = 1, opExtentBits = 6, + opExtendable = 1 in +class T_StoreAbs_Pred <string mnemonic, RegisterClass RC, bits<2> MajOp, + bit isHalf, bit isNot, bit isNew> + : STInst<(outs), (ins PredRegs:$src1, u6Ext:$absaddr, RC: $src2), + !if(isNot, "if (!$src1", "if ($src1")#!if(isNew, ".new) ", + ") ")#mnemonic#"(#$absaddr) = $src2"#!if(isHalf, ".h",""), + [], "", ST_tc_st_SLOT01>, AddrModeRel { + bits<2> src1; + bits<6> absaddr; + bits<5> src2; + + let isPredicatedNew = isNew; + let isPredicatedFalse = isNot; + + let IClass = 0b1010; -// if (Ps.new) dealloc_return:nt -let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, - isPredicated = 1 in { -let validSubTargets = HasV4SubT in - def DEALLOC_RET_cdnPnt_V4 : LD0Inst<(outs), (ins PredRegs:$src1), - "if ($src1.new) dealloc_return:nt", - []>, - Requires<[HasV4T]>; -} + let Inst{27-24} = 0b1111; + let Inst{23-22} = MajOp; + let Inst{21} = isHalf; + let Inst{17-16} = absaddr{5-4}; + let Inst{13} = isNew; + let Inst{12-8} = src2; + let Inst{7} = 0b1; + let Inst{6-3} = absaddr{3-0}; + let Inst{2} = isNot; + let Inst{1-0} = src1; + } -// if (!Ps.new) dealloc_return:nt -let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, - isPredicated = 1, isPredicatedFalse = 1 in { -let validSubTargets = HasV4SubT in - def DEALLOC_RET_cNotdnPnt_V4 : LD0Inst<(outs), (ins PredRegs:$src1), - "if (!$src1.new) dealloc_return:nt", - []>, - Requires<[HasV4T]>; +//===----------------------------------------------------------------------===// +// Template class for predicated store instructions with absolute addressing. +//===----------------------------------------------------------------------===// +class T_StoreAbs <string mnemonic, RegisterClass RC, Operand ImmOp, + bits<2> MajOp, bit isHalf> + : T_StoreAbsGP <mnemonic, RC, ImmOp, MajOp, u0AlwaysExt, 1, isHalf>, + AddrModeRel { + string ImmOpStr = !cast<string>(ImmOp); + let opExtentBits = !if (!eq(ImmOpStr, "u16_3Imm"), 19, + !if (!eq(ImmOpStr, "u16_2Imm"), 18, + !if (!eq(ImmOpStr, "u16_1Imm"), 17, + /* u16_0Imm */ 16))); + + let opExtentAlign = !if (!eq(ImmOpStr, "u16_3Imm"), 3, + !if (!eq(ImmOpStr, "u16_2Imm"), 2, + !if (!eq(ImmOpStr, "u16_1Imm"), 1, + /* u16_0Imm */ 0))); } -// if (Ps.new) dealloc_return:t -let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, - isPredicated = 1 in { -let validSubTargets = HasV4SubT in - def DEALLOC_RET_cdnPt_V4 : LD0Inst<(outs), (ins PredRegs:$src1), - "if ($src1.new) dealloc_return:t", - []>, - Requires<[HasV4T]>; -} +//===----------------------------------------------------------------------===// +// Multiclass for store instructions with absolute addressing. +//===----------------------------------------------------------------------===// +let validSubTargets = HasV4SubT, addrMode = Absolute, isExtended = 1 in +multiclass ST_Abs<string mnemonic, string CextOp, RegisterClass RC, + Operand ImmOp, bits<2> MajOp, bit isHalf = 0> { + let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in { + let opExtendable = 0, isPredicable = 1 in + def S2_#NAME#abs : T_StoreAbs <mnemonic, RC, ImmOp, MajOp, isHalf>; -// if (!Ps.new) dealloc_return:nt -let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, - isPredicated = 1, isPredicatedFalse = 1 in { -let validSubTargets = HasV4SubT in - def DEALLOC_RET_cNotdnPt_V4 : LD0Inst<(outs), (ins PredRegs:$src1), - "if (!$src1.new) dealloc_return:t", - []>, - Requires<[HasV4T]>; + // Predicated + def S4_p#NAME#t_abs : T_StoreAbs_Pred<mnemonic, RC, MajOp, isHalf, 0, 0>; + def S4_p#NAME#f_abs : T_StoreAbs_Pred<mnemonic, RC, MajOp, isHalf, 1, 0>; + + // .new Predicated + def S4_p#NAME#tnew_abs : T_StoreAbs_Pred<mnemonic, RC, MajOp, isHalf, 0, 1>; + def S4_p#NAME#fnew_abs : T_StoreAbs_Pred<mnemonic, RC, MajOp, isHalf, 1, 1>; + } } -// Load/Store with absolute addressing mode -// memw(#u6)=Rt +//===----------------------------------------------------------------------===// +// Template class for non predicated new-value store instructions with +// GP-Relative or absolute addressing. +//===----------------------------------------------------------------------===// +let hasSideEffects = 0, isPredicable = 1, mayStore = 1, isNVStore = 1, + isNewValue = 1, opNewValue = 1 in +class T_StoreAbsGP_NV <string mnemonic, Operand ImmOp, bits<2>MajOp, bit isAbs> + : NVInst_V4<(outs), (ins u0AlwaysExt:$addr, IntRegs:$src), + mnemonic # !if(isAbs, "(##", "(#")#"$addr) = $src.new", + [], "", V2LDST_tc_st_SLOT0> { + bits<19> addr; + bits<3> src; + bits<16> offsetBits; + + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "u16_3Imm"), addr{18-3}, + !if (!eq(ImmOpStr, "u16_2Imm"), addr{17-2}, + !if (!eq(ImmOpStr, "u16_1Imm"), addr{16-1}, + /* u16_0Imm */ addr{15-0}))); + let IClass = 0b0100; + + let Inst{27} = 1; + let Inst{26-25} = offsetBits{15-14}; + let Inst{24-21} = 0b0101; + let Inst{20-16} = offsetBits{13-9}; + let Inst{13} = offsetBits{8}; + let Inst{12-11} = MajOp; + let Inst{10-8} = src; + let Inst{7-0} = offsetBits{7-0}; + } -multiclass ST_Abs_Predbase<string mnemonic, RegisterClass RC, bit isNot, - bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME#_V4 : STInst2<(outs), - (ins PredRegs:$src1, u0AlwaysExt:$absaddr, RC: $src2), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"(##$absaddr) = $src2", - []>, - Requires<[HasV4T]>; +//===----------------------------------------------------------------------===// +// Template class for predicated new-value store instructions with +// absolute addressing. +//===----------------------------------------------------------------------===// +let hasSideEffects = 0, isPredicated = 1, mayStore = 1, isNVStore = 1, + isNewValue = 1, opNewValue = 2, opExtentBits = 6, opExtendable = 1 in +class T_StoreAbs_NV_Pred <string mnemonic, bits<2> MajOp, bit isNot, bit isNew> + : NVInst_V4<(outs), (ins PredRegs:$src1, u6Ext:$absaddr, IntRegs:$src2), + !if(isNot, "if (!$src1", "if ($src1")#!if(isNew, ".new) ", + ") ")#mnemonic#"(#$absaddr) = $src2.new", + [], "", ST_tc_st_SLOT0>, AddrModeRel { + bits<2> src1; + bits<6> absaddr; + bits<3> src2; + + let isPredicatedNew = isNew; + let isPredicatedFalse = isNot; + + let IClass = 0b1010; + + let Inst{27-24} = 0b1111; + let Inst{23-21} = 0b101; + let Inst{17-16} = absaddr{5-4}; + let Inst{13} = isNew; + let Inst{12-11} = MajOp; + let Inst{10-8} = src2; + let Inst{7} = 0b1; + let Inst{6-3} = absaddr{3-0}; + let Inst{2} = isNot; + let Inst{1-0} = src1; } -multiclass ST_Abs_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ST_Abs_Predbase<mnemonic, RC, PredNot, 0>; - // Predicate new - defm _cdn#NAME : ST_Abs_Predbase<mnemonic, RC, PredNot, 1>; - } +//===----------------------------------------------------------------------===// +// Template class for non-predicated new-value store instructions with +// absolute addressing. +//===----------------------------------------------------------------------===// +class T_StoreAbs_NV <string mnemonic, Operand ImmOp, bits<2> MajOp> + : T_StoreAbsGP_NV <mnemonic, ImmOp, MajOp, 1>, AddrModeRel { + + string ImmOpStr = !cast<string>(ImmOp); + let opExtentBits = !if (!eq(ImmOpStr, "u16_3Imm"), 19, + !if (!eq(ImmOpStr, "u16_2Imm"), 18, + !if (!eq(ImmOpStr, "u16_1Imm"), 17, + /* u16_0Imm */ 16))); + + let opExtentAlign = !if (!eq(ImmOpStr, "u16_3Imm"), 3, + !if (!eq(ImmOpStr, "u16_2Imm"), 2, + !if (!eq(ImmOpStr, "u16_1Imm"), 1, + /* u16_0Imm */ 0))); } -let isNVStorable = 1, isExtended = 1, neverHasSideEffects = 1 in -multiclass ST_Abs<string mnemonic, string CextOp, RegisterClass RC> { +//===----------------------------------------------------------------------===// +// Multiclass for new-value store instructions with absolute addressing. +//===----------------------------------------------------------------------===// +let validSubTargets = HasV4SubT, addrMode = Absolute, isExtended = 1 in +multiclass ST_Abs_NV <string mnemonic, string CextOp, Operand ImmOp, + bits<2> MajOp> { let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in { let opExtendable = 0, isPredicable = 1 in - def NAME#_V4 : STInst2<(outs), - (ins u0AlwaysExt:$absaddr, RC:$src), - mnemonic#"(##$absaddr) = $src", - []>, - Requires<[HasV4T]>; + def S2_#NAME#newabs : T_StoreAbs_NV <mnemonic, ImmOp, MajOp>; - let opExtendable = 1, isPredicated = 1 in { - defm Pt : ST_Abs_Pred<mnemonic, RC, 0>; - defm NotPt : ST_Abs_Pred<mnemonic, RC, 1>; - } + // Predicated + def S4_p#NAME#newt_abs : T_StoreAbs_NV_Pred <mnemonic, MajOp, 0, 0>; + def S4_p#NAME#newf_abs : T_StoreAbs_NV_Pred <mnemonic, MajOp, 1, 0>; + + // .new Predicated + def S4_p#NAME#newtnew_abs : T_StoreAbs_NV_Pred <mnemonic, MajOp, 0, 1>; + def S4_p#NAME#newfnew_abs : T_StoreAbs_NV_Pred <mnemonic, MajOp, 1, 1>; } } -multiclass ST_Abs_Predbase_nv<string mnemonic, RegisterClass RC, bit isNot, - bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME#_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, u0AlwaysExt:$absaddr, RC: $src2), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#mnemonic#"(##$absaddr) = $src2.new", - []>, - Requires<[HasV4T]>; -} +//===----------------------------------------------------------------------===// +// Stores with absolute addressing +//===----------------------------------------------------------------------===// +let accessSize = ByteAccess, isCodeGenOnly = 0 in +defm storerb : ST_Abs <"memb", "STrib", IntRegs, u16_0Imm, 0b00>, + ST_Abs_NV <"memb", "STrib", u16_0Imm, 0b00>; -multiclass ST_Abs_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : ST_Abs_Predbase_nv<mnemonic, RC, PredNot, 0>; - // Predicate new - defm _cdn#NAME : ST_Abs_Predbase_nv<mnemonic, RC, PredNot, 1>; - } -} +let accessSize = HalfWordAccess, isCodeGenOnly = 0 in +defm storerh : ST_Abs <"memh", "STrih", IntRegs, u16_1Imm, 0b01>, + ST_Abs_NV <"memh", "STrih", u16_1Imm, 0b01>; -let mayStore = 1, isNVStore = 1, isExtended = 1, neverHasSideEffects = 1 in -multiclass ST_Abs_nv<string mnemonic, string CextOp, RegisterClass RC> { - let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in { - let opExtendable = 0, isPredicable = 1 in - def NAME#_nv_V4 : NVInst_V4<(outs), - (ins u0AlwaysExt:$absaddr, RC:$src), - mnemonic#"(##$absaddr) = $src.new", - []>, - Requires<[HasV4T]>; +let accessSize = WordAccess, isCodeGenOnly = 0 in +defm storeri : ST_Abs <"memw", "STriw", IntRegs, u16_2Imm, 0b10>, + ST_Abs_NV <"memw", "STriw", u16_2Imm, 0b10>; - let opExtendable = 1, isPredicated = 1 in { - defm Pt : ST_Abs_Pred_nv<mnemonic, RC, 0>; - defm NotPt : ST_Abs_Pred_nv<mnemonic, RC, 1>; - } +let isNVStorable = 0, accessSize = DoubleWordAccess, isCodeGenOnly = 0 in +defm storerd : ST_Abs <"memd", "STrid", DoubleRegs, u16_3Imm, 0b11>; + +let isNVStorable = 0, accessSize = HalfWordAccess, isCodeGenOnly = 0 in +defm storerf : ST_Abs <"memh", "STrif", IntRegs, u16_1Imm, 0b01, 1>; + +//===----------------------------------------------------------------------===// +// GP-relative stores. +// mem[bhwd](#global)=Rt +// Once predicated, these instructions map to absolute addressing mode. +// if ([!]Pv[.new]) mem[bhwd](##global)=Rt +//===----------------------------------------------------------------------===// + +let validSubTargets = HasV4SubT in +class T_StoreGP <string mnemonic, string BaseOp, RegisterClass RC, + Operand ImmOp, bits<2> MajOp, bit isHalf = 0> + : T_StoreAbsGP <mnemonic, RC, ImmOp, MajOp, globaladdress, 0, isHalf> { + // Set BaseOpcode same as absolute addressing instructions so that + // non-predicated GP-Rel instructions can have relate with predicated + // Absolute instruction. + let BaseOpcode = BaseOp#_abs; + } + +let validSubTargets = HasV4SubT in +multiclass ST_GP <string mnemonic, string BaseOp, Operand ImmOp, + bits<2> MajOp, bit isHalf = 0> { + // Set BaseOpcode same as absolute addressing instructions so that + // non-predicated GP-Rel instructions can have relate with predicated + // Absolute instruction. + let BaseOpcode = BaseOp#_abs in { + def NAME#gp : T_StoreAbsGP <mnemonic, IntRegs, ImmOp, MajOp, + globaladdress, 0, isHalf>; + // New-value store + def NAME#newgp : T_StoreAbsGP_NV <mnemonic, ImmOp, MajOp, 0> ; } } -let addrMode = Absolute in { - let accessSize = ByteAccess in - defm STrib_abs : ST_Abs<"memb", "STrib", IntRegs>, - ST_Abs_nv<"memb", "STrib", IntRegs>, AddrModeRel; +let accessSize = ByteAccess in +defm S2_storerb : ST_GP<"memb", "STrib", u16_0Imm, 0b00>, NewValueRel; - let accessSize = HalfWordAccess in - defm STrih_abs : ST_Abs<"memh", "STrih", IntRegs>, - ST_Abs_nv<"memh", "STrih", IntRegs>, AddrModeRel; +let accessSize = HalfWordAccess in +defm S2_storerh : ST_GP<"memh", "STrih", u16_1Imm, 0b01>, NewValueRel; - let accessSize = WordAccess in - defm STriw_abs : ST_Abs<"memw", "STriw", IntRegs>, - ST_Abs_nv<"memw", "STriw", IntRegs>, AddrModeRel; +let accessSize = WordAccess in +defm S2_storeri : ST_GP<"memw", "STriw", u16_2Imm, 0b10>, NewValueRel; - let accessSize = DoubleWordAccess, isNVStorable = 0 in - defm STrid_abs : ST_Abs<"memd", "STrid", DoubleRegs>, AddrModeRel; -} +let isNVStorable = 0, accessSize = DoubleWordAccess in +def S2_storerdgp : T_StoreGP <"memd", "STrid", DoubleRegs, + u16_3Imm, 0b11>, PredNewRel; + +let isNVStorable = 0, accessSize = HalfWordAccess in +def S2_storerfgp : T_StoreGP <"memh", "STrif", IntRegs, + u16_1Imm, 0b01, 1>, PredNewRel; let Predicates = [HasV4T], AddedComplexity = 30 in { def : Pat<(truncstorei8 (i32 IntRegs:$src1), (HexagonCONST32 tglobaladdr:$absaddr)), - (STrib_abs_V4 tglobaladdr: $absaddr, IntRegs: $src1)>; + (S2_storerbabs tglobaladdr: $absaddr, IntRegs: $src1)>; def : Pat<(truncstorei16 (i32 IntRegs:$src1), (HexagonCONST32 tglobaladdr:$absaddr)), - (STrih_abs_V4 tglobaladdr: $absaddr, IntRegs: $src1)>; + (S2_storerhabs tglobaladdr: $absaddr, IntRegs: $src1)>; def : Pat<(store (i32 IntRegs:$src1), (HexagonCONST32 tglobaladdr:$absaddr)), - (STriw_abs_V4 tglobaladdr: $absaddr, IntRegs: $src1)>; + (S2_storeriabs tglobaladdr: $absaddr, IntRegs: $src1)>; def : Pat<(store (i64 DoubleRegs:$src1), (HexagonCONST32 tglobaladdr:$absaddr)), - (STrid_abs_V4 tglobaladdr: $absaddr, DoubleRegs: $src1)>; -} - -//===----------------------------------------------------------------------===// -// multiclass for store instructions with GP-relative addressing mode. -// mem[bhwd](#global)=Rt -// if ([!]Pv[.new]) mem[bhwd](##global) = Rt -//===----------------------------------------------------------------------===// -let mayStore = 1, isNVStorable = 1 in -multiclass ST_GP<string mnemonic, string BaseOp, RegisterClass RC> { - let BaseOpcode = BaseOp, isPredicable = 1 in - def NAME#_V4 : STInst2<(outs), - (ins globaladdress:$global, RC:$src), - mnemonic#"(#$global) = $src", - []>; - - // When GP-relative instructions are predicated, their addressing mode is - // changed to absolute and they are always constant extended. - let BaseOpcode = BaseOp, isExtended = 1, opExtendable = 1, - isPredicated = 1 in { - defm Pt : ST_Abs_Pred <mnemonic, RC, 0>; - defm NotPt : ST_Abs_Pred <mnemonic, RC, 1>; - } -} - -let mayStore = 1, isNVStore = 1 in -multiclass ST_GP_nv<string mnemonic, string BaseOp, RegisterClass RC> { - let BaseOpcode = BaseOp, isPredicable = 1 in - def NAME#_nv_V4 : NVInst_V4<(outs), - (ins u0AlwaysExt:$global, RC:$src), - mnemonic#"(#$global) = $src.new", - []>, - Requires<[HasV4T]>; - - // When GP-relative instructions are predicated, their addressing mode is - // changed to absolute and they are always constant extended. - let BaseOpcode = BaseOp, isExtended = 1, opExtendable = 1, - isPredicated = 1 in { - defm Pt : ST_Abs_Pred_nv<mnemonic, RC, 0>; - defm NotPt : ST_Abs_Pred_nv<mnemonic, RC, 1>; - } -} - -let validSubTargets = HasV4SubT, neverHasSideEffects = 1 in { - let isNVStorable = 0 in - defm STd_GP : ST_GP <"memd", "STd_GP", DoubleRegs>, PredNewRel; - - defm STb_GP : ST_GP<"memb", "STb_GP", IntRegs>, - ST_GP_nv<"memb", "STb_GP", IntRegs>, NewValueRel; - defm STh_GP : ST_GP<"memh", "STh_GP", IntRegs>, - ST_GP_nv<"memh", "STh_GP", IntRegs>, NewValueRel; - defm STw_GP : ST_GP<"memw", "STw_GP", IntRegs>, - ST_GP_nv<"memw", "STw_GP", IntRegs>, NewValueRel; + (S2_storerdabs tglobaladdr: $absaddr, DoubleRegs: $src1)>; } // 64 bit atomic store def : Pat <(atomic_store_64 (HexagonCONST32_GP tglobaladdr:$global), (i64 DoubleRegs:$src1)), - (STd_GP_V4 tglobaladdr:$global, (i64 DoubleRegs:$src1))>, + (S2_storerdgp tglobaladdr:$global, (i64 DoubleRegs:$src1))>, Requires<[HasV4T]>; // Map from store(globaladdress) -> memd(#foo) let AddedComplexity = 100 in def : Pat <(store (i64 DoubleRegs:$src1), (HexagonCONST32_GP tglobaladdr:$global)), - (STd_GP_V4 tglobaladdr:$global, (i64 DoubleRegs:$src1))>; + (S2_storerdgp tglobaladdr:$global, (i64 DoubleRegs:$src1))>; // 8 bit atomic store def : Pat < (atomic_store_8 (HexagonCONST32_GP tglobaladdr:$global), (i32 IntRegs:$src1)), - (STb_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; + (S2_storerbgp tglobaladdr:$global, (i32 IntRegs:$src1))>; // Map from store(globaladdress) -> memb(#foo) let AddedComplexity = 100 in def : Pat<(truncstorei8 (i32 IntRegs:$src1), (HexagonCONST32_GP tglobaladdr:$global)), - (STb_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; + (S2_storerbgp tglobaladdr:$global, (i32 IntRegs:$src1))>; // Map from "i1 = constant<-1>; memw(CONST32(#foo)) = i1" // to "r0 = 1; memw(#foo) = r0" let AddedComplexity = 100 in def : Pat<(store (i1 -1), (HexagonCONST32_GP tglobaladdr:$global)), - (STb_GP_V4 tglobaladdr:$global, (TFRI 1))>; + (S2_storerbgp tglobaladdr:$global, (A2_tfrsi 1))>; def : Pat<(atomic_store_16 (HexagonCONST32_GP tglobaladdr:$global), (i32 IntRegs:$src1)), - (STh_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; + (S2_storerhgp tglobaladdr:$global, (i32 IntRegs:$src1))>; // Map from store(globaladdress) -> memh(#foo) let AddedComplexity = 100 in def : Pat<(truncstorei16 (i32 IntRegs:$src1), (HexagonCONST32_GP tglobaladdr:$global)), - (STh_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; + (S2_storerhgp tglobaladdr:$global, (i32 IntRegs:$src1))>; // 32 bit atomic store def : Pat<(atomic_store_32 (HexagonCONST32_GP tglobaladdr:$global), (i32 IntRegs:$src1)), - (STw_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; + (S2_storerigp tglobaladdr:$global, (i32 IntRegs:$src1))>; // Map from store(globaladdress) -> memw(#foo) let AddedComplexity = 100 in def : Pat<(store (i32 IntRegs:$src1), (HexagonCONST32_GP tglobaladdr:$global)), - (STw_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; + (S2_storerigp tglobaladdr:$global, (i32 IntRegs:$src1))>; //===----------------------------------------------------------------------===// -// Multiclass for the load instructions with absolute addressing mode. +// Template class for non predicated load instructions with +// absolute addressing mode. //===----------------------------------------------------------------------===// -multiclass LD_Abs_Predbase<string mnemonic, RegisterClass RC, bit isNot, - bit isPredNew> { - let isPredicatedNew = isPredNew in - def NAME : LDInst2<(outs RC:$dst), - (ins PredRegs:$src1, u0AlwaysExt:$absaddr), - !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", - ") ")#"$dst = "#mnemonic#"(##$absaddr)", - []>, - Requires<[HasV4T]>; -} +let isPredicable = 1, hasSideEffects = 0, validSubTargets = HasV4SubT in +class T_LoadAbsGP <string mnemonic, RegisterClass RC, Operand ImmOp, + bits<3> MajOp, Operand AddrOp, bit isAbs> + : LDInst <(outs RC:$dst), (ins AddrOp:$addr), + "$dst = "#mnemonic# !if(isAbs, "(##", "(#")#"$addr)", + [], "", V2LDST_tc_ld_SLOT01> { + bits<5> dst; + bits<19> addr; + bits<16> offsetBits; + + string ImmOpStr = !cast<string>(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "u16_3Imm"), addr{18-3}, + !if (!eq(ImmOpStr, "u16_2Imm"), addr{17-2}, + !if (!eq(ImmOpStr, "u16_1Imm"), addr{16-1}, + /* u16_0Imm */ addr{15-0}))); + + let IClass = 0b0100; + + let Inst{27} = 0b1; + let Inst{26-25} = offsetBits{15-14}; + let Inst{24} = 0b1; + let Inst{23-21} = MajOp; + let Inst{20-16} = offsetBits{13-9}; + let Inst{13-5} = offsetBits{8-0}; + let Inst{4-0} = dst; + } + +class T_LoadAbs <string mnemonic, RegisterClass RC, Operand ImmOp, + bits<3> MajOp> + : T_LoadAbsGP <mnemonic, RC, ImmOp, MajOp, u0AlwaysExt, 1>, AddrModeRel { -multiclass LD_Abs_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let isPredicatedFalse = PredNot in { - defm _c#NAME : LD_Abs_Predbase<mnemonic, RC, PredNot, 0>; - // Predicate new - defm _cdn#NAME : LD_Abs_Predbase<mnemonic, RC, PredNot, 1>; + string ImmOpStr = !cast<string>(ImmOp); + let opExtentBits = !if (!eq(ImmOpStr, "u16_3Imm"), 19, + !if (!eq(ImmOpStr, "u16_2Imm"), 18, + !if (!eq(ImmOpStr, "u16_1Imm"), 17, + /* u16_0Imm */ 16))); + + let opExtentAlign = !if (!eq(ImmOpStr, "u16_3Imm"), 3, + !if (!eq(ImmOpStr, "u16_2Imm"), 2, + !if (!eq(ImmOpStr, "u16_1Imm"), 1, + /* u16_0Imm */ 0))); } +//===----------------------------------------------------------------------===// +// Template class for predicated load instructions with +// absolute addressing mode. +//===----------------------------------------------------------------------===// +let isPredicated = 1, hasNewValue = 1, opExtentBits = 6, opExtendable = 2 in +class T_LoadAbs_Pred <string mnemonic, RegisterClass RC, bits<3> MajOp, + bit isPredNot, bit isPredNew> + : LDInst <(outs RC:$dst), (ins PredRegs:$src1, u6Ext:$absaddr), + !if(isPredNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#"$dst = "#mnemonic#"(#$absaddr)">, AddrModeRel { + bits<5> dst; + bits<2> src1; + bits<6> absaddr; + + let isPredicatedNew = isPredNew; + let isPredicatedFalse = isPredNot; + + let IClass = 0b1001; + + let Inst{27-24} = 0b1111; + let Inst{23-21} = MajOp; + let Inst{20-16} = absaddr{5-1}; + let Inst{13} = 0b1; + let Inst{12} = isPredNew; + let Inst{11} = isPredNot; + let Inst{10-9} = src1; + let Inst{8} = absaddr{0}; + let Inst{7} = 0b1; + let Inst{4-0} = dst; + } + +//===----------------------------------------------------------------------===// +// Multiclass for the load instructions with absolute addressing mode. +//===----------------------------------------------------------------------===// +multiclass LD_Abs_Pred<string mnemonic, RegisterClass RC, bits<3> MajOp, + bit PredNot> { + def _abs : T_LoadAbs_Pred <mnemonic, RC, MajOp, PredNot, 0>; + // Predicate new + def new_abs : T_LoadAbs_Pred <mnemonic, RC, MajOp, PredNot, 1>; } -let isExtended = 1, neverHasSideEffects = 1 in -multiclass LD_Abs<string mnemonic, string CextOp, RegisterClass RC> { +let addrMode = Absolute, isExtended = 1 in +multiclass LD_Abs<string mnemonic, string CextOp, RegisterClass RC, + Operand ImmOp, bits<3> MajOp> { let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in { - let opExtendable = 1, isPredicable = 1 in - def NAME#_V4 : LDInst2<(outs RC:$dst), - (ins u0AlwaysExt:$absaddr), - "$dst = "#mnemonic#"(##$absaddr)", - []>, - Requires<[HasV4T]>; + let opExtendable = 1, isPredicable = 1 in + def L4_#NAME#_abs: T_LoadAbs <mnemonic, RC, ImmOp, MajOp>; - let opExtendable = 2, isPredicated = 1 in { - defm Pt_V4 : LD_Abs_Pred<mnemonic, RC, 0>; - defm NotPt_V4 : LD_Abs_Pred<mnemonic, RC, 1>; - } + // Predicated + defm L4_p#NAME#t : LD_Abs_Pred<mnemonic, RC, MajOp, 0>; + defm L4_p#NAME#f : LD_Abs_Pred<mnemonic, RC, MajOp, 1>; } } -let addrMode = Absolute in { - let accessSize = ByteAccess in { - defm LDrib_abs : LD_Abs<"memb", "LDrib", IntRegs>, AddrModeRel; - defm LDriub_abs : LD_Abs<"memub", "LDriub", IntRegs>, AddrModeRel; - } - let accessSize = HalfWordAccess in { - defm LDrih_abs : LD_Abs<"memh", "LDrih", IntRegs>, AddrModeRel; - defm LDriuh_abs : LD_Abs<"memuh", "LDriuh", IntRegs>, AddrModeRel; +let accessSize = ByteAccess, hasNewValue = 1, isCodeGenOnly = 0 in { + defm loadrb : LD_Abs<"memb", "LDrib", IntRegs, u16_0Imm, 0b000>; + defm loadrub : LD_Abs<"memub", "LDriub", IntRegs, u16_0Imm, 0b001>; +} + +let accessSize = HalfWordAccess, hasNewValue = 1, isCodeGenOnly = 0 in { + defm loadrh : LD_Abs<"memh", "LDrih", IntRegs, u16_1Imm, 0b010>; + defm loadruh : LD_Abs<"memuh", "LDriuh", IntRegs, u16_1Imm, 0b011>; +} + +let accessSize = WordAccess, hasNewValue = 1, isCodeGenOnly = 0 in +defm loadri : LD_Abs<"memw", "LDriw", IntRegs, u16_2Imm, 0b100>; + +let accessSize = DoubleWordAccess, isCodeGenOnly = 0 in +defm loadrd : LD_Abs<"memd", "LDrid", DoubleRegs, u16_3Imm, 0b110>; + +//===----------------------------------------------------------------------===// +// multiclass for load instructions with GP-relative addressing mode. +// Rx=mem[bhwd](##global) +// Once predicated, these instructions map to absolute addressing mode. +// if ([!]Pv[.new]) Rx=mem[bhwd](##global) +//===----------------------------------------------------------------------===// + +class T_LoadGP <string mnemonic, string BaseOp, RegisterClass RC, Operand ImmOp, + bits<3> MajOp> + : T_LoadAbsGP <mnemonic, RC, ImmOp, MajOp, globaladdress, 0>, PredNewRel { + let BaseOpcode = BaseOp#_abs; } - let accessSize = WordAccess in - defm LDriw_abs : LD_Abs<"memw", "LDriw", IntRegs>, AddrModeRel; - let accessSize = DoubleWordAccess in - defm LDrid_abs : LD_Abs<"memd", "LDrid", DoubleRegs>, AddrModeRel; +let accessSize = ByteAccess, hasNewValue = 1 in { + def L2_loadrbgp : T_LoadGP<"memb", "LDrib", IntRegs, u16_0Imm, 0b000>; + def L2_loadrubgp : T_LoadGP<"memub", "LDriub", IntRegs, u16_0Imm, 0b001>; +} + +let accessSize = HalfWordAccess, hasNewValue = 1 in { + def L2_loadrhgp : T_LoadGP<"memh", "LDrih", IntRegs, u16_1Imm, 0b010>; + def L2_loadruhgp : T_LoadGP<"memuh", "LDriuh", IntRegs, u16_1Imm, 0b011>; } +let accessSize = WordAccess, hasNewValue = 1 in +def L2_loadrigp : T_LoadGP<"memw", "LDriw", IntRegs, u16_2Imm, 0b100>; + +let accessSize = DoubleWordAccess in +def L2_loadrdgp : T_LoadGP<"memd", "LDrid", DoubleRegs, u16_3Imm, 0b110>; + let Predicates = [HasV4T], AddedComplexity = 30 in { def : Pat<(i32 (load (HexagonCONST32 tglobaladdr:$absaddr))), - (LDriw_abs_V4 tglobaladdr: $absaddr)>; + (L4_loadri_abs tglobaladdr: $absaddr)>; def : Pat<(i32 (sextloadi8 (HexagonCONST32 tglobaladdr:$absaddr))), - (LDrib_abs_V4 tglobaladdr:$absaddr)>; + (L4_loadrb_abs tglobaladdr:$absaddr)>; def : Pat<(i32 (zextloadi8 (HexagonCONST32 tglobaladdr:$absaddr))), - (LDriub_abs_V4 tglobaladdr:$absaddr)>; + (L4_loadrub_abs tglobaladdr:$absaddr)>; def : Pat<(i32 (sextloadi16 (HexagonCONST32 tglobaladdr:$absaddr))), - (LDrih_abs_V4 tglobaladdr:$absaddr)>; + (L4_loadrh_abs tglobaladdr:$absaddr)>; def : Pat<(i32 (zextloadi16 (HexagonCONST32 tglobaladdr:$absaddr))), - (LDriuh_abs_V4 tglobaladdr:$absaddr)>; -} - -//===----------------------------------------------------------------------===// -// multiclass for load instructions with GP-relative addressing mode. -// Rx=mem[bhwd](##global) -// if ([!]Pv[.new]) Rx=mem[bhwd](##global) -//===----------------------------------------------------------------------===// -let neverHasSideEffects = 1, validSubTargets = HasV4SubT in -multiclass LD_GP<string mnemonic, string BaseOp, RegisterClass RC> { - let BaseOpcode = BaseOp in { - let isPredicable = 1 in - def NAME#_V4 : LDInst2<(outs RC:$dst), - (ins globaladdress:$global), - "$dst = "#mnemonic#"(#$global)", - []>; - - let isExtended = 1, opExtendable = 2, isPredicated = 1 in { - defm Pt_V4 : LD_Abs_Pred<mnemonic, RC, 0>; - defm NotPt_V4 : LD_Abs_Pred<mnemonic, RC, 1>; - } - } + (L4_loadruh_abs tglobaladdr:$absaddr)>; } -defm LDd_GP : LD_GP<"memd", "LDd_GP", DoubleRegs>, PredNewRel; -defm LDb_GP : LD_GP<"memb", "LDb_GP", IntRegs>, PredNewRel; -defm LDub_GP : LD_GP<"memub", "LDub_GP", IntRegs>, PredNewRel; -defm LDh_GP : LD_GP<"memh", "LDh_GP", IntRegs>, PredNewRel; -defm LDuh_GP : LD_GP<"memuh", "LDuh_GP", IntRegs>, PredNewRel; -defm LDw_GP : LD_GP<"memw", "LDw_GP", IntRegs>, PredNewRel; - def : Pat <(atomic_load_64 (HexagonCONST32_GP tglobaladdr:$global)), - (i64 (LDd_GP_V4 tglobaladdr:$global))>; + (i64 (L2_loadrdgp tglobaladdr:$global))>; def : Pat <(atomic_load_32 (HexagonCONST32_GP tglobaladdr:$global)), - (i32 (LDw_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrigp tglobaladdr:$global))>; def : Pat <(atomic_load_16 (HexagonCONST32_GP tglobaladdr:$global)), - (i32 (LDuh_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadruhgp tglobaladdr:$global))>; def : Pat <(atomic_load_8 (HexagonCONST32_GP tglobaladdr:$global)), - (i32 (LDub_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrubgp tglobaladdr:$global))>; // Map from load(globaladdress) -> memw(#foo + 0) let AddedComplexity = 100 in def : Pat <(i64 (load (HexagonCONST32_GP tglobaladdr:$global))), - (i64 (LDd_GP_V4 tglobaladdr:$global))>; + (i64 (L2_loadrdgp tglobaladdr:$global))>; // Map from Pd = load(globaladdress) -> Rd = memb(globaladdress), Pd = Rd let AddedComplexity = 100 in def : Pat <(i1 (load (HexagonCONST32_GP tglobaladdr:$global))), - (i1 (TFR_PdRs (i32 (LDb_GP_V4 tglobaladdr:$global))))>; + (i1 (C2_tfrrp (i32 (L2_loadrbgp tglobaladdr:$global))))>; // When the Interprocedural Global Variable optimizer realizes that a certain // global variable takes only two constant values, it shrinks the global to // a boolean. Catch those loads here in the following 3 patterns. let AddedComplexity = 100 in def : Pat <(i32 (extloadi1 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrbgp tglobaladdr:$global))>; let AddedComplexity = 100 in def : Pat <(i32 (sextloadi1 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrbgp tglobaladdr:$global))>; // Map from load(globaladdress) -> memb(#foo) let AddedComplexity = 100 in def : Pat <(i32 (extloadi8 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrbgp tglobaladdr:$global))>; // Map from load(globaladdress) -> memb(#foo) let AddedComplexity = 100 in def : Pat <(i32 (sextloadi8 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrbgp tglobaladdr:$global))>; let AddedComplexity = 100 in def : Pat <(i32 (zextloadi1 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDub_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrubgp tglobaladdr:$global))>; // Map from load(globaladdress) -> memub(#foo) let AddedComplexity = 100 in def : Pat <(i32 (zextloadi8 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDub_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrubgp tglobaladdr:$global))>; // Map from load(globaladdress) -> memh(#foo) let AddedComplexity = 100 in def : Pat <(i32 (extloadi16 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDh_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrhgp tglobaladdr:$global))>; // Map from load(globaladdress) -> memh(#foo) let AddedComplexity = 100 in def : Pat <(i32 (sextloadi16 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDh_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrhgp tglobaladdr:$global))>; // Map from load(globaladdress) -> memuh(#foo) let AddedComplexity = 100 in def : Pat <(i32 (zextloadi16 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDuh_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadruhgp tglobaladdr:$global))>; // Map from load(globaladdress) -> memw(#foo) let AddedComplexity = 100 in def : Pat <(i32 (load (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDw_GP_V4 tglobaladdr:$global))>; + (i32 (L2_loadrigp tglobaladdr:$global))>; // Transfer global address into a register @@ -3073,7 +3798,7 @@ def : Pat<(HexagonCONST32_GP tblockaddress:$src1), Requires<[HasV4T]>; let isExtended = 1, opExtendable = 2, AddedComplexity=50, -neverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in +hasSideEffects = 0, isPredicated = 1, validSubTargets = HasV4SubT in def TFRI_cPt_V4 : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, s16Ext:$src2), "if($src1) $dst = #$src2", @@ -3081,7 +3806,7 @@ def TFRI_cPt_V4 : ALU32_ri<(outs IntRegs:$dst), Requires<[HasV4T]>; let isExtended = 1, opExtendable = 2, AddedComplexity=50, isPredicatedFalse = 1, -neverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in +hasSideEffects = 0, isPredicated = 1, validSubTargets = HasV4SubT in def TFRI_cNotPt_V4 : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, s16Ext:$src2), "if(!$src1) $dst = #$src2", @@ -3089,7 +3814,7 @@ def TFRI_cNotPt_V4 : ALU32_ri<(outs IntRegs:$dst), Requires<[HasV4T]>; let isExtended = 1, opExtendable = 2, AddedComplexity=50, -neverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in +hasSideEffects = 0, isPredicated = 1, validSubTargets = HasV4SubT in def TFRI_cdnPt_V4 : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, s16Ext:$src2), "if($src1.new) $dst = #$src2", @@ -3097,7 +3822,7 @@ def TFRI_cdnPt_V4 : ALU32_ri<(outs IntRegs:$dst), Requires<[HasV4T]>; let isExtended = 1, opExtendable = 2, AddedComplexity=50, isPredicatedFalse = 1, -neverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in +hasSideEffects = 0, isPredicated = 1, validSubTargets = HasV4SubT in def TFRI_cdnNotPt_V4 : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, s16Ext:$src2), "if(!$src1.new) $dst = #$src2", @@ -3157,30 +3882,30 @@ def : Pat <(i32 (zextloadi8 (add IntRegs:$src1, let Predicates = [HasV4T], AddedComplexity = 30 in { def : Pat<(truncstorei8 (i32 IntRegs:$src1), u0AlwaysExtPred:$src2), - (STrib_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; + (S2_storerbabs u0AlwaysExtPred:$src2, IntRegs: $src1)>; def : Pat<(truncstorei16 (i32 IntRegs:$src1), u0AlwaysExtPred:$src2), - (STrih_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; + (S2_storerhabs u0AlwaysExtPred:$src2, IntRegs: $src1)>; def : Pat<(store (i32 IntRegs:$src1), u0AlwaysExtPred:$src2), - (STriw_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; + (S2_storeriabs u0AlwaysExtPred:$src2, IntRegs: $src1)>; } let Predicates = [HasV4T], AddedComplexity = 30 in { def : Pat<(i32 (load u0AlwaysExtPred:$src)), - (LDriw_abs_V4 u0AlwaysExtPred:$src)>; + (L4_loadri_abs u0AlwaysExtPred:$src)>; def : Pat<(i32 (sextloadi8 u0AlwaysExtPred:$src)), - (LDrib_abs_V4 u0AlwaysExtPred:$src)>; + (L4_loadrb_abs u0AlwaysExtPred:$src)>; def : Pat<(i32 (zextloadi8 u0AlwaysExtPred:$src)), - (LDriub_abs_V4 u0AlwaysExtPred:$src)>; + (L4_loadrub_abs u0AlwaysExtPred:$src)>; def : Pat<(i32 (sextloadi16 u0AlwaysExtPred:$src)), - (LDrih_abs_V4 u0AlwaysExtPred:$src)>; + (L4_loadrh_abs u0AlwaysExtPred:$src)>; def : Pat<(i32 (zextloadi16 u0AlwaysExtPred:$src)), - (LDriuh_abs_V4 u0AlwaysExtPred:$src)>; + (L4_loadruh_abs u0AlwaysExtPred:$src)>; } // Indexed store word - global address. @@ -3194,11 +3919,11 @@ def STriw_offset_ext_V4 : STInst<(outs), Requires<[HasV4T]>; def : Pat<(i64 (ctlz (i64 DoubleRegs:$src1))), - (i64 (COMBINE_Ir_V4 (i32 0), (i32 (CTLZ64_rr DoubleRegs:$src1))))>, + (i64 (A4_combineir (i32 0), (i32 (CTLZ64_rr DoubleRegs:$src1))))>, Requires<[HasV4T]>; def : Pat<(i64 (cttz (i64 DoubleRegs:$src1))), - (i64 (COMBINE_Ir_V4 (i32 0), (i32 (CTTZ64_rr DoubleRegs:$src1))))>, + (i64 (A4_combineir (i32 0), (i32 (CTTZ64_rr DoubleRegs:$src1))))>, Requires<[HasV4T]>; @@ -3207,49 +3932,49 @@ def : Pat<(i64 (cttz (i64 DoubleRegs:$src1))), // zextloadi8. let Predicates = [HasV4T], AddedComplexity = 120 in { def: Pat <(i64 (extloadi8 (NumUsesBelowThresCONST32 tglobaladdr:$addr))), - (i64 (COMBINE_Ir_V4 0, (LDrib_abs_V4 tglobaladdr:$addr)))>; + (i64 (A4_combineir 0, (L4_loadrb_abs tglobaladdr:$addr)))>; def: Pat <(i64 (zextloadi8 (NumUsesBelowThresCONST32 tglobaladdr:$addr))), - (i64 (COMBINE_Ir_V4 0, (LDriub_abs_V4 tglobaladdr:$addr)))>; + (i64 (A4_combineir 0, (L4_loadrub_abs tglobaladdr:$addr)))>; def: Pat <(i64 (sextloadi8 (NumUsesBelowThresCONST32 tglobaladdr:$addr))), - (i64 (SXTW (LDrib_abs_V4 tglobaladdr:$addr)))>; + (i64 (A2_sxtw (L4_loadrb_abs tglobaladdr:$addr)))>; def: Pat <(i64 (extloadi8 FoldGlobalAddr:$addr)), - (i64 (COMBINE_Ir_V4 0, (LDrib_abs_V4 FoldGlobalAddr:$addr)))>; + (i64 (A4_combineir 0, (L4_loadrb_abs FoldGlobalAddr:$addr)))>; def: Pat <(i64 (zextloadi8 FoldGlobalAddr:$addr)), - (i64 (COMBINE_Ir_V4 0, (LDriub_abs_V4 FoldGlobalAddr:$addr)))>; + (i64 (A4_combineir 0, (L4_loadrub_abs FoldGlobalAddr:$addr)))>; def: Pat <(i64 (sextloadi8 FoldGlobalAddr:$addr)), - (i64 (SXTW (LDrib_abs_V4 FoldGlobalAddr:$addr)))>; + (i64 (A2_sxtw (L4_loadrb_abs FoldGlobalAddr:$addr)))>; } // i16 -> i64 loads // We need a complexity of 120 here to override preceding handling of // zextloadi16. let AddedComplexity = 120 in { def: Pat <(i64 (extloadi16 (NumUsesBelowThresCONST32 tglobaladdr:$addr))), - (i64 (COMBINE_Ir_V4 0, (LDrih_abs_V4 tglobaladdr:$addr)))>, + (i64 (A4_combineir 0, (L4_loadrh_abs tglobaladdr:$addr)))>, Requires<[HasV4T]>; def: Pat <(i64 (zextloadi16 (NumUsesBelowThresCONST32 tglobaladdr:$addr))), - (i64 (COMBINE_Ir_V4 0, (LDriuh_abs_V4 tglobaladdr:$addr)))>, + (i64 (A4_combineir 0, (L4_loadruh_abs tglobaladdr:$addr)))>, Requires<[HasV4T]>; def: Pat <(i64 (sextloadi16 (NumUsesBelowThresCONST32 tglobaladdr:$addr))), - (i64 (SXTW (LDrih_abs_V4 tglobaladdr:$addr)))>, + (i64 (A2_sxtw (L4_loadrh_abs tglobaladdr:$addr)))>, Requires<[HasV4T]>; def: Pat <(i64 (extloadi16 FoldGlobalAddr:$addr)), - (i64 (COMBINE_Ir_V4 0, (LDrih_abs_V4 FoldGlobalAddr:$addr)))>, + (i64 (A4_combineir 0, (L4_loadrh_abs FoldGlobalAddr:$addr)))>, Requires<[HasV4T]>; def: Pat <(i64 (zextloadi16 FoldGlobalAddr:$addr)), - (i64 (COMBINE_Ir_V4 0, (LDriuh_abs_V4 FoldGlobalAddr:$addr)))>, + (i64 (A4_combineir 0, (L4_loadruh_abs FoldGlobalAddr:$addr)))>, Requires<[HasV4T]>; def: Pat <(i64 (sextloadi16 FoldGlobalAddr:$addr)), - (i64 (SXTW (LDrih_abs_V4 FoldGlobalAddr:$addr)))>, + (i64 (A2_sxtw (L4_loadrh_abs FoldGlobalAddr:$addr)))>, Requires<[HasV4T]>; } // i32->i64 loads @@ -3257,27 +3982,27 @@ def: Pat <(i64 (sextloadi16 FoldGlobalAddr:$addr)), // zextloadi32. let AddedComplexity = 120 in { def: Pat <(i64 (extloadi32 (NumUsesBelowThresCONST32 tglobaladdr:$addr))), - (i64 (COMBINE_Ir_V4 0, (LDriw_abs_V4 tglobaladdr:$addr)))>, + (i64 (A4_combineir 0, (L4_loadri_abs tglobaladdr:$addr)))>, Requires<[HasV4T]>; def: Pat <(i64 (zextloadi32 (NumUsesBelowThresCONST32 tglobaladdr:$addr))), - (i64 (COMBINE_Ir_V4 0, (LDriw_abs_V4 tglobaladdr:$addr)))>, + (i64 (A4_combineir 0, (L4_loadri_abs tglobaladdr:$addr)))>, Requires<[HasV4T]>; def: Pat <(i64 (sextloadi32 (NumUsesBelowThresCONST32 tglobaladdr:$addr))), - (i64 (SXTW (LDriw_abs_V4 tglobaladdr:$addr)))>, + (i64 (A2_sxtw (L4_loadri_abs tglobaladdr:$addr)))>, Requires<[HasV4T]>; def: Pat <(i64 (extloadi32 FoldGlobalAddr:$addr)), - (i64 (COMBINE_Ir_V4 0, (LDriw_abs_V4 FoldGlobalAddr:$addr)))>, + (i64 (A4_combineir 0, (L4_loadri_abs FoldGlobalAddr:$addr)))>, Requires<[HasV4T]>; def: Pat <(i64 (zextloadi32 FoldGlobalAddr:$addr)), - (i64 (COMBINE_Ir_V4 0, (LDriw_abs_V4 FoldGlobalAddr:$addr)))>, + (i64 (A4_combineir 0, (L4_loadri_abs FoldGlobalAddr:$addr)))>, Requires<[HasV4T]>; def: Pat <(i64 (sextloadi32 FoldGlobalAddr:$addr)), - (i64 (SXTW (LDriw_abs_V4 FoldGlobalAddr:$addr)))>, + (i64 (A2_sxtw (L4_loadri_abs FoldGlobalAddr:$addr)))>, Requires<[HasV4T]>; } @@ -3294,104 +4019,457 @@ def STrih_offset_ext_V4 : STInst<(outs), let AddedComplexity = 100 in def : Pat<(store (i64 DoubleRegs:$src1), FoldGlobalAddrGP:$addr), - (STrid_abs_V4 FoldGlobalAddrGP:$addr, (i64 DoubleRegs:$src1))>, + (S2_storerdabs FoldGlobalAddrGP:$addr, (i64 DoubleRegs:$src1))>, Requires<[HasV4T]>; def : Pat<(atomic_store_64 FoldGlobalAddrGP:$addr, (i64 DoubleRegs:$src1)), - (STrid_abs_V4 FoldGlobalAddrGP:$addr, (i64 DoubleRegs:$src1))>, + (S2_storerdabs FoldGlobalAddrGP:$addr, (i64 DoubleRegs:$src1))>, Requires<[HasV4T]>; // Map from store(globaladdress + x) -> memb(#foo + x) let AddedComplexity = 100 in def : Pat<(truncstorei8 (i32 IntRegs:$src1), FoldGlobalAddrGP:$addr), - (STrib_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + (S2_storerbabs FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, Requires<[HasV4T]>; def : Pat<(atomic_store_8 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1)), - (STrib_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + (S2_storerbabs FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, Requires<[HasV4T]>; // Map from store(globaladdress + x) -> memh(#foo + x) let AddedComplexity = 100 in def : Pat<(truncstorei16 (i32 IntRegs:$src1), FoldGlobalAddrGP:$addr), - (STrih_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + (S2_storerhabs FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, Requires<[HasV4T]>; def : Pat<(atomic_store_16 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1)), - (STrih_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + (S2_storerhabs FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, Requires<[HasV4T]>; // Map from store(globaladdress + x) -> memw(#foo + x) let AddedComplexity = 100 in def : Pat<(store (i32 IntRegs:$src1), FoldGlobalAddrGP:$addr), - (STriw_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + (S2_storeriabs FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, Requires<[HasV4T]>; def : Pat<(atomic_store_32 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1)), - (STriw_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + (S2_storeriabs FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, Requires<[HasV4T]>; // Map from load(globaladdress + x) -> memd(#foo + x) let AddedComplexity = 100 in def : Pat<(i64 (load FoldGlobalAddrGP:$addr)), - (i64 (LDrid_abs_V4 FoldGlobalAddrGP:$addr))>, + (i64 (L4_loadrd_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; def : Pat<(atomic_load_64 FoldGlobalAddrGP:$addr), - (i64 (LDrid_abs_V4 FoldGlobalAddrGP:$addr))>, + (i64 (L4_loadrd_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; // Map from load(globaladdress + x) -> memb(#foo + x) let AddedComplexity = 100 in def : Pat<(i32 (extloadi8 FoldGlobalAddrGP:$addr)), - (i32 (LDrib_abs_V4 FoldGlobalAddrGP:$addr))>, + (i32 (L4_loadrb_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; // Map from load(globaladdress + x) -> memb(#foo + x) let AddedComplexity = 100 in def : Pat<(i32 (sextloadi8 FoldGlobalAddrGP:$addr)), - (i32 (LDrib_abs_V4 FoldGlobalAddrGP:$addr))>, + (i32 (L4_loadrb_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; //let AddedComplexity = 100 in let AddedComplexity = 100 in def : Pat<(i32 (extloadi16 FoldGlobalAddrGP:$addr)), - (i32 (LDrih_abs_V4 FoldGlobalAddrGP:$addr))>, + (i32 (L4_loadrh_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; // Map from load(globaladdress + x) -> memh(#foo + x) let AddedComplexity = 100 in def : Pat<(i32 (sextloadi16 FoldGlobalAddrGP:$addr)), - (i32 (LDrih_abs_V4 FoldGlobalAddrGP:$addr))>, + (i32 (L4_loadrh_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; // Map from load(globaladdress + x) -> memuh(#foo + x) let AddedComplexity = 100 in def : Pat<(i32 (zextloadi16 FoldGlobalAddrGP:$addr)), - (i32 (LDriuh_abs_V4 FoldGlobalAddrGP:$addr))>, + (i32 (L4_loadruh_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; def : Pat<(atomic_load_16 FoldGlobalAddrGP:$addr), - (i32 (LDriuh_abs_V4 FoldGlobalAddrGP:$addr))>, + (i32 (L4_loadruh_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; // Map from load(globaladdress + x) -> memub(#foo + x) let AddedComplexity = 100 in def : Pat<(i32 (zextloadi8 FoldGlobalAddrGP:$addr)), - (i32 (LDriub_abs_V4 FoldGlobalAddrGP:$addr))>, + (i32 (L4_loadrub_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; def : Pat<(atomic_load_8 FoldGlobalAddrGP:$addr), - (i32 (LDriub_abs_V4 FoldGlobalAddrGP:$addr))>, + (i32 (L4_loadrub_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; // Map from load(globaladdress + x) -> memw(#foo + x) let AddedComplexity = 100 in def : Pat<(i32 (load FoldGlobalAddrGP:$addr)), - (i32 (LDriw_abs_V4 FoldGlobalAddrGP:$addr))>, + (i32 (L4_loadri_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; def : Pat<(atomic_load_32 FoldGlobalAddrGP:$addr), - (i32 (LDriw_abs_V4 FoldGlobalAddrGP:$addr))>, + (i32 (L4_loadri_abs FoldGlobalAddrGP:$addr))>, Requires<[HasV4T]>; + +//===----------------------------------------------------------------------===// +// :raw for of boundscheck:hi:lo insns +//===----------------------------------------------------------------------===// + +// A4_boundscheck_lo: Detect if a register is within bounds. +let hasSideEffects = 0, isCodeGenOnly = 0 in +def A4_boundscheck_lo: ALU64Inst < + (outs PredRegs:$Pd), + (ins DoubleRegs:$Rss, DoubleRegs:$Rtt), + "$Pd = boundscheck($Rss, $Rtt):raw:lo"> { + bits<2> Pd; + bits<5> Rss; + bits<5> Rtt; + + let IClass = 0b1101; + + let Inst{27-23} = 0b00100; + let Inst{13} = 0b1; + let Inst{7-5} = 0b100; + let Inst{1-0} = Pd; + let Inst{20-16} = Rss; + let Inst{12-8} = Rtt; + } + +// A4_boundscheck_hi: Detect if a register is within bounds. +let hasSideEffects = 0, isCodeGenOnly = 0 in +def A4_boundscheck_hi: ALU64Inst < + (outs PredRegs:$Pd), + (ins DoubleRegs:$Rss, DoubleRegs:$Rtt), + "$Pd = boundscheck($Rss, $Rtt):raw:hi"> { + bits<2> Pd; + bits<5> Rss; + bits<5> Rtt; + + let IClass = 0b1101; + + let Inst{27-23} = 0b00100; + let Inst{13} = 0b1; + let Inst{7-5} = 0b101; + let Inst{1-0} = Pd; + let Inst{20-16} = Rss; + let Inst{12-8} = Rtt; + } + +let hasSideEffects = 0 in +def A4_boundscheck : MInst < + (outs PredRegs:$Pd), (ins IntRegs:$Rs, DoubleRegs:$Rtt), + "$Pd=boundscheck($Rs,$Rtt)">; + +// A4_tlbmatch: Detect if a VA/ASID matches a TLB entry. +let isPredicateLate = 1, hasSideEffects = 0, isCodeGenOnly = 0 in +def A4_tlbmatch : ALU64Inst<(outs PredRegs:$Pd), + (ins DoubleRegs:$Rs, IntRegs:$Rt), + "$Pd = tlbmatch($Rs, $Rt)", + [], "", ALU64_tc_2early_SLOT23> { + bits<2> Pd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1101; + let Inst{27-23} = 0b00100; + let Inst{20-16} = Rs; + let Inst{13} = 0b1; + let Inst{12-8} = Rt; + let Inst{7-5} = 0b011; + let Inst{1-0} = Pd; + } + +// We need custom lowering of ISD::PREFETCH into HexagonISD::DCFETCH +// because the SDNode ISD::PREFETCH has properties MayLoad and MayStore. +// We don't really want either one here. +def SDTHexagonDCFETCH : SDTypeProfile<0, 2, [SDTCisPtrTy<0>,SDTCisInt<1>]>; +def HexagonDCFETCH : SDNode<"HexagonISD::DCFETCH", SDTHexagonDCFETCH, + [SDNPHasChain]>; + +// Use LD0Inst for dcfetch, but set "mayLoad" to 0 because this doesn't +// really do a load. +let hasSideEffects = 1, mayLoad = 0, isCodeGenOnly = 0 in +def Y2_dcfetchbo : LD0Inst<(outs), (ins IntRegs:$Rs, u11_3Imm:$u11_3), + "dcfetch($Rs + #$u11_3)", + [(HexagonDCFETCH IntRegs:$Rs, u11_3ImmPred:$u11_3)], + "", LD_tc_ld_SLOT0> { + bits<5> Rs; + bits<14> u11_3; + + let IClass = 0b1001; + let Inst{27-21} = 0b0100000; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{10-0} = u11_3{13-3}; +} + +//===----------------------------------------------------------------------===// +// Compound instructions +//===----------------------------------------------------------------------===// + +let isBranch = 1, hasSideEffects = 0, isExtentSigned = 1, + isPredicated = 1, isPredicatedNew = 1, isExtendable = 1, + opExtentBits = 11, opExtentAlign = 2, opExtendable = 1, + isTerminator = 1, validSubTargets = HasV4SubT in +class CJInst_tstbit_R0<string px, bit np, string tnt> + : InstHexagon<(outs), (ins IntRegs:$Rs, brtarget:$r9_2), + ""#px#" = tstbit($Rs, #0); if (" + #!if(np, "!","")#""#px#".new) jump:"#tnt#" $r9_2", + [], "", COMPOUND, TypeCOMPOUND> { + bits<4> Rs; + bits<11> r9_2; + + // np: !p[01] + let isPredicatedFalse = np; + // tnt: Taken/Not Taken + let isBrTaken = !if (!eq(tnt, "t"), "true", "false"); + let isTaken = !if (!eq(tnt, "t"), 1, 0); + + let IClass = 0b0001; + let Inst{27-26} = 0b00; + let Inst{25} = !if (!eq(px, "!p1"), 1, + !if (!eq(px, "p1"), 1, 0)); + let Inst{24-23} = 0b11; + let Inst{22} = np; + let Inst{21-20} = r9_2{10-9}; + let Inst{19-16} = Rs; + let Inst{13} = !if (!eq(tnt, "t"), 1, 0); + let Inst{9-8} = 0b11; + let Inst{7-1} = r9_2{8-2}; +} + +let Defs = [PC, P0], Uses = [P0], isCodeGenOnly = 0 in { + def J4_tstbit0_tp0_jump_nt : CJInst_tstbit_R0<"p0", 0, "nt">; + def J4_tstbit0_tp0_jump_t : CJInst_tstbit_R0<"p0", 0, "t">; + def J4_tstbit0_fp0_jump_nt : CJInst_tstbit_R0<"p0", 1, "nt">; + def J4_tstbit0_fp0_jump_t : CJInst_tstbit_R0<"p0", 1, "t">; +} + +let Defs = [PC, P1], Uses = [P1], isCodeGenOnly = 0 in { + def J4_tstbit0_tp1_jump_nt : CJInst_tstbit_R0<"p1", 0, "nt">; + def J4_tstbit0_tp1_jump_t : CJInst_tstbit_R0<"p1", 0, "t">; + def J4_tstbit0_fp1_jump_nt : CJInst_tstbit_R0<"p1", 1, "nt">; + def J4_tstbit0_fp1_jump_t : CJInst_tstbit_R0<"p1", 1, "t">; +} + + +let isBranch = 1, hasSideEffects = 0, + isExtentSigned = 1, isPredicated = 1, isPredicatedNew = 1, + isExtendable = 1, opExtentBits = 11, opExtentAlign = 2, + opExtendable = 2, isTerminator = 1, validSubTargets = HasV4SubT in +class CJInst_RR<string px, string op, bit np, string tnt> + : InstHexagon<(outs), (ins IntRegs:$Rs, IntRegs:$Rt, brtarget:$r9_2), + ""#px#" = cmp."#op#"($Rs, $Rt); if (" + #!if(np, "!","")#""#px#".new) jump:"#tnt#" $r9_2", + [], "", COMPOUND, TypeCOMPOUND> { + bits<4> Rs; + bits<4> Rt; + bits<11> r9_2; + + // np: !p[01] + let isPredicatedFalse = np; + // tnt: Taken/Not Taken + let isBrTaken = !if (!eq(tnt, "t"), "true", "false"); + let isTaken = !if (!eq(tnt, "t"), 1, 0); + + let IClass = 0b0001; + let Inst{27-23} = !if (!eq(op, "eq"), 0b01000, + !if (!eq(op, "gt"), 0b01001, + !if (!eq(op, "gtu"), 0b01010, 0))); + let Inst{22} = np; + let Inst{21-20} = r9_2{10-9}; + let Inst{19-16} = Rs; + let Inst{13} = !if (!eq(tnt, "t"), 1, 0); + // px: Predicate reg 0/1 + let Inst{12} = !if (!eq(px, "!p1"), 1, + !if (!eq(px, "p1"), 1, 0)); + let Inst{11-8} = Rt; + let Inst{7-1} = r9_2{8-2}; +} + +// P[10] taken/not taken. +multiclass T_tnt_CJInst_RR<string op, bit np> { + let Defs = [PC, P0], Uses = [P0] in { + def NAME#p0_jump_nt : CJInst_RR<"p0", op, np, "nt">; + def NAME#p0_jump_t : CJInst_RR<"p0", op, np, "t">; + } + let Defs = [PC, P1], Uses = [P1] in { + def NAME#p1_jump_nt : CJInst_RR<"p1", op, np, "nt">; + def NAME#p1_jump_t : CJInst_RR<"p1", op, np, "t">; + } +} +// Predicate / !Predicate +multiclass T_pnp_CJInst_RR<string op>{ + defm J4_cmp#NAME#_t : T_tnt_CJInst_RR<op, 0>; + defm J4_cmp#NAME#_f : T_tnt_CJInst_RR<op, 1>; +} +// TypeCJ Instructions compare RR and jump +let isCodeGenOnly = 0 in { +defm eq : T_pnp_CJInst_RR<"eq">; +defm gt : T_pnp_CJInst_RR<"gt">; +defm gtu : T_pnp_CJInst_RR<"gtu">; +} + +let isBranch = 1, hasSideEffects = 0, isExtentSigned = 1, + isPredicated = 1, isPredicatedNew = 1, isExtendable = 1, opExtentBits = 11, + opExtentAlign = 2, opExtendable = 2, isTerminator = 1, + validSubTargets = HasV4SubT in +class CJInst_RU5<string px, string op, bit np, string tnt> + : InstHexagon<(outs), (ins IntRegs:$Rs, u5Imm:$U5, brtarget:$r9_2), + ""#px#" = cmp."#op#"($Rs, #$U5); if (" + #!if(np, "!","")#""#px#".new) jump:"#tnt#" $r9_2", + [], "", COMPOUND, TypeCOMPOUND> { + bits<4> Rs; + bits<5> U5; + bits<11> r9_2; + + // np: !p[01] + let isPredicatedFalse = np; + // tnt: Taken/Not Taken + let isBrTaken = !if (!eq(tnt, "t"), "true", "false"); + let isTaken = !if (!eq(tnt, "t"), 1, 0); + + let IClass = 0b0001; + let Inst{27-26} = 0b00; + // px: Predicate reg 0/1 + let Inst{25} = !if (!eq(px, "!p1"), 1, + !if (!eq(px, "p1"), 1, 0)); + let Inst{24-23} = !if (!eq(op, "eq"), 0b00, + !if (!eq(op, "gt"), 0b01, + !if (!eq(op, "gtu"), 0b10, 0))); + let Inst{22} = np; + let Inst{21-20} = r9_2{10-9}; + let Inst{19-16} = Rs; + let Inst{13} = !if (!eq(tnt, "t"), 1, 0); + let Inst{12-8} = U5; + let Inst{7-1} = r9_2{8-2}; +} +// P[10] taken/not taken. +multiclass T_tnt_CJInst_RU5<string op, bit np> { + let Defs = [PC, P0], Uses = [P0] in { + def NAME#p0_jump_nt : CJInst_RU5<"p0", op, np, "nt">; + def NAME#p0_jump_t : CJInst_RU5<"p0", op, np, "t">; + } + let Defs = [PC, P1], Uses = [P1] in { + def NAME#p1_jump_nt : CJInst_RU5<"p1", op, np, "nt">; + def NAME#p1_jump_t : CJInst_RU5<"p1", op, np, "t">; + } +} +// Predicate / !Predicate +multiclass T_pnp_CJInst_RU5<string op>{ + defm J4_cmp#NAME#i_t : T_tnt_CJInst_RU5<op, 0>; + defm J4_cmp#NAME#i_f : T_tnt_CJInst_RU5<op, 1>; +} +// TypeCJ Instructions compare RI and jump +let isCodeGenOnly = 0 in { +defm eq : T_pnp_CJInst_RU5<"eq">; +defm gt : T_pnp_CJInst_RU5<"gt">; +defm gtu : T_pnp_CJInst_RU5<"gtu">; +} + +let isBranch = 1, hasSideEffects = 0, isExtentSigned = 1, + isPredicated = 1, isPredicatedFalse = 1, isPredicatedNew = 1, + isExtendable = 1, opExtentBits = 11, opExtentAlign = 2, opExtendable = 1, + isTerminator = 1, validSubTargets = HasV4SubT in +class CJInst_Rn1<string px, string op, bit np, string tnt> + : InstHexagon<(outs), (ins IntRegs:$Rs, brtarget:$r9_2), + ""#px#" = cmp."#op#"($Rs,#-1); if (" + #!if(np, "!","")#""#px#".new) jump:"#tnt#" $r9_2", + [], "", COMPOUND, TypeCOMPOUND> { + bits<4> Rs; + bits<11> r9_2; + + // np: !p[01] + let isPredicatedFalse = np; + // tnt: Taken/Not Taken + let isBrTaken = !if (!eq(tnt, "t"), "true", "false"); + let isTaken = !if (!eq(tnt, "t"), 1, 0); + + let IClass = 0b0001; + let Inst{27-26} = 0b00; + let Inst{25} = !if (!eq(px, "!p1"), 1, + !if (!eq(px, "p1"), 1, 0)); + + let Inst{24-23} = 0b11; + let Inst{22} = np; + let Inst{21-20} = r9_2{10-9}; + let Inst{19-16} = Rs; + let Inst{13} = !if (!eq(tnt, "t"), 1, 0); + let Inst{9-8} = !if (!eq(op, "eq"), 0b00, + !if (!eq(op, "gt"), 0b01, 0)); + let Inst{7-1} = r9_2{8-2}; +} + +// P[10] taken/not taken. +multiclass T_tnt_CJInst_Rn1<string op, bit np> { + let Defs = [PC, P0], Uses = [P0] in { + def NAME#p0_jump_nt : CJInst_Rn1<"p0", op, np, "nt">; + def NAME#p0_jump_t : CJInst_Rn1<"p0", op, np, "t">; + } + let Defs = [PC, P1], Uses = [P1] in { + def NAME#p1_jump_nt : CJInst_Rn1<"p1", op, np, "nt">; + def NAME#p1_jump_t : CJInst_Rn1<"p1", op, np, "t">; + } +} +// Predicate / !Predicate +multiclass T_pnp_CJInst_Rn1<string op>{ + defm J4_cmp#NAME#n1_t : T_tnt_CJInst_Rn1<op, 0>; + defm J4_cmp#NAME#n1_f : T_tnt_CJInst_Rn1<op, 1>; +} +// TypeCJ Instructions compare -1 and jump +let isCodeGenOnly = 0 in { +defm eq : T_pnp_CJInst_Rn1<"eq">; +defm gt : T_pnp_CJInst_Rn1<"gt">; +} + +// J4_jumpseti: Direct unconditional jump and set register to immediate. +let Defs = [PC], isBranch = 1, hasSideEffects = 0, hasNewValue = 1, + isExtentSigned = 1, opNewValue = 0, isExtendable = 1, opExtentBits = 11, + opExtentAlign = 2, opExtendable = 2, validSubTargets = HasV4SubT, + isCodeGenOnly = 0 in +def J4_jumpseti: CJInst < + (outs IntRegs:$Rd), + (ins u6Imm:$U6, brtarget:$r9_2), + "$Rd = #$U6 ; jump $r9_2"> { + bits<4> Rd; + bits<6> U6; + bits<11> r9_2; + + let IClass = 0b0001; + let Inst{27-24} = 0b0110; + let Inst{21-20} = r9_2{10-9}; + let Inst{19-16} = Rd; + let Inst{13-8} = U6; + let Inst{7-1} = r9_2{8-2}; + } + +// J4_jumpsetr: Direct unconditional jump and transfer register. +let Defs = [PC], isBranch = 1, hasSideEffects = 0, hasNewValue = 1, + isExtentSigned = 1, opNewValue = 0, isExtendable = 1, opExtentBits = 11, + opExtentAlign = 2, opExtendable = 2, validSubTargets = HasV4SubT, + isCodeGenOnly = 0 in +def J4_jumpsetr: CJInst < + (outs IntRegs:$Rd), + (ins IntRegs:$Rs, brtarget:$r9_2), + "$Rd = $Rs ; jump $r9_2"> { + bits<4> Rd; + bits<4> Rs; + bits<11> r9_2; + + let IClass = 0b0001; + let Inst{27-24} = 0b0111; + let Inst{21-20} = r9_2{10-9}; + let Inst{11-8} = Rd; + let Inst{19-16} = Rs; + let Inst{7-1} = r9_2{8-2}; + } diff --git a/lib/Target/Hexagon/HexagonInstrInfoV5.td b/lib/Target/Hexagon/HexagonInstrInfoV5.td index 9da607455811..5674aa3ccd83 100644 --- a/lib/Target/Hexagon/HexagonInstrInfoV5.td +++ b/lib/Target/Hexagon/HexagonInstrInfoV5.td @@ -1,3 +1,42 @@ +//=- HexagonInstrInfoV5.td - Target Desc. for Hexagon Target -*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Hexagon V5 instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// XTYPE/MPY +//===----------------------------------------------------------------------===// + +let isCodeGenOnly = 0 in +def S2_asr_i_p_rnd : S_2OpInstImm<"asr", 0b110, 0b111, u6Imm, + [(set I64:$dst, + (sra (i64 (add (i64 (sra I64:$src1, u6ImmPred:$src2)), 1)), + (i32 1)))], 1>, + Requires<[HasV5T]> { + bits<6> src2; + let Inst{13-8} = src2; +} + +let isCodeGenOnly = 0 in +def C4_fastcorner9 : T_LOGICAL_2OP<"fastcorner9", 0b000, 0, 0>, + Requires<[HasV5T]> { + let Inst{13,7,4} = 0b111; +} + +let isCodeGenOnly = 0 in +def C4_fastcorner9_not : T_LOGICAL_2OP<"!fastcorner9", 0b000, 0, 0>, + Requires<[HasV5T]> { + let Inst{20,13,7,4} = 0b1111; +} + def SDTHexagonFCONST32 : SDTypeProfile<1, 1, [ SDTCisVT<0, f32>, SDTCisPtrTy<1>]>; @@ -37,7 +76,7 @@ def TFRI_f : ALU32_ri<(outs IntRegs:$dst), (ins f32Ext:$src1), Requires<[HasV5T]>; let isExtended = 1, opExtendable = 2, isPredicated = 1, -neverHasSideEffects = 1, validSubTargets = HasV5SubT in +hasSideEffects = 0, validSubTargets = HasV5SubT in def TFRI_cPt_f : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, f32Ext:$src2), "if ($src1) $dst = #$src2", @@ -45,13 +84,405 @@ def TFRI_cPt_f : ALU32_ri<(outs IntRegs:$dst), Requires<[HasV5T]>; let isExtended = 1, opExtendable = 2, isPredicated = 1, isPredicatedFalse = 1, -neverHasSideEffects = 1, validSubTargets = HasV5SubT in +hasSideEffects = 0, validSubTargets = HasV5SubT in def TFRI_cNotPt_f : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, f32Ext:$src2), "if (!$src1) $dst =#$src2", []>, Requires<[HasV5T]>; +def SDTHexagonI32I64: SDTypeProfile<1, 1, [SDTCisVT<0, i32>, + SDTCisVT<1, i64>]>; + +def HexagonPOPCOUNT: SDNode<"HexagonISD::POPCOUNT", SDTHexagonI32I64>; + +let hasNewValue = 1, validSubTargets = HasV5SubT, isCodeGenOnly = 0 in +def S5_popcountp : ALU64_rr<(outs IntRegs:$Rd), (ins DoubleRegs:$Rss), + "$Rd = popcount($Rss)", + [(set I32:$Rd, (HexagonPOPCOUNT I64:$Rss))], "", S_2op_tc_2_SLOT23>, + Requires<[HasV5T]> { + bits<5> Rd; + bits<5> Rss; + + let IClass = 0b1000; + + let Inst{27-21} = 0b1000011; + let Inst{7-5} = 0b011; + let Inst{4-0} = Rd; + let Inst{20-16} = Rss; + } + +let isFP = 1, hasNewValue = 1, opNewValue = 0 in +class T_MInstFloat <string mnemonic, bits<3> MajOp, bits<3> MinOp> + : MInst<(outs IntRegs:$Rd), + (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = "#mnemonic#"($Rs, $Rt)", [], + "" , M_tc_3or4x_SLOT23 > , + Requires<[HasV5T]> { + bits<5> Rd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + + let Inst{27-24} = 0b1011; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-8} = Rt; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rd; + } + +let isCommutable = 1, isCodeGenOnly = 0 in { + def F2_sfadd : T_MInstFloat < "sfadd", 0b000, 0b000>; + def F2_sfmpy : T_MInstFloat < "sfmpy", 0b010, 0b000>; +} + +let isCodeGenOnly = 0 in +def F2_sfsub : T_MInstFloat < "sfsub", 0b000, 0b001>; + +let Itinerary = M_tc_3x_SLOT23, isCodeGenOnly = 0 in { + def F2_sfmax : T_MInstFloat < "sfmax", 0b100, 0b000>; + def F2_sfmin : T_MInstFloat < "sfmin", 0b100, 0b001>; +} + +let isCodeGenOnly = 0 in { +def F2_sffixupn : T_MInstFloat < "sffixupn", 0b110, 0b000>; +def F2_sffixupd : T_MInstFloat < "sffixupd", 0b110, 0b001>; +} + +// F2_sfrecipa: Reciprocal approximation for division. +let isPredicateLate = 1, isFP = 1, +hasSideEffects = 0, hasNewValue = 1, isCodeGenOnly = 0 in +def F2_sfrecipa: MInst < + (outs IntRegs:$Rd, PredRegs:$Pe), + (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd, $Pe = sfrecipa($Rs, $Rt)">, + Requires<[HasV5T]> { + bits<5> Rd; + bits<2> Pe; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + let Inst{27-21} = 0b1011111; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-8} = Rt; + let Inst{7} = 0b1; + let Inst{6-5} = Pe; + let Inst{4-0} = Rd; + } + +// F2_dfcmpeq: Floating point compare for equal. +let isCompare = 1, isFP = 1 in +class T_fcmp <string mnemonic, RegisterClass RC, bits<3> MinOp, + list<dag> pattern = [] > + : ALU64Inst <(outs PredRegs:$dst), (ins RC:$src1, RC:$src2), + "$dst = "#mnemonic#"($src1, $src2)", pattern, + "" , ALU64_tc_2early_SLOT23 > , + Requires<[HasV5T]> { + bits<2> dst; + bits<5> src1; + bits<5> src2; + + let IClass = 0b1101; + + let Inst{27-21} = 0b0010111; + let Inst{20-16} = src1; + let Inst{12-8} = src2; + let Inst{7-5} = MinOp; + let Inst{1-0} = dst; + } + +class T_fcmp64 <string mnemonic, PatFrag OpNode, bits<3> MinOp> + : T_fcmp <mnemonic, DoubleRegs, MinOp, + [(set I1:$dst, (OpNode F64:$src1, F64:$src2))]> { + let IClass = 0b1101; + let Inst{27-21} = 0b0010111; +} + +class T_fcmp32 <string mnemonic, PatFrag OpNode, bits<3> MinOp> + : T_fcmp <mnemonic, IntRegs, MinOp, + [(set I1:$dst, (OpNode F32:$src1, F32:$src2))]> { + let IClass = 0b1100; + let Inst{27-21} = 0b0111111; +} + +let isCodeGenOnly = 0 in { +def F2_dfcmpeq : T_fcmp64<"dfcmp.eq", setoeq, 0b000>; +def F2_dfcmpgt : T_fcmp64<"dfcmp.gt", setogt, 0b001>; +def F2_dfcmpge : T_fcmp64<"dfcmp.ge", setoge, 0b010>; +def F2_dfcmpuo : T_fcmp64<"dfcmp.uo", setuo, 0b011>; + +def F2_sfcmpge : T_fcmp32<"sfcmp.ge", setoge, 0b000>; +def F2_sfcmpuo : T_fcmp32<"sfcmp.uo", setuo, 0b001>; +def F2_sfcmpeq : T_fcmp32<"sfcmp.eq", setoeq, 0b011>; +def F2_sfcmpgt : T_fcmp32<"sfcmp.gt", setogt, 0b100>; +} + +// F2 convert template classes: +let isFP = 1 in +class F2_RDD_RSS_CONVERT<string mnemonic, bits<3> MinOp, + SDNode Op, PatLeaf RCOut, PatLeaf RCIn, + string chop =""> + : SInst <(outs DoubleRegs:$Rdd), (ins DoubleRegs:$Rss), + "$Rdd = "#mnemonic#"($Rss)"#chop, + [(set RCOut:$Rdd, (Op RCIn:$Rss))], "", + S_2op_tc_3or4x_SLOT23> { + bits<5> Rdd; + bits<5> Rss; + + let IClass = 0b1000; + + let Inst{27-21} = 0b0000111; + let Inst{20-16} = Rss; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rdd; + } + +let isFP = 1 in +class F2_RDD_RS_CONVERT<string mnemonic, bits<3> MinOp, + SDNode Op, PatLeaf RCOut, PatLeaf RCIn, + string chop =""> + : SInst <(outs DoubleRegs:$Rdd), (ins IntRegs:$Rs), + "$Rdd = "#mnemonic#"($Rs)"#chop, + [(set RCOut:$Rdd, (Op RCIn:$Rs))], "", + S_2op_tc_3or4x_SLOT23> { + bits<5> Rdd; + bits<5> Rs; + + let IClass = 0b1000; + + let Inst{27-21} = 0b0100100; + let Inst{20-16} = Rs; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rdd; + } + +let isFP = 1, hasNewValue = 1 in +class F2_RD_RSS_CONVERT<string mnemonic, bits<3> MinOp, + SDNode Op, PatLeaf RCOut, PatLeaf RCIn, + string chop =""> + : SInst <(outs IntRegs:$Rd), (ins DoubleRegs:$Rss), + "$Rd = "#mnemonic#"($Rss)"#chop, + [(set RCOut:$Rd, (Op RCIn:$Rss))], "", + S_2op_tc_3or4x_SLOT23> { + bits<5> Rd; + bits<5> Rss; + + let IClass = 0b1000; + + let Inst{27-24} = 0b1000; + let Inst{23-21} = MinOp; + let Inst{20-16} = Rss; + let Inst{7-5} = 0b001; + let Inst{4-0} = Rd; + } + +let isFP = 1, hasNewValue = 1 in +class F2_RD_RS_CONVERT<string mnemonic, bits<3> MajOp, bits<3> MinOp, + SDNode Op, PatLeaf RCOut, PatLeaf RCIn, + string chop =""> + : SInst <(outs IntRegs:$Rd), (ins IntRegs:$Rs), + "$Rd = "#mnemonic#"($Rs)"#chop, + [(set RCOut:$Rd, (Op RCIn:$Rs))], "", + S_2op_tc_3or4x_SLOT23> { + bits<5> Rd; + bits<5> Rs; + + let IClass = 0b1000; + + let Inst{27-24} = 0b1011; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rd; + } + +// Convert single precision to double precision and vice-versa. +let isCodeGenOnly = 0 in { +def F2_conv_sf2df : F2_RDD_RS_CONVERT <"convert_sf2df", 0b000, + fextend, F64, F32>; + +def F2_conv_df2sf : F2_RD_RSS_CONVERT <"convert_df2sf", 0b000, + fround, F32, F64>; + +// Convert Integer to Floating Point. +def F2_conv_d2sf : F2_RD_RSS_CONVERT <"convert_d2sf", 0b010, + sint_to_fp, F32, I64>; +def F2_conv_ud2sf : F2_RD_RSS_CONVERT <"convert_ud2sf", 0b001, + uint_to_fp, F32, I64>; +def F2_conv_uw2sf : F2_RD_RS_CONVERT <"convert_uw2sf", 0b001, 0b000, + uint_to_fp, F32, I32>; +def F2_conv_w2sf : F2_RD_RS_CONVERT <"convert_w2sf", 0b010, 0b000, + sint_to_fp, F32, I32>; +def F2_conv_d2df : F2_RDD_RSS_CONVERT <"convert_d2df", 0b011, + sint_to_fp, F64, I64>; +def F2_conv_ud2df : F2_RDD_RSS_CONVERT <"convert_ud2df", 0b010, + uint_to_fp, F64, I64>; +def F2_conv_uw2df : F2_RDD_RS_CONVERT <"convert_uw2df", 0b001, + uint_to_fp, F64, I32>; +def F2_conv_w2df : F2_RDD_RS_CONVERT <"convert_w2df", 0b010, + sint_to_fp, F64, I32>; + +// Convert Floating Point to Integer - default. +def F2_conv_df2uw_chop : F2_RD_RSS_CONVERT <"convert_df2uw", 0b101, + fp_to_uint, I32, F64, ":chop">; +def F2_conv_df2w_chop : F2_RD_RSS_CONVERT <"convert_df2w", 0b111, + fp_to_sint, I32, F64, ":chop">; +def F2_conv_sf2uw_chop : F2_RD_RS_CONVERT <"convert_sf2uw", 0b011, 0b001, + fp_to_uint, I32, F32, ":chop">; +def F2_conv_sf2w_chop : F2_RD_RS_CONVERT <"convert_sf2w", 0b100, 0b001, + fp_to_sint, I32, F32, ":chop">; +def F2_conv_df2d_chop : F2_RDD_RSS_CONVERT <"convert_df2d", 0b110, + fp_to_sint, I64, F64, ":chop">; +def F2_conv_df2ud_chop : F2_RDD_RSS_CONVERT <"convert_df2ud", 0b111, + fp_to_uint, I64, F64, ":chop">; +def F2_conv_sf2d_chop : F2_RDD_RS_CONVERT <"convert_sf2d", 0b110, + fp_to_sint, I64, F32, ":chop">; +def F2_conv_sf2ud_chop : F2_RDD_RS_CONVERT <"convert_sf2ud", 0b101, + fp_to_uint, I64, F32, ":chop">; + +// Convert Floating Point to Integer: non-chopped. +let AddedComplexity = 20, Predicates = [HasV5T, IEEERndNearV5T] in { + def F2_conv_df2d : F2_RDD_RSS_CONVERT <"convert_df2d", 0b000, + fp_to_sint, I64, F64>; + def F2_conv_df2ud : F2_RDD_RSS_CONVERT <"convert_df2ud", 0b001, + fp_to_uint, I64, F64>; + def F2_conv_sf2ud : F2_RDD_RS_CONVERT <"convert_sf2ud", 0b011, + fp_to_uint, I64, F32>; + def F2_conv_sf2d : F2_RDD_RS_CONVERT <"convert_sf2d", 0b100, + fp_to_sint, I64, F32>; + def F2_conv_df2uw : F2_RD_RSS_CONVERT <"convert_df2uw", 0b011, + fp_to_uint, I32, F64>; + def F2_conv_df2w : F2_RD_RSS_CONVERT <"convert_df2w", 0b100, + fp_to_sint, I32, F64>; + def F2_conv_sf2uw : F2_RD_RS_CONVERT <"convert_sf2uw", 0b011, 0b000, + fp_to_uint, I32, F32>; + def F2_conv_sf2w : F2_RD_RS_CONVERT <"convert_sf2w", 0b100, 0b000, + fp_to_sint, I32, F32>; +} +} + +// Fix up radicand. +let isFP = 1, hasNewValue = 1, isCodeGenOnly = 0 in +def F2_sffixupr: SInst<(outs IntRegs:$Rd), (ins IntRegs:$Rs), + "$Rd = sffixupr($Rs)", + [], "" , S_2op_tc_3or4x_SLOT23>, Requires<[HasV5T]> { + bits<5> Rd; + bits<5> Rs; + + let IClass = 0b1000; + + let Inst{27-21} = 0b1011101; + let Inst{20-16} = Rs; + let Inst{7-5} = 0b000; + let Inst{4-0} = Rd; + } + +// F2_sffma: Floating-point fused multiply add. +let isFP = 1, hasNewValue = 1 in +class T_sfmpy_acc <bit isSub, bit isLib> + : MInst<(outs IntRegs:$Rx), + (ins IntRegs:$dst2, IntRegs:$Rs, IntRegs:$Rt), + "$Rx "#!if(isSub, "-=","+=")#" sfmpy($Rs, $Rt)"#!if(isLib, ":lib",""), + [], "$dst2 = $Rx" , M_tc_3_SLOT23 > , + Requires<[HasV5T]> { + bits<5> Rx; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + + let Inst{27-21} = 0b1111000; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-8} = Rt; + let Inst{7} = 0b1; + let Inst{6} = isLib; + let Inst{5} = isSub; + let Inst{4-0} = Rx; + } + +let isCodeGenOnly = 0 in { +def F2_sffma: T_sfmpy_acc <0, 0>; +def F2_sffms: T_sfmpy_acc <1, 0>; +def F2_sffma_lib: T_sfmpy_acc <0, 1>; +def F2_sffms_lib: T_sfmpy_acc <1, 1>; +} + +// Floating-point fused multiply add w/ additional scaling (2**pu). +let isFP = 1, hasNewValue = 1, isCodeGenOnly = 0 in +def F2_sffma_sc: MInst < + (outs IntRegs:$Rx), + (ins IntRegs:$dst2, IntRegs:$Rs, IntRegs:$Rt, PredRegs:$Pu), + "$Rx += sfmpy($Rs, $Rt, $Pu):scale" , + [], "$dst2 = $Rx" , M_tc_3_SLOT23 > , + Requires<[HasV5T]> { + bits<5> Rx; + bits<5> Rs; + bits<5> Rt; + bits<2> Pu; + + let IClass = 0b1110; + + let Inst{27-21} = 0b1111011; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-8} = Rt; + let Inst{7} = 0b1; + let Inst{6-5} = Pu; + let Inst{4-0} = Rx; + } + +// Classify floating-point value +let isFP = 1, isCodeGenOnly = 0 in + def F2_sfclass : T_TEST_BIT_IMM<"sfclass", 0b111>; + +let isFP = 1, isCodeGenOnly = 0 in +def F2_dfclass: ALU64Inst<(outs PredRegs:$Pd), (ins DoubleRegs:$Rss, u5Imm:$u5), + "$Pd = dfclass($Rss, #$u5)", + [], "" , ALU64_tc_2early_SLOT23 > , Requires<[HasV5T]> { + bits<2> Pd; + bits<5> Rss; + bits<5> u5; + + let IClass = 0b1101; + let Inst{27-21} = 0b1100100; + let Inst{20-16} = Rss; + let Inst{12-10} = 0b000; + let Inst{9-5} = u5; + let Inst{4-3} = 0b10; + let Inst{1-0} = Pd; + } + +// Instructions to create floating point constant +let hasNewValue = 1, opNewValue = 0 in +class T_fimm <string mnemonic, RegisterClass RC, bits<4> RegType, bit isNeg> + : ALU64Inst<(outs RC:$dst), (ins u10Imm:$src), + "$dst = "#mnemonic#"(#$src)"#!if(isNeg, ":neg", ":pos"), + [], "", ALU64_tc_3x_SLOT23>, Requires<[HasV5T]> { + bits<5> dst; + bits<10> src; + + let IClass = 0b1101; + let Inst{27-24} = RegType; + let Inst{23} = 0b0; + let Inst{22} = isNeg; + let Inst{21} = src{9}; + let Inst{13-5} = src{8-0}; + let Inst{4-0} = dst; + } + +let isCodeGenOnly = 0 in { +def F2_sfimm_p : T_fimm <"sfmake", IntRegs, 0b0110, 0>; +def F2_sfimm_n : T_fimm <"sfmake", IntRegs, 0b0110, 1>; +def F2_dfimm_p : T_fimm <"dfmake", DoubleRegs, 0b1001, 0>; +def F2_dfimm_n : T_fimm <"dfmake", DoubleRegs, 0b1001, 1>; +} + // Convert single precision to double precision and vice-versa. def CONVERT_sf2df : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src), "$dst = convert_sf2df($src)", @@ -290,36 +721,36 @@ def : Pat<(i1 (setule (f64 DoubleRegs:$src1), (fpimm:$src2))), // ne. def : Pat<(i1 (setone (f32 IntRegs:$src1), (f32 IntRegs:$src2))), - (i1 (NOT_p (FCMPOEQ32_rr IntRegs:$src1, IntRegs:$src2)))>, + (i1 (C2_not (FCMPOEQ32_rr IntRegs:$src1, IntRegs:$src2)))>, Requires<[HasV5T]>; def : Pat<(i1 (setone (f64 DoubleRegs:$src1), (f64 DoubleRegs:$src2))), - (i1 (NOT_p (FCMPOEQ64_rr DoubleRegs:$src1, DoubleRegs:$src2)))>, + (i1 (C2_not (FCMPOEQ64_rr DoubleRegs:$src1, DoubleRegs:$src2)))>, Requires<[HasV5T]>; def : Pat<(i1 (setune (f32 IntRegs:$src1), (f32 IntRegs:$src2))), - (i1 (NOT_p (FCMPUEQ32_rr IntRegs:$src1, IntRegs:$src2)))>, + (i1 (C2_not (FCMPUEQ32_rr IntRegs:$src1, IntRegs:$src2)))>, Requires<[HasV5T]>; def : Pat<(i1 (setune (f64 DoubleRegs:$src1), (f64 DoubleRegs:$src2))), - (i1 (NOT_p (FCMPUEQ64_rr DoubleRegs:$src1, DoubleRegs:$src2)))>, + (i1 (C2_not (FCMPUEQ64_rr DoubleRegs:$src1, DoubleRegs:$src2)))>, Requires<[HasV5T]>; def : Pat<(i1 (setone (f32 IntRegs:$src1), (fpimm:$src2))), - (i1 (NOT_p (FCMPOEQ32_rr IntRegs:$src1, (f32 (TFRI_f fpimm:$src2)))))>, + (i1 (C2_not (FCMPOEQ32_rr IntRegs:$src1, (f32 (TFRI_f fpimm:$src2)))))>, Requires<[HasV5T]>; def : Pat<(i1 (setone (f64 DoubleRegs:$src1), (fpimm:$src2))), - (i1 (NOT_p (FCMPOEQ64_rr DoubleRegs:$src1, + (i1 (C2_not (FCMPOEQ64_rr DoubleRegs:$src1, (f64 (CONST64_Float_Real fpimm:$src2)))))>, Requires<[HasV5T]>; def : Pat<(i1 (setune (f32 IntRegs:$src1), (fpimm:$src2))), - (i1 (NOT_p (FCMPUEQ32_rr IntRegs:$src1, (f32 (TFRI_f fpimm:$src2)))))>, + (i1 (C2_not (FCMPUEQ32_rr IntRegs:$src1, (f32 (TFRI_f fpimm:$src2)))))>, Requires<[HasV5T]>; def : Pat<(i1 (setune (f64 DoubleRegs:$src1), (fpimm:$src2))), - (i1 (NOT_p (FCMPUEQ64_rr DoubleRegs:$src1, + (i1 (C2_not (FCMPUEQ64_rr DoubleRegs:$src1, (f64 (CONST64_Float_Real fpimm:$src2)))))>, Requires<[HasV5T]>; @@ -458,30 +889,21 @@ def CONVERT_sf2ud_nchop : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src), // Bitcast is different than [fp|sint|uint]_to_[sint|uint|fp]. def : Pat <(i32 (bitconvert (f32 IntRegs:$src))), - (i32 (TFR IntRegs:$src))>, + (i32 (A2_tfr IntRegs:$src))>, Requires<[HasV5T]>; def : Pat <(f32 (bitconvert (i32 IntRegs:$src))), - (f32 (TFR IntRegs:$src))>, + (f32 (A2_tfr IntRegs:$src))>, Requires<[HasV5T]>; def : Pat <(i64 (bitconvert (f64 DoubleRegs:$src))), - (i64 (TFR64 DoubleRegs:$src))>, + (i64 (A2_tfrp DoubleRegs:$src))>, Requires<[HasV5T]>; def : Pat <(f64 (bitconvert (i64 DoubleRegs:$src))), - (f64 (TFR64 DoubleRegs:$src))>, + (f64 (A2_tfrp DoubleRegs:$src))>, Requires<[HasV5T]>; -// Floating point fused multiply-add. -def FMADD_dp : ALU64_acc<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2, DoubleRegs:$src3), - "$dst += dfmpy($src2, $src3)", - [(set (f64 DoubleRegs:$dst), - (fma DoubleRegs:$src2, DoubleRegs:$src3, DoubleRegs:$src1))], - "$src1 = $dst">, - Requires<[HasV5T]>; - def FMADD_sp : ALU64_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3), "$dst += sfmpy($src2, $src3)", @@ -492,15 +914,6 @@ def FMADD_sp : ALU64_acc<(outs IntRegs:$dst), // Floating point max/min. -let AddedComplexity = 100 in -def FMAX_dp : ALU64_rr<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2), - "$dst = dfmax($src1, $src2)", - [(set DoubleRegs:$dst, (f64 (select (i1 (setolt DoubleRegs:$src2, - DoubleRegs:$src1)), - DoubleRegs:$src1, - DoubleRegs:$src2)))]>, - Requires<[HasV5T]>; let AddedComplexity = 100 in def FMAX_sp : ALU64_rr<(outs IntRegs:$dst), @@ -513,16 +926,6 @@ def FMAX_sp : ALU64_rr<(outs IntRegs:$dst), Requires<[HasV5T]>; let AddedComplexity = 100 in -def FMIN_dp : ALU64_rr<(outs DoubleRegs:$dst), - (ins DoubleRegs:$src1, DoubleRegs:$src2), - "$dst = dfmin($src1, $src2)", - [(set DoubleRegs:$dst, (f64 (select (i1 (setogt DoubleRegs:$src2, - DoubleRegs:$src1)), - DoubleRegs:$src1, - DoubleRegs:$src2)))]>, - Requires<[HasV5T]>; - -let AddedComplexity = 100 in def FMIN_sp : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = sfmin($src1, $src2)", @@ -615,19 +1018,19 @@ def : Pat <(i32 (fp_to_sint (f64 DoubleRegs:$src1))), Requires<[HasV5T]>; def : Pat <(fabs (f32 IntRegs:$src1)), - (CLRBIT_31 (f32 IntRegs:$src1), 31)>, + (S2_clrbit_i (f32 IntRegs:$src1), 31)>, Requires<[HasV5T]>; def : Pat <(fneg (f32 IntRegs:$src1)), - (TOGBIT_31 (f32 IntRegs:$src1), 31)>, + (S2_togglebit_i (f32 IntRegs:$src1), 31)>, Requires<[HasV5T]>; /* def : Pat <(fabs (f64 DoubleRegs:$src1)), - (CLRBIT_31 (f32 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg)), 31)>, + (S2_clrbit_i (f32 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg)), 31)>, Requires<[HasV5T]>; def : Pat <(fabs (f64 DoubleRegs:$src1)), - (CLRBIT_31 (f32 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg)), 31)>, + (S2_clrbit_i (f32 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg)), 31)>, Requires<[HasV5T]>; */ diff --git a/lib/Target/Hexagon/HexagonIntrinsics.td b/lib/Target/Hexagon/HexagonIntrinsics.td index 99f59d5ea669..7d3f9d92cbd4 100644 --- a/lib/Target/Hexagon/HexagonIntrinsics.td +++ b/lib/Target/Hexagon/HexagonIntrinsics.td @@ -1843,13 +1843,18 @@ class si_MInst_didi<string opc, Intrinsic IntID> !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), [(set IntRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>; + +class T_RI_pat <InstHexagon MI, Intrinsic IntID> + : Pat<(IntID (i32 IntRegs:$Rs), imm:$It), + (MI IntRegs:$Rs, imm:$It)>; + // // LDInst classes. // -let mayLoad = 1, neverHasSideEffects = 1 in +let mayLoad = 1, hasSideEffects = 0 in class di_LDInstPI_diu4<string opc, Intrinsic IntID> : LDInstPI<(outs IntRegs:$dst, DoubleRegs:$dst2), - (ins IntRegs:$src1, IntRegs:$src2, CRRegs:$src3, s4Imm:$offset), + (ins IntRegs:$src1, IntRegs:$src2, CtrRegs:$src3, s4Imm:$offset), "$dst2 = memd($src1++#$offset:circ($src3))", [], "$src1 = $dst">; diff --git a/lib/Target/Hexagon/HexagonIntrinsicsDerived.td b/lib/Target/Hexagon/HexagonIntrinsicsDerived.td index 2788101d5a66..df89378603a4 100644 --- a/lib/Target/Hexagon/HexagonIntrinsicsDerived.td +++ b/lib/Target/Hexagon/HexagonIntrinsicsDerived.td @@ -13,13 +13,13 @@ // def : Pat <(mul DoubleRegs:$src1, DoubleRegs:$src2), (i64 - (COMBINE_rr + (A2_combinew (HEXAGON_M2_maci (HEXAGON_M2_maci (i32 (EXTRACT_SUBREG (i64 - (MPYU64 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), + (M2_dpmpyuu_s0 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg)), (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_loreg)))), @@ -31,7 +31,8 @@ def : Pat <(mul DoubleRegs:$src1, DoubleRegs:$src2), (i32 (EXTRACT_SUBREG (i64 - (MPYU64 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg)), + (M2_dpmpyuu_s0 + (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg)), (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_loreg)))), subreg_loreg))))>; diff --git a/lib/Target/Hexagon/HexagonIntrinsicsV4.td b/lib/Target/Hexagon/HexagonIntrinsicsV4.td index dd28ebb57231..77b148b9f2bd 100644 --- a/lib/Target/Hexagon/HexagonIntrinsicsV4.td +++ b/lib/Target/Hexagon/HexagonIntrinsicsV4.td @@ -217,12 +217,13 @@ def Hexagon_A4_combineri : di_ALU32_sis8 <"combine", int_hexagon_A4_combineri>; // ALU32 / PRED / Conditional Sign Extend. // ALU32 / PRED / Conditional Zero Extend. // ALU32 / PRED / Compare. -def Hexagon_C4_cmpneq : qi_neg_ALU32_sisi <"cmp.eq", int_hexagon_C4_cmpneq>; -def Hexagon_C4_cmpneqi : qi_neg_ALU32_sis10 <"cmp.eq", int_hexagon_C4_cmpneqi>; -def Hexagon_C4_cmplte : qi_neg_ALU32_sisi <"cmp.gt", int_hexagon_C4_cmplte>; def Hexagon_C4_cmpltei : qi_neg_ALU32_sis10 <"cmp.gt", int_hexagon_C4_cmpltei>; +def Hexagon_C4_cmplte : qi_neg_ALU32_sisi <"cmp.gt", int_hexagon_C4_cmplte>; def Hexagon_C4_cmplteu : qi_neg_ALU32_sisi <"cmp.gtu",int_hexagon_C4_cmplteu>; -def Hexagon_C4_cmplteui: qi_neg_ALU32_siu9 <"cmp.gtu",int_hexagon_C4_cmplteui>; + +def: T_RI_pat<C4_cmpneqi, int_hexagon_C4_cmpneqi>; +def: T_RI_pat<C4_cmpltei, int_hexagon_C4_cmpltei>; +def: T_RI_pat<C4_cmplteui, int_hexagon_C4_cmplteui>; // ALU32 / PRED / cmpare To General Register. def Hexagon_A4_rcmpneq : si_neg_ALU32_sisi <"cmp.eq", int_hexagon_A4_rcmpneq>; diff --git a/lib/Target/Hexagon/HexagonMCInstLower.cpp b/lib/Target/Hexagon/HexagonMCInstLower.cpp index 5e4346d40213..3f5d6d84a108 100644 --- a/lib/Target/Hexagon/HexagonMCInstLower.cpp +++ b/lib/Target/Hexagon/HexagonMCInstLower.cpp @@ -42,7 +42,6 @@ static MCOperand GetSymbolRef(const MachineOperand& MO, const MCSymbol* Symbol, void llvm::HexagonLowerToMC(const MachineInstr* MI, HexagonMCInst& MCI, HexagonAsmPrinter& AP) { MCI.setOpcode(MI->getOpcode()); - MCI.setDesc(MI->getDesc()); for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) { const MachineOperand &MO = MI->getOperand(i); diff --git a/lib/Target/Hexagon/HexagonMachineFunctionInfo.h b/lib/Target/Hexagon/HexagonMachineFunctionInfo.h index d799bdbd5f19..cb18df6ed198 100644 --- a/lib/Target/Hexagon/HexagonMachineFunctionInfo.h +++ b/lib/Target/Hexagon/HexagonMachineFunctionInfo.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HexagonMACHINEFUNCTIONINFO_H -#define HexagonMACHINEFUNCTIONINFO_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINEFUNCTIONINFO_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINEFUNCTIONINFO_H #include "llvm/CodeGen/MachineFunction.h" #include <map> diff --git a/lib/Target/Hexagon/HexagonMachineScheduler.cpp b/lib/Target/Hexagon/HexagonMachineScheduler.cpp index 6fcaa2057404..97c626fdf7af 100644 --- a/lib/Target/Hexagon/HexagonMachineScheduler.cpp +++ b/lib/Target/Hexagon/HexagonMachineScheduler.cpp @@ -145,7 +145,7 @@ void VLIWMachineScheduler::schedule() { << "********** MI Converging Scheduling VLIW BB#" << BB->getNumber() << " " << BB->getName() << " in_func " << BB->getParent()->getFunction()->getName() - << " at loop depth " << MLI.getLoopDepth(BB) + << " at loop depth " << MLI->getLoopDepth(BB) << " \n"); buildDAGWithRegPressure(); @@ -208,8 +208,12 @@ void ConvergingVLIWScheduler::initialize(ScheduleDAGMI *dag) { const TargetMachine &TM = DAG->MF.getTarget(); delete Top.HazardRec; delete Bot.HazardRec; - Top.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG); - Bot.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG); + Top.HazardRec = + TM.getSubtargetImpl()->getInstrInfo()->CreateTargetMIHazardRecognizer( + Itin, DAG); + Bot.HazardRec = + TM.getSubtargetImpl()->getInstrInfo()->CreateTargetMIHazardRecognizer( + Itin, DAG); delete Top.ResourceModel; delete Bot.ResourceModel; diff --git a/lib/Target/Hexagon/HexagonMachineScheduler.h b/lib/Target/Hexagon/HexagonMachineScheduler.h index 8c4108609606..1e023c32bb8c 100644 --- a/lib/Target/Hexagon/HexagonMachineScheduler.h +++ b/lib/Target/Hexagon/HexagonMachineScheduler.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HEXAGONASMPRINTER_H -#define HEXAGONASMPRINTER_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H #include "llvm/ADT/PriorityQueue.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -56,7 +56,9 @@ class VLIWResourceModel { public: VLIWResourceModel(const TargetMachine &TM, const TargetSchedModel *SM) : SchedModel(SM), TotalPackets(0) { - ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM, nullptr); + ResourcesModel = + TM.getSubtargetImpl()->getInstrInfo()->CreateTargetScheduleState( + *TM.getSubtargetImpl()); // This hard requirement could be relaxed, // but for now do not let it proceed. @@ -99,7 +101,7 @@ public: /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's /// time to do some work. - virtual void schedule() override; + void schedule() override; /// Perform platform-specific DAG postprocessing. void postprocessDAG(); }; @@ -207,15 +209,15 @@ public: : DAG(nullptr), SchedModel(nullptr), Top(TopQID, "TopQ"), Bot(BotQID, "BotQ") {} - virtual void initialize(ScheduleDAGMI *dag) override; + void initialize(ScheduleDAGMI *dag) override; - virtual SUnit *pickNode(bool &IsTopNode) override; + SUnit *pickNode(bool &IsTopNode) override; - virtual void schedNode(SUnit *SU, bool IsTopNode) override; + void schedNode(SUnit *SU, bool IsTopNode) override; - virtual void releaseTopNode(SUnit *SU) override; + void releaseTopNode(SUnit *SU) override; - virtual void releaseBottomNode(SUnit *SU) override; + void releaseBottomNode(SUnit *SU) override; unsigned ReportPackets() { return Top.ResourceModel->getTotalPackets() + diff --git a/lib/Target/Hexagon/HexagonNewValueJump.cpp b/lib/Target/Hexagon/HexagonNewValueJump.cpp index b7c03a72779f..7edba92e7e0d 100644 --- a/lib/Target/Hexagon/HexagonNewValueJump.cpp +++ b/lib/Target/Hexagon/HexagonNewValueJump.cpp @@ -176,7 +176,7 @@ static bool commonChecksToProhibitNewValueJump(bool afterRA, return false; // if call in path, bail out. - if (MII->getOpcode() == Hexagon::CALLv3) + if (MII->getOpcode() == Hexagon::J2_call) return false; // if NVJ is running prior to RA, do the following checks. @@ -199,8 +199,7 @@ static bool commonChecksToProhibitNewValueJump(bool afterRA, // of registers by individual passes in the backend. At this time, // we don't know the scope of usage and definitions of these // instructions. - if (MII->getOpcode() == Hexagon::TFR_condset_rr || - MII->getOpcode() == Hexagon::TFR_condset_ii || + if (MII->getOpcode() == Hexagon::TFR_condset_ii || MII->getOpcode() == Hexagon::TFR_condset_ri || MII->getOpcode() == Hexagon::TFR_condset_ir || MII->getOpcode() == Hexagon::LDriw_pred || @@ -228,8 +227,8 @@ static bool canCompareBeNewValueJump(const HexagonInstrInfo *QII, int64_t v = MI->getOperand(2).getImm(); if (!(isUInt<5>(v) || - ((MI->getOpcode() == Hexagon::CMPEQri || - MI->getOpcode() == Hexagon::CMPGTri) && + ((MI->getOpcode() == Hexagon::C2_cmpeqi || + MI->getOpcode() == Hexagon::C2_cmpgti) && (v == -1)))) return false; } @@ -299,11 +298,11 @@ static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg, taken = true; switch (MI->getOpcode()) { - case Hexagon::CMPEQrr: + case Hexagon::C2_cmpeq: return taken ? Hexagon::CMPEQrr_t_Jumpnv_t_V4 : Hexagon::CMPEQrr_t_Jumpnv_nt_V4; - case Hexagon::CMPEQri: { + case Hexagon::C2_cmpeqi: { if (reg >= 0) return taken ? Hexagon::CMPEQri_t_Jumpnv_t_V4 : Hexagon::CMPEQri_t_Jumpnv_nt_V4; @@ -312,7 +311,7 @@ static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg, : Hexagon::CMPEQn1_t_Jumpnv_nt_V4; } - case Hexagon::CMPGTrr: { + case Hexagon::C2_cmpgt: { if (secondRegNewified) return taken ? Hexagon::CMPLTrr_t_Jumpnv_t_V4 : Hexagon::CMPLTrr_t_Jumpnv_nt_V4; @@ -321,7 +320,7 @@ static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg, : Hexagon::CMPGTrr_t_Jumpnv_nt_V4; } - case Hexagon::CMPGTri: { + case Hexagon::C2_cmpgti: { if (reg >= 0) return taken ? Hexagon::CMPGTri_t_Jumpnv_t_V4 : Hexagon::CMPGTri_t_Jumpnv_nt_V4; @@ -330,7 +329,7 @@ static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg, : Hexagon::CMPGTn1_t_Jumpnv_nt_V4; } - case Hexagon::CMPGTUrr: { + case Hexagon::C2_cmpgtu: { if (secondRegNewified) return taken ? Hexagon::CMPLTUrr_t_Jumpnv_t_V4 : Hexagon::CMPLTUrr_t_Jumpnv_nt_V4; @@ -339,7 +338,7 @@ static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg, : Hexagon::CMPGTUrr_t_Jumpnv_nt_V4; } - case Hexagon::CMPGTUri: + case Hexagon::C2_cmpgtui: return taken ? Hexagon::CMPGTUri_t_Jumpnv_t_V4 : Hexagon::CMPGTUri_t_Jumpnv_nt_V4; @@ -362,9 +361,9 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) { LiveVariables &LVs = getAnalysis<LiveVariables>(); #endif - QII = static_cast<const HexagonInstrInfo *>(MF.getTarget().getInstrInfo()); - QRI = - static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo()); + QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); + QRI = static_cast<const HexagonRegisterInfo *>( + MF.getSubtarget().getRegisterInfo()); MBPI = &getAnalysis<MachineBranchProbabilityInfo>(); if (!QRI->Subtarget.hasV4TOps() || @@ -413,12 +412,12 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) { DEBUG(dbgs() << "Instr: "; MI->dump(); dbgs() << "\n"); if (!foundJump && - (MI->getOpcode() == Hexagon::JMP_t || - MI->getOpcode() == Hexagon::JMP_f || - MI->getOpcode() == Hexagon::JMP_tnew_t || - MI->getOpcode() == Hexagon::JMP_tnew_nt || - MI->getOpcode() == Hexagon::JMP_fnew_t || - MI->getOpcode() == Hexagon::JMP_fnew_nt)) { + (MI->getOpcode() == Hexagon::J2_jumpt || + MI->getOpcode() == Hexagon::J2_jumpf || + MI->getOpcode() == Hexagon::J2_jumptnewpt || + MI->getOpcode() == Hexagon::J2_jumptnew || + MI->getOpcode() == Hexagon::J2_jumpfnewpt || + MI->getOpcode() == Hexagon::J2_jumpfnew)) { // This is where you would insert your compare and // instr that feeds compare jmpPos = MII; @@ -454,9 +453,9 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) { jmpTarget = MI->getOperand(1).getMBB(); foundJump = true; - if (MI->getOpcode() == Hexagon::JMP_f || - MI->getOpcode() == Hexagon::JMP_fnew_t || - MI->getOpcode() == Hexagon::JMP_fnew_nt) { + if (MI->getOpcode() == Hexagon::J2_jumpf || + MI->getOpcode() == Hexagon::J2_jumpfnewpt || + MI->getOpcode() == Hexagon::J2_jumpfnew) { invertPredicate = true; } continue; @@ -545,7 +544,7 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) { if (isSecondOpReg) { // In case of CMPLT, or CMPLTU, or EQ with the second register // to newify, swap the operands. - if (cmpInstr->getOpcode() == Hexagon::CMPEQrr && + if (cmpInstr->getOpcode() == Hexagon::C2_cmpeq && feederReg == (unsigned) cmpOp2) { unsigned tmp = cmpReg1; bool tmpIsKill = MO1IsKill; @@ -612,8 +611,8 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) { .addReg(cmpOp2, getKillRegState(MO2IsKill)) .addMBB(jmpTarget); - else if ((cmpInstr->getOpcode() == Hexagon::CMPEQri || - cmpInstr->getOpcode() == Hexagon::CMPGTri) && + else if ((cmpInstr->getOpcode() == Hexagon::C2_cmpeqi || + cmpInstr->getOpcode() == Hexagon::C2_cmpgti) && cmpOp2 == -1 ) // Corresponding new-value compare jump instructions don't have the // operand for -1 immediate value. diff --git a/lib/Target/Hexagon/HexagonOperands.td b/lib/Target/Hexagon/HexagonOperands.td index c79d78f21080..5a6de0ae2746 100644 --- a/lib/Target/Hexagon/HexagonOperands.td +++ b/lib/Target/Hexagon/HexagonOperands.td @@ -39,6 +39,7 @@ let PrintMethod = "printImmOperand" in { def u16_0Imm : Operand<i32>; def u16_1Imm : Operand<i32>; def u16_2Imm : Operand<i32>; + def u16_3Imm : Operand<i32>; def u11_3Imm : Operand<i32>; def u10Imm : Operand<i32>; def u9Imm : Operand<i32>; @@ -258,6 +259,13 @@ def u16_s8ImmPred : PatLeaf<(i32 imm), [{ return isShiftedUInt<16,8>(v); }]>; +def u11_3ImmPred : PatLeaf<(i32 imm), [{ + // True if the immediate fits in a 14-bit unsigned field, and the lowest + // three bits are 0. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<11,3>(v); +}]>; + def u9ImmPred : PatLeaf<(i32 imm), [{ // u9ImmPred predicate - True if the immediate fits in a 9-bit unsigned // field. @@ -800,6 +808,12 @@ def u6_3ExtPred : PatLeaf<(i32 imm), [{ } }]>; + +// This complex pattern exists only to create a machine instruction operand +// of type "frame index". There doesn't seem to be a way to do that directly +// in the patterns. +def AddrFI : ComplexPattern<i32, 1, "SelectAddrFI", [frameindex], []>; + // Addressing modes. def ADDRrr : ComplexPattern<i32, 2, "SelectADDRrr", [], []>; @@ -856,3 +870,12 @@ def symbolHi32 : Operand<i32> { def symbolLo32 : Operand<i32> { let PrintMethod = "printSymbolLo"; } + +// Return true if for a 32 to 64-bit sign-extended load. +def is_sext_i32 : PatLeaf<(i64 DoubleRegs:$src1), [{ + LoadSDNode *LD = dyn_cast<LoadSDNode>(N); + if (!LD) + return false; + return LD->getExtensionType() == ISD::SEXTLOAD && + LD->getMemoryVT().getScalarType() == MVT::i32; +}]>; diff --git a/lib/Target/Hexagon/HexagonPeephole.cpp b/lib/Target/Hexagon/HexagonPeephole.cpp index 48b61590853a..e9b2ef6b3911 100644 --- a/lib/Target/Hexagon/HexagonPeephole.cpp +++ b/lib/Target/Hexagon/HexagonPeephole.cpp @@ -111,10 +111,8 @@ INITIALIZE_PASS(HexagonPeephole, "hexagon-peephole", "Hexagon Peephole", false, false) bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { - QII = static_cast<const HexagonInstrInfo *>(MF.getTarget(). - getInstrInfo()); - QRI = static_cast<const HexagonRegisterInfo *>(MF.getTarget(). - getRegisterInfo()); + QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); + QRI = MF.getTarget().getSubtarget<HexagonSubtarget>().getRegisterInfo(); MRI = &MF.getRegInfo(); DenseMap<unsigned, unsigned> PeepholeMap; @@ -135,7 +133,7 @@ bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { MachineInstr *MI = MII; // Look for sign extends: // %vreg170<def> = SXTW %vreg166 - if (!DisableOptSZExt && MI->getOpcode() == Hexagon::SXTW) { + if (!DisableOptSZExt && MI->getOpcode() == Hexagon::A2_sxtw) { assert (MI->getNumOperands() == 2); MachineOperand &Dst = MI->getOperand(0); MachineOperand &Src = MI->getOperand(1); @@ -154,7 +152,7 @@ bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { // Look for %vreg170<def> = COMBINE_ir_V4 (0, %vreg169) // %vreg170:DoublRegs, %vreg169:IntRegs if (!DisableOptExtTo64 && - MI->getOpcode () == Hexagon::COMBINE_Ir_V4) { + MI->getOpcode () == Hexagon::A4_combineir) { assert (MI->getNumOperands() == 3); MachineOperand &Dst = MI->getOperand(0); MachineOperand &Src1 = MI->getOperand(1); @@ -171,7 +169,7 @@ bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { // %vregIntReg = COPY %vregDoubleReg1:subreg_loreg. // and convert into // %vregIntReg = COPY %vregDoubleReg0:subreg_hireg. - if (MI->getOpcode() == Hexagon::LSRd_ri) { + if (MI->getOpcode() == Hexagon::S2_lsr_i_p) { assert(MI->getNumOperands() == 3); MachineOperand &Dst = MI->getOperand(0); MachineOperand &Src1 = MI->getOperand(1); @@ -186,7 +184,7 @@ bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { // Look for P=NOT(P). if (!DisablePNotP && - (MI->getOpcode() == Hexagon::NOT_p)) { + (MI->getOpcode() == Hexagon::C2_not)) { assert (MI->getNumOperands() == 2); MachineOperand &Dst = MI->getOperand(0); MachineOperand &Src = MI->getOperand(1); @@ -271,10 +269,9 @@ bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { unsigned PR = 1, S1 = 2, S2 = 3; // Operand indices. switch (Op) { - case Hexagon::TFR_condset_rr: + case Hexagon::C2_mux: + case Hexagon::C2_muxii: case Hexagon::TFR_condset_ii: - case Hexagon::MUX_ii: - case Hexagon::MUX_rr: NewOp = Op; break; case Hexagon::TFR_condset_ri: @@ -283,11 +280,11 @@ bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { case Hexagon::TFR_condset_ir: NewOp = Hexagon::TFR_condset_ri; break; - case Hexagon::MUX_ri: - NewOp = Hexagon::MUX_ir; + case Hexagon::C2_muxri: + NewOp = Hexagon::C2_muxir; break; - case Hexagon::MUX_ir: - NewOp = Hexagon::MUX_ri; + case Hexagon::C2_muxir: + NewOp = Hexagon::C2_muxri; break; } if (NewOp) { diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/lib/Target/Hexagon/HexagonRegisterInfo.cpp index fb466d3b5908..a64c9df9a047 100644 --- a/lib/Target/Hexagon/HexagonRegisterInfo.cpp +++ b/lib/Target/Hexagon/HexagonRegisterInfo.cpp @@ -128,12 +128,12 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, // Addressable stack objects are accessed using neg. offsets from %fp. MachineFunction &MF = *MI.getParent()->getParent(); const HexagonInstrInfo &TII = - *static_cast<const HexagonInstrInfo*>(MF.getTarget().getInstrInfo()); + *static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); MachineFrameInfo &MFI = *MF.getFrameInfo(); unsigned FrameReg = getFrameRegister(MF); - const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); if (!TFI->hasFP(MF)) { // We will not reserve space on the stack for the lr and fp registers. Offset -= 2 * Hexagon_WordSize; @@ -159,15 +159,15 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, // // r0 = add(r30, #10000) // r0 = memw(r0) - if ( (MI.getOpcode() == Hexagon::LDriw) || - (MI.getOpcode() == Hexagon::LDrid) || - (MI.getOpcode() == Hexagon::LDrih) || - (MI.getOpcode() == Hexagon::LDriuh) || - (MI.getOpcode() == Hexagon::LDrib) || - (MI.getOpcode() == Hexagon::LDriub) || + if ( (MI.getOpcode() == Hexagon::L2_loadri_io) || + (MI.getOpcode() == Hexagon::L2_loadrd_io) || + (MI.getOpcode() == Hexagon::L2_loadrh_io) || + (MI.getOpcode() == Hexagon::L2_loadruh_io) || + (MI.getOpcode() == Hexagon::L2_loadrb_io) || + (MI.getOpcode() == Hexagon::L2_loadrub_io) || (MI.getOpcode() == Hexagon::LDriw_f) || (MI.getOpcode() == Hexagon::LDrid_f)) { - unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ? + unsigned dstReg = (MI.getOpcode() == Hexagon::L2_loadrd_io) ? getSubReg(MI.getOperand(0).getReg(), Hexagon::subreg_loreg) : MI.getOperand(0).getReg(); @@ -176,7 +176,7 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, BuildMI(*MI.getParent(), II, MI.getDebugLoc(), TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); BuildMI(*MI.getParent(), II, MI.getDebugLoc(), - TII.get(Hexagon::ADD_rr), + TII.get(Hexagon::A2_add), dstReg).addReg(FrameReg).addReg(dstReg); } else { BuildMI(*MI.getParent(), II, MI.getDebugLoc(), @@ -186,11 +186,10 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true); MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); - } else if ((MI.getOpcode() == Hexagon::STriw_indexed) || - (MI.getOpcode() == Hexagon::STriw) || - (MI.getOpcode() == Hexagon::STrid) || - (MI.getOpcode() == Hexagon::STrih) || - (MI.getOpcode() == Hexagon::STrib) || + } else if ((MI.getOpcode() == Hexagon::S2_storeri_io) || + (MI.getOpcode() == Hexagon::S2_storerd_io) || + (MI.getOpcode() == Hexagon::S2_storerh_io) || + (MI.getOpcode() == Hexagon::S2_storerb_io) || (MI.getOpcode() == Hexagon::STrid_f) || (MI.getOpcode() == Hexagon::STriw_f)) { // For stores, we need a reserved register. Change @@ -205,7 +204,7 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, BuildMI(*MI.getParent(), II, MI.getDebugLoc(), TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); BuildMI(*MI.getParent(), II, MI.getDebugLoc(), - TII.get(Hexagon::ADD_rr), + TII.get(Hexagon::A2_add), resReg).addReg(FrameReg).addReg(resReg); } else { BuildMI(*MI.getParent(), II, MI.getDebugLoc(), @@ -237,7 +236,7 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, BuildMI(*MI.getParent(), II, MI.getDebugLoc(), TII.get(Hexagon::CONST32_Int_Real), ResReg).addImm(Offset); BuildMI(*MI.getParent(), II, MI.getDebugLoc(), - TII.get(Hexagon::ADD_rr), ResReg).addReg(FrameReg). + TII.get(Hexagon::A2_add), ResReg).addReg(FrameReg). addReg(ResReg); MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false, true); @@ -256,7 +255,7 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, BuildMI(*MI.getParent(), II, MI.getDebugLoc(), TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); BuildMI(*MI.getParent(), II, MI.getDebugLoc(), - TII.get(Hexagon::ADD_rr), + TII.get(Hexagon::A2_add), dstReg).addReg(FrameReg).addReg(dstReg); // Can we delete MI??? r2 = add (r2, #0). MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true); @@ -278,7 +277,7 @@ unsigned HexagonRegisterInfo::getRARegister() const { unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction &MF) const { - const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); if (TFI->hasFP(MF)) { return Hexagon::R30; } diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.h b/lib/Target/Hexagon/HexagonRegisterInfo.h index 648b4af9e957..a83b5026467a 100644 --- a/lib/Target/Hexagon/HexagonRegisterInfo.h +++ b/lib/Target/Hexagon/HexagonRegisterInfo.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HexagonREGISTERINFO_H -#define HexagonREGISTERINFO_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONREGISTERINFO_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONREGISTERINFO_H #include "llvm/MC/MachineLocation.h" #include "llvm/Target/TargetRegisterInfo.h" diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.td b/lib/Target/Hexagon/HexagonRegisterInfo.td index 8ea1b7e75db7..decd94722da1 100644 --- a/lib/Target/Hexagon/HexagonRegisterInfo.td +++ b/lib/Target/Hexagon/HexagonRegisterInfo.td @@ -13,90 +13,78 @@ let Namespace = "Hexagon" in { - class HexagonReg<string n> : Register<n> { + class HexagonReg<bits<5> num, string n, list<string> alt = [], + list<Register> alias = []> : Register<n> { field bits<5> Num; + let Aliases = alias; + let HWEncoding{4-0} = num; } - class HexagonDoubleReg<string n, list<Register> subregs> : + class HexagonDoubleReg<bits<5> num, string n, list<Register> subregs, + list<string> alt = []> : RegisterWithSubRegs<n, subregs> { field bits<5> Num; + + let AltNames = alt; + let HWEncoding{4-0} = num; } // Registers are identified with 5-bit ID numbers. // Ri - 32-bit integer registers. - class Ri<bits<5> num, string n> : HexagonReg<n> { + class Ri<bits<5> num, string n, list<string> alt = []> : HexagonReg<num, n, alt> { let Num = num; } // Rf - 32-bit floating-point registers. - class Rf<bits<5> num, string n> : HexagonReg<n> { + class Rf<bits<5> num, string n> : HexagonReg<num, n> { let Num = num; } // Rd - 64-bit registers. class Rd<bits<5> num, string n, list<Register> subregs> : - HexagonDoubleReg<n, subregs> { + HexagonDoubleReg<num, n, subregs> { let Num = num; let SubRegs = subregs; } // Rp - predicate registers - class Rp<bits<5> num, string n> : HexagonReg<n> { + class Rp<bits<5> num, string n> : HexagonReg<num, n> { let Num = num; } // Rc - control registers - class Rc<bits<5> num, string n> : HexagonReg<n> { + class Rc<bits<5> num, string n, + list<string> alt = [], list<Register> alias = []> : + HexagonReg<num, n, alt, alias> { + let Num = num; + } + + // Rcc - 64-bit control registers. + class Rcc<bits<5> num, string n, list<Register> subregs, + list<string> alt = []> : + HexagonDoubleReg<num, n, subregs, alt> { let Num = num; + let SubRegs = subregs; } - // Rj - aliased integer registers - class Rj<string n, Ri R>: HexagonReg<n> { - let Num = R.Num; - let Aliases = [R]; + // Mx - address modifier registers + class Mx<bits<1> num, string n> : HexagonReg<{0b0000, num}, n> { + let Num = !cast<bits<5>>(num); } def subreg_loreg : SubRegIndex<32>; def subreg_hireg : SubRegIndex<32, 32>; + def subreg_overflow : SubRegIndex<1, 0>; // Integer registers. - def R0 : Ri< 0, "r0">, DwarfRegNum<[0]>; - def R1 : Ri< 1, "r1">, DwarfRegNum<[1]>; - def R2 : Ri< 2, "r2">, DwarfRegNum<[2]>; - def R3 : Ri< 3, "r3">, DwarfRegNum<[3]>; - def R4 : Ri< 4, "r4">, DwarfRegNum<[4]>; - def R5 : Ri< 5, "r5">, DwarfRegNum<[5]>; - def R6 : Ri< 6, "r6">, DwarfRegNum<[6]>; - def R7 : Ri< 7, "r7">, DwarfRegNum<[7]>; - def R8 : Ri< 8, "r8">, DwarfRegNum<[8]>; - def R9 : Ri< 9, "r9">, DwarfRegNum<[9]>; - def R10 : Ri<10, "r10">, DwarfRegNum<[10]>; - def R11 : Ri<11, "r11">, DwarfRegNum<[11]>; - def R12 : Ri<12, "r12">, DwarfRegNum<[12]>; - def R13 : Ri<13, "r13">, DwarfRegNum<[13]>; - def R14 : Ri<14, "r14">, DwarfRegNum<[14]>; - def R15 : Ri<15, "r15">, DwarfRegNum<[15]>; - def R16 : Ri<16, "r16">, DwarfRegNum<[16]>; - def R17 : Ri<17, "r17">, DwarfRegNum<[17]>; - def R18 : Ri<18, "r18">, DwarfRegNum<[18]>; - def R19 : Ri<19, "r19">, DwarfRegNum<[19]>; - def R20 : Ri<20, "r20">, DwarfRegNum<[20]>; - def R21 : Ri<21, "r21">, DwarfRegNum<[21]>; - def R22 : Ri<22, "r22">, DwarfRegNum<[22]>; - def R23 : Ri<23, "r23">, DwarfRegNum<[23]>; - def R24 : Ri<24, "r24">, DwarfRegNum<[24]>; - def R25 : Ri<25, "r25">, DwarfRegNum<[25]>; - def R26 : Ri<26, "r26">, DwarfRegNum<[26]>; - def R27 : Ri<27, "r27">, DwarfRegNum<[27]>; - def R28 : Ri<28, "r28">, DwarfRegNum<[28]>; - def R29 : Ri<29, "r29">, DwarfRegNum<[29]>; - def R30 : Ri<30, "r30">, DwarfRegNum<[30]>; - def R31 : Ri<31, "r31">, DwarfRegNum<[31]>; - - def SP : Rj<"sp", R29>, DwarfRegNum<[29]>; - def FP : Rj<"fp", R30>, DwarfRegNum<[30]>; - def LR : Rj<"lr", R31>, DwarfRegNum<[31]>; + foreach i = 0-28 in { + def R#i : Ri<i, "r"#i>, DwarfRegNum<[i]>; + } + + def R29 : Ri<29, "r29", ["sp"]>, DwarfRegNum<[29]>; + def R30 : Ri<30, "r30", ["fp"]>, DwarfRegNum<[30]>; + def R31 : Ri<31, "r31", ["lr"]>, DwarfRegNum<[31]>; // Aliases of the R* registers used to hold 64-bit int values (doubles). let SubRegIndices = [subreg_loreg, subreg_hireg], CoveredBySubRegs = 1 in { @@ -124,20 +112,52 @@ let Namespace = "Hexagon" in { def P2 : Rp<2, "p2">, DwarfRegNum<[65]>; def P3 : Rp<3, "p3">, DwarfRegNum<[66]>; - // Control registers. - def SA0 : Rc<0, "sa0">, DwarfRegNum<[67]>; - def LC0 : Rc<1, "lc0">, DwarfRegNum<[68]>; - - def SA1 : Rc<2, "sa1">, DwarfRegNum<[69]>; - def LC1 : Rc<3, "lc1">, DwarfRegNum<[70]>; + // Modifier registers. + // C6 and C7 can also be M0 and M1, but register names must be unique, even + // if belonging to different register classes. + def M0 : Mx<0, "m0">, DwarfRegNum<[72]>; + def M1 : Mx<1, "m1">, DwarfRegNum<[73]>; - def M0 : Rc<6, "m0">, DwarfRegNum<[71]>; - def M1 : Rc<7, "m1">, DwarfRegNum<[72]>; + // Fake register to represent USR.OVF bit. Artihmetic/saturating instruc- + // tions modify this bit, and multiple such instructions are allowed in the + // same packet. We need to ignore output dependencies on this bit, but not + // on the entire USR. + def USR_OVF : Rc<?, "usr.ovf">; - def PC : Rc<9, "pc">, DwarfRegNum<[32]>; // is the Dwarf number correct? - def GP : Rc<11, "gp">, DwarfRegNum<[33]>; // is the Dwarf number correct? + // Control registers. + def SA0 : Rc<0, "sa0", ["c0"]>, DwarfRegNum<[67]>; + def LC0 : Rc<1, "lc0", ["c1"]>, DwarfRegNum<[68]>; + def SA1 : Rc<2, "sa1", ["c2"]>, DwarfRegNum<[69]>; + def LC1 : Rc<3, "lc1", ["c3"]>, DwarfRegNum<[70]>; + def P3_0 : Rc<4, "p3:0", ["c4"], [P0, P1, P2, P3]>, + DwarfRegNum<[71]>; + def C6 : Rc<6, "c6", [], [M0]>, DwarfRegNum<[72]>; + def C7 : Rc<7, "c7", [], [M1]>, DwarfRegNum<[73]>; + + def USR : Rc<8, "usr", ["c8"]>, DwarfRegNum<[74]> { + let SubRegIndices = [subreg_overflow]; + let SubRegs = [USR_OVF]; + } + def PC : Rc<9, "pc">, DwarfRegNum<[75]>; + def UGP : Rc<10, "ugp", ["c10"]>, DwarfRegNum<[76]>; + def GP : Rc<11, "gp">, DwarfRegNum<[77]>; + def CS0 : Rc<12, "cs0", ["c12"]>, DwarfRegNum<[78]>; + def CS1 : Rc<13, "cs1", ["c13"]>, DwarfRegNum<[79]>; + def UPCL : Rc<14, "upcyclelo", ["c14"]>, DwarfRegNum<[80]>; + def UPCH : Rc<15, "upcyclehi", ["c15"]>, DwarfRegNum<[81]>; } + // Control registers pairs. + let SubRegIndices = [subreg_loreg, subreg_hireg], CoveredBySubRegs = 1 in { + def C1_0 : Rcc<0, "c1:0", [SA0, LC0], ["lc0:sa0"]>, DwarfRegNum<[67]>; + def C3_2 : Rcc<2, "c3:2", [SA1, LC1], ["lc1:sa1"]>, DwarfRegNum<[69]>; + def C7_6 : Rcc<6, "c7:6", [C6, C7], ["m1:0"]>, DwarfRegNum<[72]>; + def C9_8 : Rcc<8, "c9:8", [USR, PC]>, DwarfRegNum<[74]>; + def C11_10 : Rcc<10, "c11:10", [UGP, GP]>, DwarfRegNum<[76]>; + def CS : Rcc<12, "c13:12", [CS0, CS1], ["cs1:0"]>, DwarfRegNum<[78]>; + def UPC : Rcc<14, "c15:14", [UPCL, UPCH]>, DwarfRegNum<[80]>; + } + // Register classes. // // FIXME: the register order should be defined in terms of the preferred @@ -159,9 +179,29 @@ def PredRegs : RegisterClass<"Hexagon", [i1], 32, (add (sequence "P%u", 0, 3))> let Size = 32; } -def CRRegs : RegisterClass<"Hexagon", [i32], 32, - (add (sequence "LC%u", 0, 1), - (sequence "SA%u", 0, 1), - (sequence "M%u", 0, 1), PC, GP)> { - let Size = 32; +let Size = 32 in +def ModRegs : RegisterClass<"Hexagon", [i32], 32, (add M0, M1)>; + +let Size = 32, isAllocatable = 0 in +def CtrRegs : RegisterClass<"Hexagon", [i32], 32, + (add LC0, SA0, LC1, SA1, + P3_0, + M0, M1, C6, C7, CS0, CS1, UPCL, UPCH, + USR, USR_OVF, UGP, GP, PC)>; + +let Size = 64, isAllocatable = 0 in +def CtrRegs64 : RegisterClass<"Hexagon", [i64], 64, + (add C1_0, C3_2, C7_6, C9_8, C11_10, CS, UPC)>; + +def VolatileV3 { + list<Register> Regs = [D0, D1, D2, D3, D4, D5, D6, D7, + R28, R31, + P0, P1, P2, P3, + M0, M1, + LC0, LC1, SA0, SA1, USR, USR_OVF]; } + +def PositiveHalfWord : PatLeaf<(i32 IntRegs:$a), +[{ + return isPositiveHalfWord(N); +}]>; diff --git a/lib/Target/Hexagon/HexagonSelectionDAGInfo.h b/lib/Target/Hexagon/HexagonSelectionDAGInfo.h index b40b30320cf1..8ac2e43f9294 100644 --- a/lib/Target/Hexagon/HexagonSelectionDAGInfo.h +++ b/lib/Target/Hexagon/HexagonSelectionDAGInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HexagonSELECTIONDAGINFO_H -#define HexagonSELECTIONDAGINFO_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONSELECTIONDAGINFO_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONSELECTIONDAGINFO_H #include "llvm/Target/TargetSelectionDAGInfo.h" diff --git a/lib/Target/Hexagon/HexagonSplitConst32AndConst64.cpp b/lib/Target/Hexagon/HexagonSplitConst32AndConst64.cpp index 247207f992dc..8fdd493a75dc 100644 --- a/lib/Target/Hexagon/HexagonSplitConst32AndConst64.cpp +++ b/lib/Target/Hexagon/HexagonSplitConst32AndConst64.cpp @@ -68,12 +68,13 @@ char HexagonSplitConst32AndConst64::ID = 0; bool HexagonSplitConst32AndConst64::runOnMachineFunction(MachineFunction &Fn) { const HexagonTargetObjectFile &TLOF = - (const HexagonTargetObjectFile &) - QTM.getTargetLowering()->getObjFileLowering(); + (const HexagonTargetObjectFile &)QTM.getSubtargetImpl() + ->getTargetLowering() + ->getObjFileLowering(); if (TLOF.IsSmallDataEnabled()) return true; - const TargetInstrInfo *TII = QTM.getInstrInfo(); + const TargetInstrInfo *TII = QTM.getSubtargetImpl()->getInstrInfo(); // Loop over all of the basic blocks for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); @@ -138,10 +139,10 @@ bool HexagonSplitConst32AndConst64::runOnMachineFunction(MachineFunction &Fn) { else if (Opc == Hexagon::CONST64_Int_Real) { int DestReg = MI->getOperand(0).getReg(); int64_t ImmValue = MI->getOperand(1).getImm (); - unsigned DestLo = - QTM.getRegisterInfo()->getSubReg (DestReg, Hexagon::subreg_loreg); - unsigned DestHi = - QTM.getRegisterInfo()->getSubReg (DestReg, Hexagon::subreg_hireg); + unsigned DestLo = QTM.getSubtargetImpl()->getRegisterInfo()->getSubReg( + DestReg, Hexagon::subreg_loreg); + unsigned DestHi = QTM.getSubtargetImpl()->getRegisterInfo()->getSubReg( + DestReg, Hexagon::subreg_hireg); int32_t LowWord = (ImmValue & 0xFFFFFFFF); int32_t HighWord = (ImmValue >> 32) & 0xFFFFFFFF; diff --git a/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp b/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp index 9601090af469..a304e655f0b1 100644 --- a/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp +++ b/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp @@ -80,7 +80,7 @@ char HexagonSplitTFRCondSets::ID = 0; bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { - const TargetInstrInfo *TII = QTM.getInstrInfo(); + const TargetInstrInfo *TII = QTM.getSubtargetImpl()->getInstrInfo(); // Loop over all of the basic blocks. for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); @@ -92,21 +92,19 @@ bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { MachineInstr *MI = MII; int Opc1, Opc2; switch(MI->getOpcode()) { - case Hexagon::TFR_condset_rr: case Hexagon::TFR_condset_rr_f: case Hexagon::TFR_condset_rr64_f: { int DestReg = MI->getOperand(0).getReg(); int SrcReg1 = MI->getOperand(2).getReg(); int SrcReg2 = MI->getOperand(3).getReg(); - if (MI->getOpcode() == Hexagon::TFR_condset_rr || - MI->getOpcode() == Hexagon::TFR_condset_rr_f) { - Opc1 = Hexagon::TFR_cPt; - Opc2 = Hexagon::TFR_cNotPt; + if (MI->getOpcode() == Hexagon::TFR_condset_rr_f) { + Opc1 = Hexagon::A2_tfrt; + Opc2 = Hexagon::A2_tfrf; } else if (MI->getOpcode() == Hexagon::TFR_condset_rr64_f) { - Opc1 = Hexagon::TFR64_cPt; - Opc2 = Hexagon::TFR64_cNotPt; + Opc1 = Hexagon::A2_tfrpt; + Opc2 = Hexagon::A2_tfrpf; } // Minor optimization: do not emit the predicated copy if the source @@ -132,12 +130,12 @@ bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { // is the same register. if (DestReg != SrcReg1) { BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::TFR_cPt), DestReg). + TII->get(Hexagon::A2_tfrt), DestReg). addReg(MI->getOperand(1).getReg()).addReg(SrcReg1); } if (MI->getOpcode() == Hexagon::TFR_condset_ri ) { BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::TFRI_cNotPt), DestReg). + TII->get(Hexagon::C2_cmoveif), DestReg). addReg(MI->getOperand(1).getReg()). addImm(MI->getOperand(3).getImm()); } else if (MI->getOpcode() == Hexagon::TFR_condset_ri_f ) { @@ -158,7 +156,7 @@ bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { if (MI->getOpcode() == Hexagon::TFR_condset_ir ) { BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::TFRI_cPt), DestReg). + TII->get(Hexagon::C2_cmoveit), DestReg). addReg(MI->getOperand(1).getReg()). addImm(MI->getOperand(2).getImm()); } else if (MI->getOpcode() == Hexagon::TFR_condset_ir_f ) { @@ -172,7 +170,7 @@ bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { // the destination is the same register. if (DestReg != SrcReg2) { BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::TFR_cNotPt), DestReg). + TII->get(Hexagon::A2_tfrf), DestReg). addReg(MI->getOperand(1).getReg()).addReg(SrcReg2); } MII = MBB->erase(MI); @@ -188,10 +186,10 @@ bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { int Immed1 = MI->getOperand(2).getImm(); int Immed2 = MI->getOperand(3).getImm(); BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::TFRI_cPt), + TII->get(Hexagon::C2_cmoveit), DestReg).addReg(SrcReg1).addImm(Immed1); BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::TFRI_cNotPt), + TII->get(Hexagon::C2_cmoveif), DestReg).addReg(SrcReg1).addImm(Immed2); } else if (MI->getOpcode() == Hexagon::TFR_condset_ii_f ) { BuildMI(*MBB, MII, MI->getDebugLoc(), diff --git a/lib/Target/Hexagon/HexagonSubtarget.h b/lib/Target/Hexagon/HexagonSubtarget.h index b184e62b4d0d..34e327f7c3a1 100644 --- a/lib/Target/Hexagon/HexagonSubtarget.h +++ b/lib/Target/Hexagon/HexagonSubtarget.h @@ -11,12 +11,12 @@ // //===----------------------------------------------------------------------===// -#ifndef Hexagon_SUBTARGET_H -#define Hexagon_SUBTARGET_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONSUBTARGET_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONSUBTARGET_H #include "HexagonFrameLowering.h" -#include "HexagonInstrInfo.h" #include "HexagonISelLowering.h" +#include "HexagonInstrInfo.h" #include "HexagonSelectionDAGInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetMachine.h" @@ -56,19 +56,25 @@ public: HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS, const TargetMachine &TM); - /// getInstrItins - Return the instruction itineraies based on subtarget + /// getInstrItins - Return the instruction itineraries based on subtarget /// selection. - const InstrItineraryData &getInstrItineraryData() const { return InstrItins; } - const HexagonInstrInfo *getInstrInfo() const { return &InstrInfo; } - const HexagonRegisterInfo *getRegisterInfo() const { + const InstrItineraryData *getInstrItineraryData() const override { + return &InstrItins; + } + const HexagonInstrInfo *getInstrInfo() const override { return &InstrInfo; } + const HexagonRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); } - const HexagonTargetLowering *getTargetLowering() const { return &TLInfo; } - const HexagonFrameLowering *getFrameLowering() const { + const HexagonTargetLowering *getTargetLowering() const override { + return &TLInfo; + } + const HexagonFrameLowering *getFrameLowering() const override { return &FrameLowering; } - const HexagonSelectionDAGInfo *getSelectionDAGInfo() const { return &TSInfo; } - const DataLayout *getDataLayout() const { return &DL; } + const HexagonSelectionDAGInfo *getSelectionDAGInfo() const override { + return &TSInfo; + } + const DataLayout *getDataLayout() const override { return &DL; } HexagonSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); diff --git a/lib/Target/Hexagon/HexagonTargetMachine.cpp b/lib/Target/Hexagon/HexagonTargetMachine.cpp index 78314100d18a..52aff2787bac 100644 --- a/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -70,10 +70,13 @@ HexagonTargetMachine::HexagonTargetMachine(const Target &T, StringRef TT, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), + TLOF(make_unique<HexagonTargetObjectFile>()), Subtarget(TT, CPU, FS, *this) { initAsmInfo(); } +HexagonTargetMachine::~HexagonTargetMachine() {} + namespace { /// Hexagon Code Generator Pass Configuration Options. class HexagonPassConfig : public TargetPassConfig { @@ -100,10 +103,10 @@ public: } bool addInstSelector() override; - bool addPreRegAlloc() override; - bool addPostRegAlloc() override; - bool addPreSched2() override; - bool addPreEmitPass() override; + void addPreRegAlloc() override; + void addPostRegAlloc() override; + void addPreSched2() override; + void addPreEmitPass() override; }; } // namespace @@ -128,51 +131,45 @@ bool HexagonPassConfig::addInstSelector() { return false; } -bool HexagonPassConfig::addPreRegAlloc() { +void HexagonPassConfig::addPreRegAlloc() { if (getOptLevel() != CodeGenOpt::None) if (!DisableHardwareLoops) - addPass(createHexagonHardwareLoops()); - return false; + addPass(createHexagonHardwareLoops(), false); } -bool HexagonPassConfig::addPostRegAlloc() { +void HexagonPassConfig::addPostRegAlloc() { const HexagonTargetMachine &TM = getHexagonTargetMachine(); if (getOptLevel() != CodeGenOpt::None) if (!DisableHexagonCFGOpt) - addPass(createHexagonCFGOptimizer(TM)); - return false; + addPass(createHexagonCFGOptimizer(TM), false); } -bool HexagonPassConfig::addPreSched2() { +void HexagonPassConfig::addPreSched2() { const HexagonTargetMachine &TM = getHexagonTargetMachine(); - addPass(createHexagonCopyToCombine()); + addPass(createHexagonCopyToCombine(), false); if (getOptLevel() != CodeGenOpt::None) - addPass(&IfConverterID); + addPass(&IfConverterID, false); addPass(createHexagonSplitConst32AndConst64(TM)); - printAndVerify("After hexagon split const32/64 pass"); - return true; } -bool HexagonPassConfig::addPreEmitPass() { +void HexagonPassConfig::addPreEmitPass() { const HexagonTargetMachine &TM = getHexagonTargetMachine(); bool NoOpt = (getOptLevel() == CodeGenOpt::None); if (!NoOpt) - addPass(createHexagonNewValueJump()); + addPass(createHexagonNewValueJump(), false); // Expand Spill code for predicate registers. - addPass(createHexagonExpandPredSpillCode(TM)); + addPass(createHexagonExpandPredSpillCode(TM), false); // Split up TFRcondsets into conditional transfers. - addPass(createHexagonSplitTFRCondSets(TM)); + addPass(createHexagonSplitTFRCondSets(TM), false); // Create Packets. if (!NoOpt) { if (!DisableHardwareLoops) - addPass(createHexagonFixupHwLoops()); - addPass(createHexagonPacketizer()); + addPass(createHexagonFixupHwLoops(), false); + addPass(createHexagonPacketizer(), false); } - - return false; } diff --git a/lib/Target/Hexagon/HexagonTargetMachine.h b/lib/Target/Hexagon/HexagonTargetMachine.h index d88178e052e7..4a9f44732a6b 100644 --- a/lib/Target/Hexagon/HexagonTargetMachine.h +++ b/lib/Target/Hexagon/HexagonTargetMachine.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HexagonTARGETMACHINE_H -#define HexagonTARGETMACHINE_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONTARGETMACHINE_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONTARGETMACHINE_H #include "HexagonInstrInfo.h" #include "HexagonSubtarget.h" @@ -23,6 +23,7 @@ namespace llvm { class Module; class HexagonTargetMachine : public LLVMTargetMachine { + std::unique_ptr<TargetLoweringObjectFile> TLOF; HexagonSubtarget Subtarget; public: @@ -30,34 +31,18 @@ public: StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); + ~HexagonTargetMachine() override; - const HexagonInstrInfo *getInstrInfo() const override { - return getSubtargetImpl()->getInstrInfo(); - } const HexagonSubtarget *getSubtargetImpl() const override { return &Subtarget; } - const HexagonRegisterInfo *getRegisterInfo() const override { - return getSubtargetImpl()->getRegisterInfo(); - } - const InstrItineraryData* getInstrItineraryData() const override { - return &getSubtargetImpl()->getInstrItineraryData(); - } - const HexagonTargetLowering* getTargetLowering() const override { - return getSubtargetImpl()->getTargetLowering(); - } - const HexagonFrameLowering* getFrameLowering() const override { - return getSubtargetImpl()->getFrameLowering(); - } - const HexagonSelectionDAGInfo* getSelectionDAGInfo() const override { - return getSubtargetImpl()->getSelectionDAGInfo(); - } - const DataLayout *getDataLayout() const override { - return getSubtargetImpl()->getDataLayout(); - } static unsigned getModuleMatchQuality(const Module &M); TargetPassConfig *createPassConfig(PassManagerBase &PM) override; + + TargetLoweringObjectFile *getObjFileLowering() const override { + return TLOF.get(); + } }; extern bool flag_aligned_memcpy; diff --git a/lib/Target/Hexagon/HexagonTargetObjectFile.cpp b/lib/Target/Hexagon/HexagonTargetObjectFile.cpp index c97526eed210..f4ab5e2b5c42 100644 --- a/lib/Target/Hexagon/HexagonTargetObjectFile.cpp +++ b/lib/Target/Hexagon/HexagonTargetObjectFile.cpp @@ -31,7 +31,7 @@ static cl::opt<int> SmallDataThreshold("hexagon-small-data-threshold", void HexagonTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM) { TargetLoweringObjectFileELF::Initialize(Ctx, TM); - + InitializeELF(TM.Options.UseInitArray); SmallDataSection = getContext().getELFSection(".sdata", ELF::SHT_PROGBITS, @@ -79,7 +79,8 @@ IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, if (Kind.isBSS() || Kind.isDataNoRel() || Kind.isCommon()) { Type *Ty = GV->getType()->getElementType(); - return IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(Ty)); + return IsInSmallSection( + TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(Ty)); } return false; diff --git a/lib/Target/Hexagon/HexagonTargetObjectFile.h b/lib/Target/Hexagon/HexagonTargetObjectFile.h index 1bd1272befcf..c97420427240 100644 --- a/lib/Target/Hexagon/HexagonTargetObjectFile.h +++ b/lib/Target/Hexagon/HexagonTargetObjectFile.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HexagonTARGETOBJECTFILE_H -#define HexagonTARGETOBJECTFILE_H +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONTARGETOBJECTFILE_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONTARGETOBJECTFILE_H #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/MC/MCSectionELF.h" diff --git a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp index 87ce960a60cf..c9605278e045 100644 --- a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp +++ b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp @@ -118,7 +118,6 @@ namespace { public: // Ctor. HexagonPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI, - MachineDominatorTree &MDT, const MachineBranchProbabilityInfo *MBPI); // initPacketizerState - initialize some internal flags. @@ -146,23 +145,23 @@ namespace { bool PromoteToDotNew(MachineInstr* MI, SDep::Kind DepType, MachineBasicBlock::iterator &MII, const TargetRegisterClass* RC); - bool CanPromoteToDotNew(MachineInstr* MI, SUnit* PacketSU, - unsigned DepReg, - std::map <MachineInstr*, SUnit*> MIToSUnit, + bool CanPromoteToDotNew(MachineInstr *MI, SUnit *PacketSU, unsigned DepReg, + const std::map<MachineInstr *, SUnit *> &MIToSUnit, MachineBasicBlock::iterator &MII, - const TargetRegisterClass* RC); - bool CanPromoteToNewValue(MachineInstr* MI, SUnit* PacketSU, - unsigned DepReg, - std::map <MachineInstr*, SUnit*> MIToSUnit, - MachineBasicBlock::iterator &MII); - bool CanPromoteToNewValueStore(MachineInstr* MI, MachineInstr* PacketMI, - unsigned DepReg, - std::map <MachineInstr*, SUnit*> MIToSUnit); - bool DemoteToDotOld(MachineInstr* MI); - bool ArePredicatesComplements(MachineInstr* MI1, MachineInstr* MI2, - std::map <MachineInstr*, SUnit*> MIToSUnit); - bool RestrictingDepExistInPacket(MachineInstr*, - unsigned, std::map <MachineInstr*, SUnit*>); + const TargetRegisterClass *RC); + bool + CanPromoteToNewValue(MachineInstr *MI, SUnit *PacketSU, unsigned DepReg, + const std::map<MachineInstr *, SUnit *> &MIToSUnit, + MachineBasicBlock::iterator &MII); + bool CanPromoteToNewValueStore( + MachineInstr *MI, MachineInstr *PacketMI, unsigned DepReg, + const std::map<MachineInstr *, SUnit *> &MIToSUnit); + bool DemoteToDotOld(MachineInstr *MI); + bool ArePredicatesComplements( + MachineInstr *MI1, MachineInstr *MI2, + const std::map<MachineInstr *, SUnit *> &MIToSUnit); + bool RestrictingDepExistInPacket(MachineInstr *, unsigned, + const std::map<MachineInstr *, SUnit *> &); bool isNewifiable(MachineInstr* MI); bool isCondInst(MachineInstr* MI); bool tryAllocateResourcesForConstExt(MachineInstr* MI); @@ -184,20 +183,19 @@ INITIALIZE_PASS_END(HexagonPacketizer, "packets", "Hexagon Packetizer", // HexagonPacketizerList Ctor. HexagonPacketizerList::HexagonPacketizerList( - MachineFunction &MF, MachineLoopInfo &MLI,MachineDominatorTree &MDT, - const MachineBranchProbabilityInfo *MBPI) - : VLIWPacketizerList(MF, MLI, MDT, true){ + MachineFunction &MF, MachineLoopInfo &MLI, + const MachineBranchProbabilityInfo *MBPI) + : VLIWPacketizerList(MF, MLI, true) { this->MBPI = MBPI; } bool HexagonPacketizer::runOnMachineFunction(MachineFunction &Fn) { - const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo(); + const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo(); MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>(); - MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>(); const MachineBranchProbabilityInfo *MBPI = &getAnalysis<MachineBranchProbabilityInfo>(); // Instantiate the packetizer. - HexagonPacketizerList Packetizer(Fn, MLI, MDT, MBPI); + HexagonPacketizerList Packetizer(Fn, MLI, MBPI); // DFA state table should not be empty. assert(Packetizer.getResourceTracker() && "Empty DFA table!"); @@ -266,7 +264,7 @@ bool HexagonPacketizer::runOnMachineFunction(MachineFunction &Fn) { static bool IsIndirectCall(MachineInstr* MI) { - return ((MI->getOpcode() == Hexagon::CALLR) || + return ((MI->getOpcode() == Hexagon::J2_callr) || (MI->getOpcode() == Hexagon::CALLRv3)); } @@ -275,7 +273,7 @@ static bool IsIndirectCall(MachineInstr* MI) { void HexagonPacketizerList::reserveResourcesForConstExt(MachineInstr* MI) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; MachineFunction *MF = MI->getParent()->getParent(); - MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::IMMEXT_i), + MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::A4_ext), MI->getDebugLoc()); if (ResourceTracker->canReserveResources(PseudoMI)) { @@ -293,7 +291,7 @@ bool HexagonPacketizerList::canReserveResourcesForConstExt(MachineInstr *MI) { assert((QII->isExtended(MI) || QII->isConstExtended(MI)) && "Should only be called for constant extended instructions"); MachineFunction *MF = MI->getParent()->getParent(); - MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::IMMEXT_i), + MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::A4_ext), MI->getDebugLoc()); bool CanReserve = ResourceTracker->canReserveResources(PseudoMI); MF->DeleteMachineInstr(PseudoMI); @@ -305,7 +303,7 @@ bool HexagonPacketizerList::canReserveResourcesForConstExt(MachineInstr *MI) { bool HexagonPacketizerList::tryAllocateResourcesForConstExt(MachineInstr* MI) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; MachineFunction *MF = MI->getParent()->getParent(); - MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::IMMEXT_i), + MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::A4_ext), MI->getDebugLoc()); if (ResourceTracker->canReserveResources(PseudoMI)) { @@ -324,8 +322,8 @@ bool HexagonPacketizerList::IsCallDependent(MachineInstr* MI, unsigned DepReg) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; - const HexagonRegisterInfo* QRI = - (const HexagonRegisterInfo *) TM.getRegisterInfo(); + const HexagonRegisterInfo *QRI = + (const HexagonRegisterInfo *)MF.getSubtarget().getRegisterInfo(); // Check for lr dependence if (DepReg == QRI->getRARegister()) { @@ -368,7 +366,7 @@ static bool IsRegDependence(const SDep::Kind DepType) { } static bool IsDirectJump(MachineInstr* MI) { - return (MI->getOpcode() == Hexagon::JMP); + return (MI->getOpcode() == Hexagon::J2_jump); } static bool IsSchedBarrier(MachineInstr* MI) { @@ -384,8 +382,8 @@ static bool IsControlFlow(MachineInstr* MI) { } static bool IsLoopN(MachineInstr *MI) { - return (MI->getOpcode() == Hexagon::LOOP0_i || - MI->getOpcode() == Hexagon::LOOP0_r); + return (MI->getOpcode() == Hexagon::J2_loop0i || + MI->getOpcode() == Hexagon::J2_loop0r); } /// DoesModifyCalleeSavedReg - Returns true if the instruction modifies a @@ -536,9 +534,9 @@ static MachineOperand& GetStoreValueOperand(MachineInstr *MI) { // if there is a new value store in the packet. Corollary, if there is // already a store in a packet, there can not be a new value store. // Arch Spec: 3.4.4.2 -bool HexagonPacketizerList::CanPromoteToNewValueStore( MachineInstr *MI, - MachineInstr *PacketMI, unsigned DepReg, - std::map <MachineInstr*, SUnit*> MIToSUnit) { +bool HexagonPacketizerList::CanPromoteToNewValueStore( + MachineInstr *MI, MachineInstr *PacketMI, unsigned DepReg, + const std::map<MachineInstr *, SUnit *> &MIToSUnit) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; // Make sure we are looking at the store, that can be promoted. if (!QII->mayBeNewStore(MI)) @@ -549,8 +547,8 @@ bool HexagonPacketizerList::CanPromoteToNewValueStore( MachineInstr *MI, GetStoreValueOperand(MI).getReg() != DepReg) return false; - const HexagonRegisterInfo* QRI = - (const HexagonRegisterInfo *) TM.getRegisterInfo(); + const HexagonRegisterInfo *QRI = + (const HexagonRegisterInfo *)MF.getSubtarget().getRegisterInfo(); const MCInstrDesc& MCID = PacketMI->getDesc(); // first operand is always the result @@ -561,12 +559,12 @@ bool HexagonPacketizerList::CanPromoteToNewValueStore( MachineInstr *MI, for (std::vector<MachineInstr*>::iterator VI = CurrentPacketMIs.begin(), VE = CurrentPacketMIs.end(); (VI != VE); ++VI) { - SUnit* PacketSU = MIToSUnit[*VI]; + SUnit *PacketSU = MIToSUnit.find(*VI)->second; if (PacketSU->getInstr()->getDesc().mayStore() || // if we have mayStore = 1 set on ALLOCFRAME and DEALLOCFRAME, // then we don't need this - PacketSU->getInstr()->getOpcode() == Hexagon::ALLOCFRAME || - PacketSU->getInstr()->getOpcode() == Hexagon::DEALLOCFRAME) + PacketSU->getInstr()->getOpcode() == Hexagon::S2_allocframe || + PacketSU->getInstr()->getOpcode() == Hexagon::L2_deallocframe) return false; } @@ -661,7 +659,7 @@ bool HexagonPacketizerList::CanPromoteToNewValueStore( MachineInstr *MI, for (VI=CurrentPacketMIs.begin(), VE = CurrentPacketMIs.end(); (VI != VE); ++VI) { - SUnit* TempSU = MIToSUnit[*VI]; + SUnit *TempSU = MIToSUnit.find(*VI)->second; MachineInstr* TempMI = TempSU->getInstr(); // Following condition is true for all the instructions until PacketMI is @@ -717,15 +715,14 @@ bool HexagonPacketizerList::CanPromoteToNewValueStore( MachineInstr *MI, // can this MI to promoted to either // new value store or new value jump -bool HexagonPacketizerList::CanPromoteToNewValue( MachineInstr *MI, - SUnit *PacketSU, unsigned DepReg, - std::map <MachineInstr*, SUnit*> MIToSUnit, - MachineBasicBlock::iterator &MII) -{ +bool HexagonPacketizerList::CanPromoteToNewValue( + MachineInstr *MI, SUnit *PacketSU, unsigned DepReg, + const std::map<MachineInstr *, SUnit *> &MIToSUnit, + MachineBasicBlock::iterator &MII) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; - const HexagonRegisterInfo* QRI = - (const HexagonRegisterInfo *) TM.getRegisterInfo(); + const HexagonRegisterInfo *QRI = + (const HexagonRegisterInfo *)MF.getSubtarget().getRegisterInfo(); if (!QRI->Subtarget.hasV4TOps() || !QII->mayBeNewStore(MI)) return false; @@ -746,12 +743,10 @@ bool HexagonPacketizerList::CanPromoteToNewValue( MachineInstr *MI, // 1. dot new on predicate - V2/V3/V4 // 2. dot new on stores NV/ST - V4 // 3. dot new on jump NV/J - V4 -- This is generated in a pass. -bool HexagonPacketizerList::CanPromoteToDotNew( MachineInstr *MI, - SUnit *PacketSU, unsigned DepReg, - std::map <MachineInstr*, SUnit*> MIToSUnit, - MachineBasicBlock::iterator &MII, - const TargetRegisterClass* RC ) -{ +bool HexagonPacketizerList::CanPromoteToDotNew( + MachineInstr *MI, SUnit *PacketSU, unsigned DepReg, + const std::map<MachineInstr *, SUnit *> &MIToSUnit, + MachineBasicBlock::iterator &MII, const TargetRegisterClass *RC) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; // Already a dot new instruction. if (QII->isDotNewInst(MI) && !QII->mayBeNewStore(MI)) @@ -803,12 +798,12 @@ bool HexagonPacketizerList::CanPromoteToDotNew( MachineInstr *MI, // The P3 from a) and d) will be complements after // a)'s P3 is converted to .new form // Anti Dep between c) and b) is irrelevant for this case -bool HexagonPacketizerList::RestrictingDepExistInPacket (MachineInstr* MI, - unsigned DepReg, - std::map <MachineInstr*, SUnit*> MIToSUnit) { +bool HexagonPacketizerList::RestrictingDepExistInPacket( + MachineInstr *MI, unsigned DepReg, + const std::map<MachineInstr *, SUnit *> &MIToSUnit) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; - SUnit* PacketSUDep = MIToSUnit[MI]; + SUnit *PacketSUDep = MIToSUnit.find(MI)->second; for (std::vector<MachineInstr*>::iterator VIN = CurrentPacketMIs.begin(), VEN = CurrentPacketMIs.end(); (VIN != VEN); ++VIN) { @@ -817,7 +812,7 @@ bool HexagonPacketizerList::RestrictingDepExistInPacket (MachineInstr* MI, if(!QII->isPredicated(*VIN)) continue; // Scheduling Unit for current insn in the packet - SUnit* PacketSU = MIToSUnit[*VIN]; + SUnit *PacketSU = MIToSUnit.find(*VIN)->second; // Look at dependencies between current members of the packet // and predicate defining instruction MI. @@ -861,8 +856,9 @@ static unsigned getPredicatedRegister(MachineInstr *MI, // Given two predicated instructions, this function detects whether // the predicates are complements -bool HexagonPacketizerList::ArePredicatesComplements (MachineInstr* MI1, - MachineInstr* MI2, std::map <MachineInstr*, SUnit*> MIToSUnit) { +bool HexagonPacketizerList::ArePredicatesComplements( + MachineInstr *MI1, MachineInstr *MI2, + const std::map<MachineInstr *, SUnit *> &MIToSUnit) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; @@ -873,7 +869,7 @@ bool HexagonPacketizerList::ArePredicatesComplements (MachineInstr* MI1, return false; // Scheduling unit for candidate - SUnit* SU = MIToSUnit[MI1]; + SUnit *SU = MIToSUnit.find(MI1)->second; // One corner case deals with the following scenario: // Trying to add @@ -898,7 +894,7 @@ bool HexagonPacketizerList::ArePredicatesComplements (MachineInstr* MI1, VEN = CurrentPacketMIs.end(); (VIN != VEN); ++VIN) { // Scheduling Unit for current insn in the packet - SUnit* PacketSU = MIToSUnit[*VIN]; + SUnit *PacketSU = MIToSUnit.find(*VIN)->second; // If this instruction in the packet is succeeded by the candidate... if (PacketSU->isSucc(SU)) { @@ -1007,8 +1003,8 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { MachineBasicBlock::iterator II = I; const unsigned FrameSize = MF.getFrameInfo()->getStackSize(); - const HexagonRegisterInfo* QRI = - (const HexagonRegisterInfo *) TM.getRegisterInfo(); + const HexagonRegisterInfo *QRI = + (const HexagonRegisterInfo *)MF.getSubtarget().getRegisterInfo(); const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; // Inline asm cannot go in the packet. @@ -1103,7 +1099,7 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { VI = CurrentPacketMIs.begin(), VE = CurrentPacketMIs.end(); (VI != VE && maintainNewValueJump); ++VI) { - SUnit* PacketSU = MIToSUnit[*VI]; + SUnit *PacketSU = MIToSUnit.find(*VI)->second; // NVJ can not be part of the dual jump - Arch Spec: section 7.8 if (PacketSU->getInstr()->getDesc().isCall()) { @@ -1119,7 +1115,7 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { // first operand is also a reg), first reg is not defined in // the same packet. if (PacketSU->getInstr()->getDesc().mayStore() || - PacketSU->getInstr()->getOpcode() == Hexagon::ALLOCFRAME || + PacketSU->getInstr()->getOpcode() == Hexagon::S2_allocframe || // Check #2. (!secondRegMatch && NextMI->getOperand(1).isReg() && PacketSU->getInstr()->modifiesRegister( @@ -1278,15 +1274,15 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { } // For V4, special case ALLOCFRAME. Even though there is dependency - // between ALLOCAFRAME and subsequent store, allow it to be + // between ALLOCFRAME and subsequent store, allow it to be // packetized in a same packet. This implies that the store is using - // caller's SP. Hense, offset needs to be updated accordingly. + // caller's SP. Hence, offset needs to be updated accordingly. else if (DepType == SDep::Data && QRI->Subtarget.hasV4TOps() - && J->getOpcode() == Hexagon::ALLOCFRAME - && (I->getOpcode() == Hexagon::STrid - || I->getOpcode() == Hexagon::STriw - || I->getOpcode() == Hexagon::STrib) + && J->getOpcode() == Hexagon::S2_allocframe + && (I->getOpcode() == Hexagon::S2_storerd_io + || I->getOpcode() == Hexagon::S2_storeri_io + || I->getOpcode() == Hexagon::S2_storerb_io) && I->getOperand(0).getReg() == QRI->getStackRegister() && QII->isValidOffset(I->getOpcode(), I->getOperand(1).getImm() - diff --git a/lib/Target/Hexagon/HexagonVarargsCallingConvention.h b/lib/Target/Hexagon/HexagonVarargsCallingConvention.h index 668ca98402b2..edbe29a5344a 100644 --- a/lib/Target/Hexagon/HexagonVarargsCallingConvention.h +++ b/lib/Target/Hexagon/HexagonVarargsCallingConvention.h @@ -74,10 +74,14 @@ static bool CC_Hexagon32_VarArgs(unsigned ValNo, EVT ValVT, } const Type* ArgTy = LocVT.getTypeForEVT(State.getContext()); - unsigned Alignment = - State.getTarget().getDataLayout()->getABITypeAlignment(ArgTy); + unsigned Alignment = State.getTarget() + .getSubtargetImpl() + ->getDataLayout() + ->getABITypeAlignment(ArgTy); unsigned Size = - State.getTarget().getDataLayout()->getTypeSizeInBits(ArgTy) / 8; + State.getTarget().getSubtargetImpl()->getDataLayout()->getTypeSizeInBits( + ArgTy) / + 8; // If it's passed by value, then we need the size of the aggregate not of // the pointer. @@ -129,10 +133,14 @@ static bool RetCC_Hexagon32_VarArgs(unsigned ValNo, EVT ValVT, } const Type* ArgTy = LocVT.getTypeForEVT(State.getContext()); - unsigned Alignment = - State.getTarget().getDataLayout()->getABITypeAlignment(ArgTy); + unsigned Alignment = State.getTarget() + .getSubtargetImpl() + ->getDataLayout() + ->getABITypeAlignment(ArgTy); unsigned Size = - State.getTarget().getDataLayout()->getTypeSizeInBits(ArgTy) / 8; + State.getTarget().getSubtargetImpl()->getDataLayout()->getTypeSizeInBits( + ArgTy) / + 8; unsigned Offset3 = State.AllocateStack(Size, Alignment); State.addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset3, diff --git a/lib/Target/Hexagon/InstPrinter/CMakeLists.txt b/lib/Target/Hexagon/InstPrinter/CMakeLists.txt deleted file mode 100644 index 1ddaf9bac203..000000000000 --- a/lib/Target/Hexagon/InstPrinter/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_llvm_library(LLVMHexagonAsmPrinter - HexagonInstPrinter.cpp - ) diff --git a/lib/Target/Hexagon/LLVMBuild.txt b/lib/Target/Hexagon/LLVMBuild.txt index a436b6e0454e..6ffd26a2022a 100644 --- a/lib/Target/Hexagon/LLVMBuild.txt +++ b/lib/Target/Hexagon/LLVMBuild.txt @@ -16,7 +16,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = InstPrinter MCTargetDesc TargetInfo +subdirectories = Disassembler MCTargetDesc TargetInfo [component_0] type = TargetGroup @@ -28,5 +28,5 @@ has_asmprinter = 1 type = Library name = HexagonCodeGen parent = Hexagon -required_libraries = Analysis AsmPrinter CodeGen Core HexagonAsmPrinter HexagonDesc HexagonInfo MC SelectionDAG Support Target +required_libraries = Analysis AsmPrinter CodeGen Core HexagonDesc HexagonInfo MC SelectionDAG Support Target add_to_library_groups = Hexagon diff --git a/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt b/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt index eeef3ef8c200..2a6124ee0c5a 100644 --- a/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt @@ -1,5 +1,11 @@ add_llvm_library(LLVMHexagonDesc + HexagonAsmBackend.cpp + HexagonELFObjectWriter.cpp + HexagonInstPrinter.cpp HexagonMCAsmInfo.cpp + HexagonMCCodeEmitter.cpp HexagonMCInst.cpp HexagonMCTargetDesc.cpp ) + +add_dependencies(LLVMHexagonDesc HexagonCommonTableGen) diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp new file mode 100644 index 000000000000..bdccf880d65f --- /dev/null +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp @@ -0,0 +1,74 @@ +//===-- HexagonAsmBackend.cpp - Hexagon Assembler Backend -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "HexagonMCTargetDesc.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCELFObjectWriter.h" + +using namespace llvm; + +namespace { + +class HexagonAsmBackend : public MCAsmBackend { +public: + HexagonAsmBackend(Target const & /*T*/) {} + + unsigned getNumFixupKinds() const override { return 0; } + + void applyFixup(MCFixup const & /*Fixup*/, char * /*Data*/, + unsigned /*DataSize*/, uint64_t /*Value*/, + bool /*IsPCRel*/) const override { + return; + } + + bool mayNeedRelaxation(MCInst const & /*Inst*/) const override { + return false; + } + + bool fixupNeedsRelaxation(MCFixup const & /*Fixup*/, uint64_t /*Value*/, + MCRelaxableFragment const * /*DF*/, + MCAsmLayout const & /*Layout*/) const override { + llvm_unreachable("fixupNeedsRelaxation() unimplemented"); + } + + void relaxInstruction(MCInst const & /*Inst*/, + MCInst & /*Res*/) const override { + llvm_unreachable("relaxInstruction() unimplemented"); + } + + bool writeNopData(uint64_t /*Count*/, + MCObjectWriter * /*OW*/) const override { + return true; + } +}; +} // end anonymous namespace + +namespace { +class ELFHexagonAsmBackend : public HexagonAsmBackend { + uint8_t OSABI; + +public: + ELFHexagonAsmBackend(Target const &T, uint8_t OSABI) + : HexagonAsmBackend(T), OSABI(OSABI) {} + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { + StringRef CPU("HexagonV4"); + return createHexagonELFObjectWriter(OS, OSABI, CPU); + } +}; +} // end anonymous namespace + +namespace llvm { +MCAsmBackend *createHexagonAsmBackend(Target const &T, + MCRegisterInfo const & /*MRI*/, + StringRef TT, StringRef /*CPU*/) { + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); + return new ELFHexagonAsmBackend(T, OSABI); +} +} diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h index f8be77cd3af5..8e02f799d7e4 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h @@ -14,11 +14,12 @@ // //===----------------------------------------------------------------------===// -#ifndef HEXAGONBASEINFO_H -#define HEXAGONBASEINFO_H +#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONBASEINFO_H +#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONBASEINFO_H #include "HexagonMCTargetDesc.h" #include "llvm/Support/ErrorHandling.h" +#include <stdint.h> namespace llvm { @@ -189,6 +190,15 @@ namespace HexagonII { MO_GPREL }; + enum class InstParseBits : uint32_t { + INST_PARSE_MASK = 0x0000c000, + INST_PARSE_PACKET_END = 0x0000c000, + INST_PARSE_LOOP_END = 0x00008000, + INST_PARSE_NOT_END = 0x00004000, + INST_PARSE_DUPLEX = 0x00000000, + INST_PARSE_EXTENDER = 0x00000000 + }; + } // End namespace HexagonII. } // End namespace llvm. diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp new file mode 100644 index 000000000000..56c9dc712a6e --- /dev/null +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp @@ -0,0 +1,62 @@ +//===-- HexagonELFObjectWriter.cpp - Hexagon Target Descriptions ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Hexagon.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "hexagon-elf-writer" + +using namespace llvm; +using namespace Hexagon; + +namespace { + +class HexagonELFObjectWriter : public MCELFObjectTargetWriter { +private: + StringRef CPU; + +public: + HexagonELFObjectWriter(uint8_t OSABI, StringRef C); + + virtual unsigned GetRelocType(MCValue const &Target, MCFixup const &Fixup, + bool IsPCRel) const override; +}; +} + +HexagonELFObjectWriter::HexagonELFObjectWriter(uint8_t OSABI, StringRef C) + : MCELFObjectTargetWriter(/*Is64bit*/ false, OSABI, ELF::EM_HEXAGON, + /*HasRelocationAddend*/ true), + CPU(C) {} + +unsigned HexagonELFObjectWriter::GetRelocType(MCValue const &/*Target*/, + MCFixup const &Fixup, + bool IsPCRel) const { + unsigned Type = (unsigned)ELF::R_HEX_NONE; + llvm::MCFixupKind Kind = Fixup.getKind(); + + switch (Kind) { + default: + DEBUG(dbgs() << "unrecognized relocation " << Fixup.getKind() << "\n"); + llvm_unreachable("Unimplemented Fixup kind!"); + break; + case FK_Data_4: + Type = (IsPCRel) ? ELF::R_HEX_32_PCREL : ELF::R_HEX_32; + break; + } + return Type; +} + +MCObjectWriter *llvm::createHexagonELFObjectWriter(raw_ostream &OS, + uint8_t OSABI, + StringRef CPU) { + MCELFObjectTargetWriter *MOTW = new HexagonELFObjectWriter(OSABI, CPU); + return createELFObjectWriter(MOTW, OS, /*IsLittleEndian*/ true); +}
\ No newline at end of file diff --git a/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonInstPrinter.cpp index 9942a6067d19..5c6f0363f78a 100644 --- a/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonInstPrinter.cpp @@ -29,6 +29,45 @@ using namespace llvm; #include "HexagonGenAsmWriter.inc" const char HexagonInstPrinter::PacketPadding = '\t'; +// Return the minimum value that a constant extendable operand can have +// without being extended. +static int getMinValue(uint64_t TSFlags) { + unsigned isSigned = + (TSFlags >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask; + unsigned bits = + (TSFlags >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask; + + if (isSigned) + return -1U << (bits - 1); + + return 0; +} + +// Return the maximum value that a constant extendable operand can have +// without being extended. +static int getMaxValue(uint64_t TSFlags) { + unsigned isSigned = + (TSFlags >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask; + unsigned bits = + (TSFlags >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask; + + if (isSigned) + return ~(-1U << (bits - 1)); + + return ~(-1U << bits); +} + +// Return true if the instruction must be extended. +static bool isExtended(uint64_t TSFlags) { + return (TSFlags >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; +} + +// Currently just used in an assert statement +static bool isExtendable(uint64_t TSFlags) LLVM_ATTRIBUTE_UNUSED; +// Return true if the instruction may be extended based on the operand value. +static bool isExtendable(uint64_t TSFlags) { + return (TSFlags >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask; +} StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const { return MII.getName(Opcode); @@ -52,14 +91,14 @@ void HexagonInstPrinter::printInst(const HexagonMCInst *MI, raw_ostream &O, // Ending a harware loop is different from ending an regular packet. assert(MI->isPacketEnd() && "Loop-end must also end the packet"); - if (MI->isPacketStart()) { + if (MI->isPacketBegin()) { // There must be a packet to end a loop. // FIXME: when shuffling is always run, this shouldn't be needed. HexagonMCInst Nop; StringRef NoAnnot; - Nop.setOpcode (Hexagon::NOP); - Nop.setPacketStart (MI->isPacketStart()); + Nop.setOpcode (Hexagon::A2_nop); + Nop.setPacketBegin (MI->isPacketBegin()); printInst (&Nop, O, NoAnnot); } @@ -71,7 +110,7 @@ void HexagonInstPrinter::printInst(const HexagonMCInst *MI, raw_ostream &O, } else { // Prefix the insn opening the packet. - if (MI->isPacketStart()) + if (MI->isPacketBegin()) O << PacketPadding << startPacket << '\n'; printInstruction(MI, O); @@ -116,9 +155,20 @@ void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo, void HexagonInstPrinter::printExtOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) const { - const HexagonMCInst *HMCI = static_cast<const HexagonMCInst*>(MI); - if (HMCI->isConstExtended()) + const MCOperand &MO = MI->getOperand(OpNo); + const MCInstrDesc &MII = getMII().get(MI->getOpcode()); + + assert((isExtendable(MII.TSFlags) || isExtended(MII.TSFlags)) && + "Expecting an extendable operand"); + + if (MO.isExpr() || isExtended(MII.TSFlags)) { O << "#"; + } else if (MO.isImm()) { + int ImmValue = MO.getImm(); + if (ImmValue < getMinValue(MII.TSFlags) || + ImmValue > getMaxValue(MII.TSFlags)) + O << "#"; + } printOperand(MI, OpNo, O); } diff --git a/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.h b/lib/Target/Hexagon/MCTargetDesc/HexagonInstPrinter.h index 09e3f88434ed..55ae95cd06df 100644 --- a/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonInstPrinter.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HEXAGONINSTPRINTER_H -#define HEXAGONINSTPRINTER_H +#ifndef LLVM_LIB_TARGET_HEXAGON_INSTPRINTER_HEXAGONINSTPRINTER_H +#define LLVM_LIB_TARGET_HEXAGON_INSTPRINTER_HEXAGONINSTPRINTER_H #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp index 141e514ce412..ad5e0fb15e7f 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp @@ -24,7 +24,6 @@ HexagonMCAsmInfo::HexagonMCAsmInfo(StringRef TT) { Data64bitsDirective = nullptr; // .xword is only supported by V9. ZeroDirective = "\t.skip\t"; CommentString = "//"; - HasLEB128 = true; LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment; InlineAsmStart = "# InlineAsm Start"; diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h index 953d804b49ab..ab18f0b37ba6 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef HexagonMCASMINFO_H -#define HexagonMCASMINFO_H +#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCASMINFO_H +#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCASMINFO_H #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCAsmInfoELF.h" diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp new file mode 100644 index 000000000000..487872a1f5dd --- /dev/null +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp @@ -0,0 +1,88 @@ +//===-- HexagonMCCodeEmitter.cpp - Hexagon Target Descriptions ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Hexagon.h" +#include "MCTargetDesc/HexagonBaseInfo.h" +#include "MCTargetDesc/HexagonMCCodeEmitter.h" +#include "MCTargetDesc/HexagonMCInst.h" +#include "MCTargetDesc/HexagonMCTargetDesc.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "mccodeemitter" + +using namespace llvm; +using namespace Hexagon; + +STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); + +namespace { +/// \brief 10.6 Instruction Packets +/// Possible values for instruction packet parse field. +enum class ParseField { duplex = 0x0, last0 = 0x1, last1 = 0x2, end = 0x3 }; +/// \brief Returns the packet bits based on instruction position. +uint32_t getPacketBits(HexagonMCInst const &HMI) { + unsigned const ParseFieldOffset = 14; + ParseField Field = HMI.isPacketEnd() ? ParseField::end : ParseField::last0; + return static_cast <uint32_t> (Field) << ParseFieldOffset; +} +void emitLittleEndian(uint64_t Binary, raw_ostream &OS) { + OS << static_cast<uint8_t>((Binary >> 0x00) & 0xff); + OS << static_cast<uint8_t>((Binary >> 0x08) & 0xff); + OS << static_cast<uint8_t>((Binary >> 0x10) & 0xff); + OS << static_cast<uint8_t>((Binary >> 0x18) & 0xff); +} +} + +HexagonMCCodeEmitter::HexagonMCCodeEmitter(MCInstrInfo const &aMII, + MCSubtargetInfo const &aMST, + MCContext &aMCT) + : MST(aMST), MCT(aMCT) {} + +void HexagonMCCodeEmitter::EncodeInstruction(MCInst const &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + MCSubtargetInfo const &STI) const { + HexagonMCInst const &HMB = static_cast<HexagonMCInst const &>(MI); + uint64_t Binary = getBinaryCodeForInstr(HMB, Fixups, STI) | getPacketBits(HMB); + assert(HMB.getDesc().getSize() == 4 && "All instructions should be 32bit"); + emitLittleEndian(Binary, OS); + ++MCNumEmitted; +} + +unsigned +HexagonMCCodeEmitter::getMachineOpValue(MCInst const &MI, MCOperand const &MO, + SmallVectorImpl<MCFixup> &Fixups, + MCSubtargetInfo const &STI) const { + if (MO.isReg()) + return MCT.getRegisterInfo()->getEncodingValue(MO.getReg()); + if (MO.isImm()) + return static_cast<unsigned>(MO.getImm()); + llvm_unreachable("Only Immediates and Registers implemented right now"); +} + +MCSubtargetInfo const &HexagonMCCodeEmitter::getSubtargetInfo() const { + return MST; +} + +MCCodeEmitter *llvm::createHexagonMCCodeEmitter(MCInstrInfo const &MII, + MCRegisterInfo const &MRI, + MCSubtargetInfo const &MST, + MCContext &MCT) { + return new HexagonMCCodeEmitter(MII, MST, MCT); +} + +#include "HexagonGenMCCodeEmitter.inc" diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h new file mode 100644 index 000000000000..96048adf34b7 --- /dev/null +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h @@ -0,0 +1,60 @@ +//===-- HexagonMCCodeEmitter.h - Hexagon Target Descriptions ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Definition for classes that emit Hexagon machine code from MCInsts +/// +//===----------------------------------------------------------------------===// + +#ifndef HEXAGONMCCODEEMITTER_H +#define HEXAGONMCCODEEMITTER_H + +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class HexagonMCCodeEmitter : public MCCodeEmitter { + MCSubtargetInfo const &MST; + MCContext &MCT; + +public: + HexagonMCCodeEmitter(MCInstrInfo const &aMII, MCSubtargetInfo const &aMST, + MCContext &aMCT); + + MCSubtargetInfo const &getSubtargetInfo() const; + + void EncodeInstruction(MCInst const &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + MCSubtargetInfo const &STI) const override; + + // \brief TableGen'erated function for getting the + // binary encoding for an instruction. + uint64_t getBinaryCodeForInstr(MCInst const &MI, + SmallVectorImpl<MCFixup> &Fixups, + MCSubtargetInfo const &STI) const; + + /// \brief Return binary encoding of operand. + unsigned getMachineOpValue(MCInst const &MI, MCOperand const &MO, + SmallVectorImpl<MCFixup> &Fixups, + MCSubtargetInfo const &STI) const; + +private: + HexagonMCCodeEmitter(HexagonMCCodeEmitter const &) LLVM_DELETED_FUNCTION; + void operator=(HexagonMCCodeEmitter const &) LLVM_DELETED_FUNCTION; +}; // class HexagonMCCodeEmitter + +} // namespace llvm + +#endif /* HEXAGONMCCODEEMITTER_H */ diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp index 9260b4a27661..d8b9a2567eeb 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp @@ -18,27 +18,77 @@ using namespace llvm; +std::unique_ptr <MCInstrInfo const> HexagonMCInst::MCII; + +HexagonMCInst::HexagonMCInst() : MCInst() {} +HexagonMCInst::HexagonMCInst(MCInstrDesc const &mcid) : MCInst() {} + +void HexagonMCInst::AppendImplicitOperands(MCInst &MCI) { + MCI.addOperand(MCOperand::CreateImm(0)); + MCI.addOperand(MCOperand::CreateInst(nullptr)); +} + +std::bitset<16> HexagonMCInst::GetImplicitBits(MCInst const &MCI) { + SanityCheckImplicitOperands(MCI); + std::bitset<16> Bits(MCI.getOperand(MCI.getNumOperands() - 2).getImm()); + return Bits; +} + +void HexagonMCInst::SetImplicitBits(MCInst &MCI, std::bitset<16> Bits) { + SanityCheckImplicitOperands(MCI); + MCI.getOperand(MCI.getNumOperands() - 2).setImm(Bits.to_ulong()); +} + +void HexagonMCInst::setPacketBegin(bool f) { + std::bitset<16> Bits(GetImplicitBits(*this)); + Bits.set(packetBeginIndex, f); + SetImplicitBits(*this, Bits); +} + +bool HexagonMCInst::isPacketBegin() const { + std::bitset<16> Bits(GetImplicitBits(*this)); + return Bits.test(packetBeginIndex); +} + +void HexagonMCInst::setPacketEnd(bool f) { + std::bitset<16> Bits(GetImplicitBits(*this)); + Bits.set(packetEndIndex, f); + SetImplicitBits(*this, Bits); +} + +bool HexagonMCInst::isPacketEnd() const { + std::bitset<16> Bits(GetImplicitBits(*this)); + return Bits.test(packetEndIndex); +} + +void HexagonMCInst::resetPacket() { + setPacketBegin(false); + setPacketEnd(false); +} + // Return the slots used by the insn. -unsigned HexagonMCInst::getUnits(const HexagonTargetMachine* TM) const { - const HexagonInstrInfo* QII = TM->getInstrInfo(); - const InstrItineraryData* II = TM->getInstrItineraryData(); - const InstrStage* - IS = II->beginStage(QII->get(this->getOpcode()).getSchedClass()); +unsigned HexagonMCInst::getUnits(const HexagonTargetMachine *TM) const { + const HexagonInstrInfo *QII = TM->getSubtargetImpl()->getInstrInfo(); + const InstrItineraryData *II = + TM->getSubtargetImpl()->getInstrItineraryData(); + const InstrStage *IS = + II->beginStage(QII->get(this->getOpcode()).getSchedClass()); return (IS->getUnits()); } +MCInstrDesc const& HexagonMCInst::getDesc() const { return (MCII->get(getOpcode())); } + // Return the Hexagon ISA class for the insn. unsigned HexagonMCInst::getType() const { - const uint64_t F = MCID->TSFlags; + const uint64_t F = getDesc().TSFlags; return ((F >> HexagonII::TypePos) & HexagonII::TypeMask); } // Return whether the insn is an actual insn. bool HexagonMCInst::isCanon() const { - return (!MCID->isPseudo() && - !isPrefix() && + return (!getDesc().isPseudo() && !isPrefix() && getType() != HexagonII::TypeENDLOOP); } @@ -49,30 +99,30 @@ bool HexagonMCInst::isPrefix() const { // Return whether the insn is solo, i.e., cannot be in a packet. bool HexagonMCInst::isSolo() const { - const uint64_t F = MCID->TSFlags; + const uint64_t F = getDesc().TSFlags; return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask); } // Return whether the insn is a new-value consumer. bool HexagonMCInst::isNewValue() const { - const uint64_t F = MCID->TSFlags; + const uint64_t F = getDesc().TSFlags; return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask); } // Return whether the instruction is a legal new-value producer. bool HexagonMCInst::hasNewValue() const { - const uint64_t F = MCID->TSFlags; + const uint64_t F = getDesc().TSFlags; return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask); } // Return the operand that consumes or produces a new value. -const MCOperand& HexagonMCInst::getNewValue() const { - const uint64_t F = MCID->TSFlags; - const unsigned O = (F >> HexagonII::NewValueOpPos) & - HexagonII::NewValueOpMask; - const MCOperand& MCO = getOperand(O); +const MCOperand &HexagonMCInst::getNewValue() const { + const uint64_t F = getDesc().TSFlags; + const unsigned O = + (F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask; + const MCOperand &MCO = getOperand(O); - assert ((isNewValue() || hasNewValue()) && MCO.isReg()); + assert((isNewValue() || hasNewValue()) && MCO.isReg()); return (MCO); } @@ -92,9 +142,9 @@ bool HexagonMCInst::isConstExtended(void) const { return false; short ExtOpNum = getCExtOpNum(); - int MinValue = getMinValue(); - int MaxValue = getMaxValue(); - const MCOperand& MO = getOperand(ExtOpNum); + int MinValue = getMinValue(); + int MaxValue = getMaxValue(); + const MCOperand &MO = getOperand(ExtOpNum); // We could be using an instruction with an extendable immediate and shoehorn // a global address into it. If it is a global address it will be constant @@ -115,46 +165,45 @@ bool HexagonMCInst::isConstExtended(void) const { // Return whether the instruction must be always extended. bool HexagonMCInst::isExtended(void) const { - const uint64_t F = MCID->TSFlags; + const uint64_t F = getDesc().TSFlags; return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; } // Return true if the instruction may be extended based on the operand value. bool HexagonMCInst::isExtendable(void) const { - const uint64_t F = MCID->TSFlags; + const uint64_t F = getDesc().TSFlags; return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask; } // Return number of bits in the constant extended operand. unsigned HexagonMCInst::getBitCount(void) const { - const uint64_t F = MCID->TSFlags; + const uint64_t F = getDesc().TSFlags; return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask); } // Return constant extended operand number. unsigned short HexagonMCInst::getCExtOpNum(void) const { - const uint64_t F = MCID->TSFlags; + const uint64_t F = getDesc().TSFlags; return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask); } // Return whether the operand can be constant extended. bool HexagonMCInst::isOperandExtended(const unsigned short OperandNum) const { - const uint64_t F = MCID->TSFlags; - return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) - == OperandNum; + const uint64_t F = getDesc().TSFlags; + return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) == + OperandNum; } // Return the min value that a constant extendable operand can have // without being extended. int HexagonMCInst::getMinValue(void) const { - const uint64_t F = MCID->TSFlags; - unsigned isSigned = (F >> HexagonII::ExtentSignedPos) - & HexagonII::ExtentSignedMask; - unsigned bits = (F >> HexagonII::ExtentBitsPos) - & HexagonII::ExtentBitsMask; + const uint64_t F = getDesc().TSFlags; + unsigned isSigned = + (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask; + unsigned bits = (F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask; if (isSigned) // if value is signed - return -1 << (bits - 1); + return -1U << (bits - 1); else return 0; } @@ -162,14 +211,13 @@ int HexagonMCInst::getMinValue(void) const { // Return the max value that a constant extendable operand can have // without being extended. int HexagonMCInst::getMaxValue(void) const { - const uint64_t F = MCID->TSFlags; - unsigned isSigned = (F >> HexagonII::ExtentSignedPos) - & HexagonII::ExtentSignedMask; - unsigned bits = (F >> HexagonII::ExtentBitsPos) - & HexagonII::ExtentBitsMask; + const uint64_t F = getDesc().TSFlags; + unsigned isSigned = + (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask; + unsigned bits = (F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask; if (isSigned) // if value is signed - return ~(-1 << (bits - 1)); + return ~(-1U << (bits - 1)); else - return ~(-1 << bits); + return ~(-1U << bits); } diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h index 3c52d4563f8c..ce9a8db5ac44 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h @@ -11,90 +11,98 @@ // //===----------------------------------------------------------------------===// -#ifndef HEXAGONMCINST_H -#define HEXAGONMCINST_H +#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINST_H +#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINST_H #include "HexagonTargetMachine.h" #include "llvm/MC/MCInst.h" +#include <memory> +extern "C" void LLVMInitializeHexagonTargetMC(); namespace llvm { - class MCOperand; +class MCOperand; - class HexagonMCInst: public MCInst { - // MCID is set during instruction lowering. - // It is needed in order to access TSFlags for - // use in checking MC instruction properties. - const MCInstrDesc *MCID; +class HexagonMCInst : public MCInst { + friend void ::LLVMInitializeHexagonTargetMC(); + // Used to access TSFlags + static std::unique_ptr <MCInstrInfo const> MCII; - // Packet start and end markers - unsigned packetStart: 1, packetEnd: 1; +public: + explicit HexagonMCInst(); + HexagonMCInst(const MCInstrDesc &mcid); - public: - explicit HexagonMCInst(): - MCInst(), MCID(nullptr), packetStart(0), packetEnd(0) {}; - HexagonMCInst(const MCInstrDesc& mcid): - MCInst(), MCID(&mcid), packetStart(0), packetEnd(0) {}; + static void AppendImplicitOperands(MCInst &MCI); + static std::bitset<16> GetImplicitBits(MCInst const &MCI); + static void SetImplicitBits(MCInst &MCI, std::bitset<16> Bits); + static void SanityCheckImplicitOperands(MCInst const &MCI) { + assert(MCI.getNumOperands() >= 2 && "At least the two implicit operands"); + assert(MCI.getOperand(MCI.getNumOperands() - 1).isInst() && + "Implicit bits and flags"); + assert(MCI.getOperand(MCI.getNumOperands() - 2).isImm() && + "Parent pointer"); + } - bool isPacketStart() const { return (packetStart); }; - bool isPacketEnd() const { return (packetEnd); }; - void setPacketStart(bool Y) { packetStart = Y; }; - void setPacketEnd(bool Y) { packetEnd = Y; }; - void resetPacket() { setPacketStart(false); setPacketEnd(false); }; + void setPacketBegin(bool Y); + bool isPacketBegin() const; + static const size_t packetBeginIndex = 0; + void setPacketEnd(bool Y); + bool isPacketEnd() const; + static const size_t packetEndIndex = 1; + void resetPacket(); - // Return the slots used by the insn. - unsigned getUnits(const HexagonTargetMachine* TM) const; + // Return the slots used by the insn. + unsigned getUnits(const HexagonTargetMachine *TM) const; - // Return the Hexagon ISA class for the insn. - unsigned getType() const; + // Return the Hexagon ISA class for the insn. + unsigned getType() const; - void setDesc(const MCInstrDesc& mcid) { MCID = &mcid; }; - const MCInstrDesc& getDesc(void) const { return *MCID; }; + MCInstrDesc const &getDesc() const; - // Return whether the insn is an actual insn. - bool isCanon() const; + // Return whether the insn is an actual insn. + bool isCanon() const; - // Return whether the insn is a prefix. - bool isPrefix() const; + // Return whether the insn is a prefix. + bool isPrefix() const; - // Return whether the insn is solo, i.e., cannot be in a packet. - bool isSolo() const; + // Return whether the insn is solo, i.e., cannot be in a packet. + bool isSolo() const; - // Return whether the instruction needs to be constant extended. - bool isConstExtended() const; + // Return whether the instruction needs to be constant extended. + bool isConstExtended() const; - // Return constant extended operand number. - unsigned short getCExtOpNum(void) const; + // Return constant extended operand number. + unsigned short getCExtOpNum(void) const; - // Return whether the insn is a new-value consumer. - bool isNewValue() const; + // Return whether the insn is a new-value consumer. + bool isNewValue() const; - // Return whether the instruction is a legal new-value producer. - bool hasNewValue() const; + // Return whether the instruction is a legal new-value producer. + bool hasNewValue() const; - // Return the operand that consumes or produces a new value. - const MCOperand& getNewValue() const; + // Return the operand that consumes or produces a new value. + const MCOperand &getNewValue() const; - // Return number of bits in the constant extended operand. - unsigned getBitCount(void) const; + // Return number of bits in the constant extended operand. + unsigned getBitCount(void) const; - private: - // Return whether the instruction must be always extended. - bool isExtended() const; +private: + // Return whether the instruction must be always extended. + bool isExtended() const; - // Return true if the insn may be extended based on the operand value. - bool isExtendable() const; + // Return true if the insn may be extended based on the operand value. + bool isExtendable() const; - // Return true if the operand can be constant extended. - bool isOperandExtended(const unsigned short OperandNum) const; + // Return true if the operand can be constant extended. + bool isOperandExtended(const unsigned short OperandNum) const; - // Return the min value that a constant extendable operand can have - // without being extended. - int getMinValue() const; + // Return the min value that a constant extendable operand can have + // without being extended. + int getMinValue() const; - // Return the max value that a constant extendable operand can have - // without being extended. - int getMaxValue() const; - }; + // Return the max value that a constant extendable operand can have + // without being extended. + int getMaxValue() const; +}; } #endif diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp index 581674dd6cb2..ae5a22bdb01b 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp @@ -13,8 +13,10 @@ #include "HexagonMCTargetDesc.h" #include "HexagonMCAsmInfo.h" -#include "InstPrinter/HexagonInstPrinter.h" +#include "MCTargetDesc/HexagonInstPrinter.h" +#include "MCTargetDesc/HexagonMCInst.h" #include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" @@ -46,9 +48,17 @@ static MCRegisterInfo *createHexagonMCRegisterInfo(StringRef TT) { return X; } -static MCSubtargetInfo *createHexagonMCSubtargetInfo(StringRef TT, - StringRef CPU, - StringRef FS) { +static MCStreamer * +createHexagonELFStreamer(MCContext &Context, MCAsmBackend &MAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll) { + MCELFStreamer *ES = new MCELFStreamer(Context, MAB, OS, CE); + return ES; +} + + +static MCSubtargetInfo * +createHexagonMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS) { MCSubtargetInfo *X = new MCSubtargetInfo(); InitHexagonMCSubtargetInfo(X, TT, CPU, FS); return X; @@ -59,22 +69,40 @@ static MCAsmInfo *createHexagonMCAsmInfo(const MCRegisterInfo &MRI, MCAsmInfo *MAI = new HexagonMCAsmInfo(TT); // VirtualFP = (R30 + #0). - MCCFIInstruction Inst = MCCFIInstruction::createDefCfa( - nullptr, Hexagon::R30, 0); + MCCFIInstruction Inst = + MCCFIInstruction::createDefCfa(nullptr, Hexagon::R30, 0); MAI->addInitialFrameState(Inst); return MAI; } +static MCStreamer *createMCStreamer(Target const &T, StringRef TT, + MCContext &Context, MCAsmBackend &MAB, + raw_ostream &OS, MCCodeEmitter *Emitter, + MCSubtargetInfo const &STI, bool RelaxAll) { + MCStreamer *ES = createHexagonELFStreamer(Context, MAB, OS, Emitter, RelaxAll); + new MCTargetStreamer(*ES); + return ES; +} + + static MCCodeGenInfo *createHexagonMCCodeGenInfo(StringRef TT, Reloc::Model RM, - CodeModel::Model CM, - CodeGenOpt::Level OL) { + CodeModel::Model CM, + CodeGenOpt::Level OL) { MCCodeGenInfo *X = new MCCodeGenInfo(); // For the time being, use static relocations, since there's really no // support for PIC yet. X->InitMCCodeGenInfo(Reloc::Static, CM, OL); return X; } +static MCInstPrinter *createHexagonMCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI) { + return new HexagonInstPrinter(MAI, MII, MRI); +} // Force static initialization. extern "C" void LLVMInitializeHexagonTargetMC() { @@ -86,7 +114,9 @@ extern "C" void LLVMInitializeHexagonTargetMC() { createHexagonMCCodeGenInfo); // Register the MC instruction info. - TargetRegistry::RegisterMCInstrInfo(TheHexagonTarget, createHexagonMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheHexagonTarget, + createHexagonMCInstrInfo); + HexagonMCInst::MCII.reset (createHexagonMCInstrInfo()); // Register the MC register info. TargetRegistry::RegisterMCRegInfo(TheHexagonTarget, @@ -95,4 +125,19 @@ extern "C" void LLVMInitializeHexagonTargetMC() { // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(TheHexagonTarget, createHexagonMCSubtargetInfo); + + // Register the MC Code Emitter + TargetRegistry::RegisterMCCodeEmitter(TheHexagonTarget, + createHexagonMCCodeEmitter); + + // Register the MC Inst Printer + TargetRegistry::RegisterMCInstPrinter(TheHexagonTarget, + createHexagonMCInstPrinter); + + // Register the asm backend + TargetRegistry::RegisterMCAsmBackend(TheHexagonTarget, + createHexagonAsmBackend); + + // Register the obj streamer + TargetRegistry::RegisterMCObjectStreamer(TheHexagonTarget, createMCStreamer); } diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h index 2238b1ae5f35..02fd5161d24a 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h @@ -11,15 +11,37 @@ // //===----------------------------------------------------------------------===// -#ifndef HEXAGONMCTARGETDESC_H -#define HEXAGONMCTARGETDESC_H +#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCTARGETDESC_H +#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCTARGETDESC_H + +#include <cstdint> namespace llvm { +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCInstrInfo; +class MCObjectWriter; +class MCRegisterInfo; class MCSubtargetInfo; class Target; +class StringRef; +class raw_ostream; extern Target TheHexagonTarget; +MCCodeEmitter *createHexagonMCCodeEmitter(MCInstrInfo const &MCII, + MCRegisterInfo const &MRI, + MCSubtargetInfo const &MST, + MCContext &MCT); + +MCAsmBackend *createHexagonAsmBackend(Target const &T, + MCRegisterInfo const &MRI, StringRef TT, + StringRef CPU); + +MCObjectWriter *createHexagonELFObjectWriter(raw_ostream &OS, uint8_t OSABI, + StringRef CPU); + } // End llvm namespace // Define symbolic names for Hexagon registers. This defines a mapping from diff --git a/lib/Target/Hexagon/MCTargetDesc/LLVMBuild.txt b/lib/Target/Hexagon/MCTargetDesc/LLVMBuild.txt index 73c7e016f939..f559a21e3f9e 100644 --- a/lib/Target/Hexagon/MCTargetDesc/LLVMBuild.txt +++ b/lib/Target/Hexagon/MCTargetDesc/LLVMBuild.txt @@ -19,5 +19,5 @@ type = Library name = HexagonDesc parent = Hexagon -required_libraries = HexagonInfo MC +required_libraries = HexagonInfo MC Support add_to_library_groups = Hexagon diff --git a/lib/Target/Hexagon/Makefile b/lib/Target/Hexagon/Makefile index dc387c549a1d..329c9d3018f0 100644 --- a/lib/Target/Hexagon/Makefile +++ b/lib/Target/Hexagon/Makefile @@ -14,10 +14,12 @@ TARGET = Hexagon BUILT_SOURCES = HexagonGenRegisterInfo.inc \ HexagonGenInstrInfo.inc \ HexagonGenAsmWriter.inc \ - HexagonGenDAGISel.inc HexagonGenSubtargetInfo.inc \ - HexagonGenCallingConv.inc \ - HexagonGenDFAPacketizer.inc - -DIRS = InstPrinter TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common + HexagonGenDAGISel.inc HexagonGenSubtargetInfo.inc \
+ HexagonGenCallingConv.inc \
+ HexagonGenDFAPacketizer.inc \
+ HexagonGenMCCodeEmitter.inc \
+ HexagonGenDisassemblerTables.inc
+
+DIRS = TargetInfo MCTargetDesc Disassembler
+
+include $(LEVEL)/Makefile.common
|