summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/SystemZ
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/SystemZ')
-rw-r--r--contrib/llvm/lib/Target/SystemZ/AsmPrinter/CMakeLists.txt6
-rw-r--r--contrib/llvm/lib/Target/SystemZ/AsmPrinter/Makefile15
-rw-r--r--contrib/llvm/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp217
-rw-r--r--contrib/llvm/lib/Target/SystemZ/CMakeLists.txt24
-rw-r--r--contrib/llvm/lib/Target/SystemZ/Makefile23
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZ.h61
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZ.td61
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZCallingConv.td46
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp782
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp859
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h145
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZInstrBuilder.h128
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZInstrFP.td340
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZInstrFormats.td133
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp644
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.h123
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.td1146
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZMCAsmInfo.cpp29
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZMCAsmInfo.h30
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZMachineFunctionInfo.h51
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZOperands.td310
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp343
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h73
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td480
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp23
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h31
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp47
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.h45
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp44
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZTargetMachine.h67
-rw-r--r--contrib/llvm/lib/Target/SystemZ/TargetInfo/CMakeLists.txt7
-rw-r--r--contrib/llvm/lib/Target/SystemZ/TargetInfo/Makefile15
-rw-r--r--contrib/llvm/lib/Target/SystemZ/TargetInfo/SystemZTargetInfo.cpp19
33 files changed, 6367 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Target/SystemZ/AsmPrinter/CMakeLists.txt b/contrib/llvm/lib/Target/SystemZ/AsmPrinter/CMakeLists.txt
new file mode 100644
index 0000000..c6be83a
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/AsmPrinter/CMakeLists.txt
@@ -0,0 +1,6 @@
+include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
+
+add_llvm_library(LLVMSystemZAsmPrinter
+ SystemZAsmPrinter.cpp
+ )
+add_dependencies(LLVMSystemZAsmPrinter SystemZCodeGenTable_gen)
diff --git a/contrib/llvm/lib/Target/SystemZ/AsmPrinter/Makefile b/contrib/llvm/lib/Target/SystemZ/AsmPrinter/Makefile
new file mode 100644
index 0000000..0f90ed3
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/AsmPrinter/Makefile
@@ -0,0 +1,15 @@
+##===- lib/Target/SystemZ/AsmPrinter/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../../../..
+LIBRARYNAME = LLVMSystemZAsmPrinter
+
+# Hack: we need to include 'main' SystemZ target directory to grab private headers
+CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
+
+include $(LEVEL)/Makefile.common
diff --git a/contrib/llvm/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp b/contrib/llvm/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp
new file mode 100644
index 0000000..90be222
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp
@@ -0,0 +1,217 @@
+//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly writer ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a printer that converts from our internal representation
+// of machine-dependent LLVM code to the SystemZ assembly language.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "asm-printer"
+#include "SystemZ.h"
+#include "SystemZInstrInfo.h"
+#include "SystemZTargetMachine.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/Assembly/Writer.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/Mangler.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+namespace {
+ class SystemZAsmPrinter : public AsmPrinter {
+ public:
+ SystemZAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
+ : AsmPrinter(TM, Streamer) {}
+
+ virtual const char *getPassName() const {
+ return "SystemZ Assembly Printer";
+ }
+
+ void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
+ const char* Modifier = 0);
+ void printPCRelImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
+ void printRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
+ const char* Modifier = 0);
+ void printRRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
+ const char* Modifier = 0);
+ void printS16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
+ O << (int16_t)MI->getOperand(OpNum).getImm();
+ }
+ void printS32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
+ O << (int32_t)MI->getOperand(OpNum).getImm();
+ }
+
+ void printInstruction(const MachineInstr *MI, raw_ostream &O);
+ static const char *getRegisterName(unsigned RegNo);
+
+ void EmitInstruction(const MachineInstr *MI);
+ };
+} // end of anonymous namespace
+
+#include "SystemZGenAsmWriter.inc"
+
+void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+ printInstruction(MI, OS);
+ OutStreamer.EmitRawText(OS.str());
+}
+
+void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum,
+ raw_ostream &O) {
+ const MachineOperand &MO = MI->getOperand(OpNum);
+ switch (MO.getType()) {
+ case MachineOperand::MO_Immediate:
+ O << MO.getImm();
+ return;
+ case MachineOperand::MO_MachineBasicBlock:
+ O << *MO.getMBB()->getSymbol();
+ return;
+ case MachineOperand::MO_GlobalAddress: {
+ const GlobalValue *GV = MO.getGlobal();
+ O << *Mang->getSymbol(GV);
+
+ // Assemble calls via PLT for externally visible symbols if PIC.
+ if (TM.getRelocationModel() == Reloc::PIC_ &&
+ !GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
+ !GV->hasLocalLinkage())
+ O << "@PLT";
+
+ printOffset(MO.getOffset(), O);
+ return;
+ }
+ case MachineOperand::MO_ExternalSymbol: {
+ std::string Name(MAI->getGlobalPrefix());
+ Name += MO.getSymbolName();
+ O << Name;
+
+ if (TM.getRelocationModel() == Reloc::PIC_)
+ O << "@PLT";
+
+ return;
+ }
+ default:
+ assert(0 && "Not implemented yet!");
+ }
+}
+
+
+void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
+ raw_ostream &O, const char *Modifier) {
+ const MachineOperand &MO = MI->getOperand(OpNum);
+ switch (MO.getType()) {
+ case MachineOperand::MO_Register: {
+ assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
+ "Virtual registers should be already mapped!");
+ unsigned Reg = MO.getReg();
+ if (Modifier && strncmp(Modifier, "subreg", 6) == 0) {
+ if (strncmp(Modifier + 7, "even", 4) == 0)
+ Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_even32);
+ else if (strncmp(Modifier + 7, "odd", 3) == 0)
+ Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_odd32);
+ else
+ assert(0 && "Invalid subreg modifier");
+ }
+
+ O << '%' << getRegisterName(Reg);
+ return;
+ }
+ case MachineOperand::MO_Immediate:
+ O << MO.getImm();
+ return;
+ case MachineOperand::MO_MachineBasicBlock:
+ O << *MO.getMBB()->getSymbol();
+ return;
+ case MachineOperand::MO_JumpTableIndex:
+ O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
+ << MO.getIndex();
+
+ return;
+ case MachineOperand::MO_ConstantPoolIndex:
+ O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
+ << MO.getIndex();
+
+ printOffset(MO.getOffset(), O);
+ break;
+ case MachineOperand::MO_GlobalAddress:
+ O << *Mang->getSymbol(MO.getGlobal());
+ break;
+ case MachineOperand::MO_ExternalSymbol: {
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
+ break;
+ }
+ default:
+ assert(0 && "Not implemented yet!");
+ }
+
+ switch (MO.getTargetFlags()) {
+ default: assert(0 && "Unknown target flag on GV operand");
+ case SystemZII::MO_NO_FLAG:
+ break;
+ case SystemZII::MO_GOTENT: O << "@GOTENT"; break;
+ case SystemZII::MO_PLT: O << "@PLT"; break;
+ }
+
+ printOffset(MO.getOffset(), O);
+}
+
+void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum,
+ raw_ostream &O,
+ const char *Modifier) {
+ const MachineOperand &Base = MI->getOperand(OpNum);
+
+ // Print displacement operand.
+ printOperand(MI, OpNum+1, O);
+
+ // Print base operand (if any)
+ if (Base.getReg()) {
+ O << '(';
+ printOperand(MI, OpNum, O);
+ O << ')';
+ }
+}
+
+void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum,
+ raw_ostream &O,
+ const char *Modifier) {
+ const MachineOperand &Base = MI->getOperand(OpNum);
+ const MachineOperand &Index = MI->getOperand(OpNum+2);
+
+ // Print displacement operand.
+ printOperand(MI, OpNum+1, O);
+
+ // Print base operand (if any)
+ if (Base.getReg()) {
+ O << '(';
+ printOperand(MI, OpNum, O);
+ if (Index.getReg()) {
+ O << ',';
+ printOperand(MI, OpNum+2, O);
+ }
+ O << ')';
+ } else
+ assert(!Index.getReg() && "Should allocate base register first!");
+}
+
+// Force static initialization.
+extern "C" void LLVMInitializeSystemZAsmPrinter() {
+ RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/CMakeLists.txt b/contrib/llvm/lib/Target/SystemZ/CMakeLists.txt
new file mode 100644
index 0000000..880e56f
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/CMakeLists.txt
@@ -0,0 +1,24 @@
+set(LLVM_TARGET_DEFINITIONS SystemZ.td)
+
+tablegen(SystemZGenRegisterInfo.h.inc -gen-register-desc-header)
+tablegen(SystemZGenRegisterNames.inc -gen-register-enums)
+tablegen(SystemZGenRegisterInfo.inc -gen-register-desc)
+tablegen(SystemZGenInstrNames.inc -gen-instr-enums)
+tablegen(SystemZGenInstrInfo.inc -gen-instr-desc)
+tablegen(SystemZGenAsmWriter.inc -gen-asm-writer)
+tablegen(SystemZGenDAGISel.inc -gen-dag-isel)
+tablegen(SystemZGenCallingConv.inc -gen-callingconv)
+tablegen(SystemZGenSubtarget.inc -gen-subtarget)
+
+add_llvm_target(SystemZCodeGen
+ SystemZISelDAGToDAG.cpp
+ SystemZISelLowering.cpp
+ SystemZInstrInfo.cpp
+ SystemZMCAsmInfo.cpp
+ SystemZRegisterInfo.cpp
+ SystemZSubtarget.cpp
+ SystemZTargetMachine.cpp
+ SystemZSelectionDAGInfo.cpp
+ )
+
+target_link_libraries (LLVMSystemZCodeGen LLVMSelectionDAG)
diff --git a/contrib/llvm/lib/Target/SystemZ/Makefile b/contrib/llvm/lib/Target/SystemZ/Makefile
new file mode 100644
index 0000000..5b44090
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/Makefile
@@ -0,0 +1,23 @@
+##===- lib/Target/SystemZ/Makefile ---------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+LIBRARYNAME = LLVMSystemZCodeGen
+TARGET = SystemZ
+
+# Make sure that tblgen is run, first thing.
+BUILT_SOURCES = SystemZGenRegisterInfo.h.inc SystemZGenRegisterNames.inc \
+ SystemZGenRegisterInfo.inc SystemZGenInstrNames.inc \
+ SystemZGenInstrInfo.inc SystemZGenAsmWriter.inc \
+ SystemZGenDAGISel.inc SystemZGenSubtarget.inc SystemZGenCallingConv.inc
+
+DIRS = AsmPrinter TargetInfo
+
+include $(LEVEL)/Makefile.common
+
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZ.h b/contrib/llvm/lib/Target/SystemZ/SystemZ.h
new file mode 100644
index 0000000..ea5240a
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZ.h
@@ -0,0 +1,61 @@
+//=-- SystemZ.h - Top-level interface for SystemZ representation -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the entry points for global functions defined in
+// the LLVM SystemZ backend.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_SystemZ_H
+#define LLVM_TARGET_SystemZ_H
+
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+ class SystemZTargetMachine;
+ class FunctionPass;
+ class formatted_raw_ostream;
+
+ namespace SystemZCC {
+ // SystemZ specific condition code. These correspond to SYSTEMZ_*_COND in
+ // SystemZInstrInfo.td. They must be kept in synch.
+ enum CondCodes {
+ O = 0,
+ H = 1,
+ NLE = 2,
+ L = 3,
+ NHE = 4,
+ LH = 5,
+ NE = 6,
+ E = 7,
+ NLH = 8,
+ HE = 9,
+ NL = 10,
+ LE = 11,
+ NH = 12,
+ NO = 13,
+ INVALID = -1
+ };
+ }
+
+ FunctionPass *createSystemZISelDag(SystemZTargetMachine &TM,
+ CodeGenOpt::Level OptLevel);
+
+ extern Target TheSystemZTarget;
+
+} // end namespace llvm;
+
+// Defines symbolic names for SystemZ registers.
+// This defines a mapping from register name to register number.
+#include "SystemZGenRegisterNames.inc"
+
+// Defines symbolic names for the SystemZ instructions.
+#include "SystemZGenInstrNames.inc"
+
+#endif
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZ.td b/contrib/llvm/lib/Target/SystemZ/SystemZ.td
new file mode 100644
index 0000000..4c08c08
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZ.td
@@ -0,0 +1,61 @@
+//===- SystemZ.td - Describe the SystemZ Target Machine ------*- tblgen -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This is the top level entry point for the SystemZ target.
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Target-independent interfaces
+//===----------------------------------------------------------------------===//
+
+include "llvm/Target/Target.td"
+
+//===----------------------------------------------------------------------===//
+// Subtarget Features.
+//===----------------------------------------------------------------------===//
+def FeatureZ10 : SubtargetFeature<"z10", "HasZ10Insts", "true",
+ "Support Z10 instructions">;
+
+//===----------------------------------------------------------------------===//
+// SystemZ supported processors.
+//===----------------------------------------------------------------------===//
+class Proc<string Name, list<SubtargetFeature> Features>
+ : Processor<Name, NoItineraries, Features>;
+
+def : Proc<"z9", []>;
+def : Proc<"z10", [FeatureZ10]>;
+
+//===----------------------------------------------------------------------===//
+// Register File Description
+//===----------------------------------------------------------------------===//
+
+include "SystemZRegisterInfo.td"
+
+//===----------------------------------------------------------------------===//
+// Calling Convention Description
+//===----------------------------------------------------------------------===//
+
+include "SystemZCallingConv.td"
+
+//===----------------------------------------------------------------------===//
+// Instruction Descriptions
+//===----------------------------------------------------------------------===//
+
+include "SystemZInstrInfo.td"
+include "SystemZInstrFP.td"
+
+def SystemZInstrInfo : InstrInfo {}
+
+//===----------------------------------------------------------------------===//
+// Target Declaration
+//===----------------------------------------------------------------------===//
+
+def SystemZ : Target {
+ let InstructionSet = SystemZInstrInfo;
+}
+
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZCallingConv.td b/contrib/llvm/lib/Target/SystemZ/SystemZCallingConv.td
new file mode 100644
index 0000000..c799a9e
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZCallingConv.td
@@ -0,0 +1,46 @@
+//=- SystemZCallingConv.td - Calling Conventions for SystemZ -*- tablegen -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This describes the calling conventions for SystemZ architecture.
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// SystemZ Return Value Calling Convention
+//===----------------------------------------------------------------------===//
+def RetCC_SystemZ : CallingConv<[
+ // Promote i8/i16/i32 arguments to i64.
+ CCIfType<[i8, i16, i32], CCPromoteToType<i64>>,
+
+ // i64 is returned in register R2
+ CCIfType<[i64], CCAssignToReg<[R2D, R3D, R4D, R5D]>>,
+
+ // f32 / f64 are returned in F0
+ CCIfType<[f32], CCAssignToReg<[F0S, F2S, F4S, F6S]>>,
+ CCIfType<[f64], CCAssignToReg<[F0L, F2L, F4L, F6L]>>
+]>;
+
+//===----------------------------------------------------------------------===//
+// SystemZ Argument Calling Conventions
+//===----------------------------------------------------------------------===//
+def CC_SystemZ : CallingConv<[
+ // Promote i8/i16/i32 arguments to i64.
+ CCIfType<[i8, i16, i32], CCPromoteToType<i64>>,
+
+ // The first 5 integer arguments of non-varargs functions are passed in
+ // integer registers.
+ CCIfType<[i64], CCAssignToReg<[R2D, R3D, R4D, R5D, R6D]>>,
+
+ // The first 4 floating point arguments of non-varargs functions are passed
+ // in FP registers.
+ CCIfType<[f32], CCAssignToReg<[F0S, F2S, F4S, F6S]>>,
+ CCIfType<[f64], CCAssignToReg<[F0L, F2L, F4L, F6L]>>,
+
+ // Integer values get stored in stack slots that are 8 bytes in
+ // size and 8-byte aligned.
+ CCIfType<[i64, f32, f64], CCAssignToStack<8, 8>>
+]>;
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
new file mode 100644
index 0000000..bb2952a
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
@@ -0,0 +1,782 @@
+//==-- SystemZISelDAGToDAG.cpp - A dag to dag inst selector for SystemZ ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an instruction selector for the SystemZ target.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZ.h"
+#include "SystemZTargetMachine.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/CallingConv.h"
+#include "llvm/Constants.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+namespace {
+ /// SystemZRRIAddressMode - This corresponds to rriaddr, but uses SDValue's
+ /// instead of register numbers for the leaves of the matched tree.
+ struct SystemZRRIAddressMode {
+ enum {
+ RegBase,
+ FrameIndexBase
+ } BaseType;
+
+ struct { // This is really a union, discriminated by BaseType!
+ SDValue Reg;
+ int FrameIndex;
+ } Base;
+
+ SDValue IndexReg;
+ int64_t Disp;
+ bool isRI;
+
+ SystemZRRIAddressMode(bool RI = false)
+ : BaseType(RegBase), IndexReg(), Disp(0), isRI(RI) {
+ }
+
+ void dump() {
+ errs() << "SystemZRRIAddressMode " << this << '\n';
+ if (BaseType == RegBase) {
+ errs() << "Base.Reg ";
+ if (Base.Reg.getNode() != 0)
+ Base.Reg.getNode()->dump();
+ else
+ errs() << "nul";
+ errs() << '\n';
+ } else {
+ errs() << " Base.FrameIndex " << Base.FrameIndex << '\n';
+ }
+ if (!isRI) {
+ errs() << "IndexReg ";
+ if (IndexReg.getNode() != 0) IndexReg.getNode()->dump();
+ else errs() << "nul";
+ }
+ errs() << " Disp " << Disp << '\n';
+ }
+ };
+}
+
+/// SystemZDAGToDAGISel - SystemZ specific code to select SystemZ machine
+/// instructions for SelectionDAG operations.
+///
+namespace {
+ class SystemZDAGToDAGISel : public SelectionDAGISel {
+ const SystemZTargetLowering &Lowering;
+ const SystemZSubtarget &Subtarget;
+
+ void getAddressOperandsRI(const SystemZRRIAddressMode &AM,
+ SDValue &Base, SDValue &Disp);
+ void getAddressOperands(const SystemZRRIAddressMode &AM,
+ SDValue &Base, SDValue &Disp,
+ SDValue &Index);
+
+ public:
+ SystemZDAGToDAGISel(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel)
+ : SelectionDAGISel(TM, OptLevel),
+ Lowering(*TM.getTargetLowering()),
+ Subtarget(*TM.getSubtargetImpl()) { }
+
+ virtual const char *getPassName() const {
+ return "SystemZ DAG->DAG Pattern Instruction Selection";
+ }
+
+ /// getI8Imm - Return a target constant with the specified value, of type
+ /// i8.
+ inline SDValue getI8Imm(uint64_t Imm) {
+ return CurDAG->getTargetConstant(Imm, MVT::i8);
+ }
+
+ /// getI16Imm - Return a target constant with the specified value, of type
+ /// i16.
+ inline SDValue getI16Imm(uint64_t Imm) {
+ return CurDAG->getTargetConstant(Imm, MVT::i16);
+ }
+
+ /// getI32Imm - Return a target constant with the specified value, of type
+ /// i32.
+ inline SDValue getI32Imm(uint64_t Imm) {
+ return CurDAG->getTargetConstant(Imm, MVT::i32);
+ }
+
+ // Include the pieces autogenerated from the target description.
+ #include "SystemZGenDAGISel.inc"
+
+ private:
+ bool SelectAddrRI12Only(SDNode *Op, SDValue& Addr,
+ SDValue &Base, SDValue &Disp);
+ bool SelectAddrRI12(SDNode *Op, SDValue& Addr,
+ SDValue &Base, SDValue &Disp,
+ bool is12BitOnly = false);
+ bool SelectAddrRI(SDNode *Op, SDValue& Addr,
+ SDValue &Base, SDValue &Disp);
+ bool SelectAddrRRI12(SDNode *Op, SDValue Addr,
+ SDValue &Base, SDValue &Disp, SDValue &Index);
+ bool SelectAddrRRI20(SDNode *Op, SDValue Addr,
+ SDValue &Base, SDValue &Disp, SDValue &Index);
+ bool SelectLAAddr(SDNode *Op, SDValue Addr,
+ SDValue &Base, SDValue &Disp, SDValue &Index);
+
+ SDNode *Select(SDNode *Node);
+
+ bool TryFoldLoad(SDNode *P, SDValue N,
+ SDValue &Base, SDValue &Disp, SDValue &Index);
+
+ bool MatchAddress(SDValue N, SystemZRRIAddressMode &AM,
+ bool is12Bit, unsigned Depth = 0);
+ bool MatchAddressBase(SDValue N, SystemZRRIAddressMode &AM);
+ bool MatchAddressRI(SDValue N, SystemZRRIAddressMode &AM,
+ bool is12Bit);
+ };
+} // end anonymous namespace
+
+/// createSystemZISelDag - This pass converts a legalized DAG into a
+/// SystemZ-specific DAG, ready for instruction scheduling.
+///
+FunctionPass *llvm::createSystemZISelDag(SystemZTargetMachine &TM,
+ CodeGenOpt::Level OptLevel) {
+ return new SystemZDAGToDAGISel(TM, OptLevel);
+}
+
+/// isImmSExt20 - This method tests to see if the node is either a 32-bit
+/// or 64-bit immediate, and if the value can be accurately represented as a
+/// sign extension from a 20-bit value. If so, this returns true and the
+/// immediate.
+static bool isImmSExt20(int64_t Val, int64_t &Imm) {
+ if (Val >= -524288 && Val <= 524287) {
+ Imm = Val;
+ return true;
+ }
+ return false;
+}
+
+/// isImmZExt12 - This method tests to see if the node is either a 32-bit
+/// or 64-bit immediate, and if the value can be accurately represented as a
+/// zero extension from a 12-bit value. If so, this returns true and the
+/// immediate.
+static bool isImmZExt12(int64_t Val, int64_t &Imm) {
+ if (Val >= 0 && Val <= 0xFFF) {
+ Imm = Val;
+ return true;
+ }
+ return false;
+}
+
+/// MatchAddress - Add the specified node to the specified addressing mode,
+/// returning true if it cannot be done. This just pattern matches for the
+/// addressing mode.
+bool SystemZDAGToDAGISel::MatchAddress(SDValue N, SystemZRRIAddressMode &AM,
+ bool is12Bit, unsigned Depth) {
+ DebugLoc dl = N.getDebugLoc();
+ DEBUG(errs() << "MatchAddress: "; AM.dump());
+ // Limit recursion.
+ if (Depth > 5)
+ return MatchAddressBase(N, AM);
+
+ // FIXME: We can perform better here. If we have something like
+ // (shift (add A, imm), N), we can try to reassociate stuff and fold shift of
+ // imm into addressing mode.
+ switch (N.getOpcode()) {
+ default: break;
+ case ISD::Constant: {
+ int64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
+ int64_t Imm = 0;
+ bool Match = (is12Bit ?
+ isImmZExt12(AM.Disp + Val, Imm) :
+ isImmSExt20(AM.Disp + Val, Imm));
+ if (Match) {
+ AM.Disp = Imm;
+ return false;
+ }
+ break;
+ }
+
+ case ISD::FrameIndex:
+ if (AM.BaseType == SystemZRRIAddressMode::RegBase &&
+ AM.Base.Reg.getNode() == 0) {
+ AM.BaseType = SystemZRRIAddressMode::FrameIndexBase;
+ AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
+ return false;
+ }
+ break;
+
+ case ISD::SUB: {
+ // Given A-B, if A can be completely folded into the address and
+ // the index field with the index field unused, use -B as the index.
+ // This is a win if a has multiple parts that can be folded into
+ // the address. Also, this saves a mov if the base register has
+ // other uses, since it avoids a two-address sub instruction, however
+ // it costs an additional mov if the index register has other uses.
+
+ // Test if the LHS of the sub can be folded.
+ SystemZRRIAddressMode Backup = AM;
+ if (MatchAddress(N.getNode()->getOperand(0), AM, is12Bit, Depth+1)) {
+ AM = Backup;
+ break;
+ }
+ // Test if the index field is free for use.
+ if (AM.IndexReg.getNode() || AM.isRI) {
+ AM = Backup;
+ break;
+ }
+
+ // If the base is a register with multiple uses, this transformation may
+ // save a mov. Otherwise it's probably better not to do it.
+ if (AM.BaseType == SystemZRRIAddressMode::RegBase &&
+ (!AM.Base.Reg.getNode() || AM.Base.Reg.getNode()->hasOneUse())) {
+ AM = Backup;
+ break;
+ }
+
+ // Ok, the transformation is legal and appears profitable. Go for it.
+ SDValue RHS = N.getNode()->getOperand(1);
+ SDValue Zero = CurDAG->getConstant(0, N.getValueType());
+ SDValue Neg = CurDAG->getNode(ISD::SUB, dl, N.getValueType(), Zero, RHS);
+ AM.IndexReg = Neg;
+
+ // Insert the new nodes into the topological ordering.
+ if (Zero.getNode()->getNodeId() == -1 ||
+ Zero.getNode()->getNodeId() > N.getNode()->getNodeId()) {
+ CurDAG->RepositionNode(N.getNode(), Zero.getNode());
+ Zero.getNode()->setNodeId(N.getNode()->getNodeId());
+ }
+ if (Neg.getNode()->getNodeId() == -1 ||
+ Neg.getNode()->getNodeId() > N.getNode()->getNodeId()) {
+ CurDAG->RepositionNode(N.getNode(), Neg.getNode());
+ Neg.getNode()->setNodeId(N.getNode()->getNodeId());
+ }
+ return false;
+ }
+
+ case ISD::ADD: {
+ SystemZRRIAddressMode Backup = AM;
+ if (!MatchAddress(N.getNode()->getOperand(0), AM, is12Bit, Depth+1) &&
+ !MatchAddress(N.getNode()->getOperand(1), AM, is12Bit, Depth+1))
+ return false;
+ AM = Backup;
+ if (!MatchAddress(N.getNode()->getOperand(1), AM, is12Bit, Depth+1) &&
+ !MatchAddress(N.getNode()->getOperand(0), AM, is12Bit, Depth+1))
+ return false;
+ AM = Backup;
+
+ // If we couldn't fold both operands into the address at the same time,
+ // see if we can just put each operand into a register and fold at least
+ // the add.
+ if (!AM.isRI &&
+ AM.BaseType == SystemZRRIAddressMode::RegBase &&
+ !AM.Base.Reg.getNode() && !AM.IndexReg.getNode()) {
+ AM.Base.Reg = N.getNode()->getOperand(0);
+ AM.IndexReg = N.getNode()->getOperand(1);
+ return false;
+ }
+ break;
+ }
+
+ case ISD::OR:
+ // Handle "X | C" as "X + C" iff X is known to have C bits clear.
+ if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+ SystemZRRIAddressMode Backup = AM;
+ int64_t Offset = CN->getSExtValue();
+ int64_t Imm = 0;
+ bool MatchOffset = (is12Bit ?
+ isImmZExt12(AM.Disp + Offset, Imm) :
+ isImmSExt20(AM.Disp + Offset, Imm));
+ // The resultant disp must fit in 12 or 20-bits.
+ if (MatchOffset &&
+ // LHS should be an addr mode.
+ !MatchAddress(N.getOperand(0), AM, is12Bit, Depth+1) &&
+ // Check to see if the LHS & C is zero.
+ CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
+ AM.Disp = Imm;
+ return false;
+ }
+ AM = Backup;
+ }
+ break;
+ }
+
+ return MatchAddressBase(N, AM);
+}
+
+/// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
+/// specified addressing mode without any further recursion.
+bool SystemZDAGToDAGISel::MatchAddressBase(SDValue N,
+ SystemZRRIAddressMode &AM) {
+ // Is the base register already occupied?
+ if (AM.BaseType != SystemZRRIAddressMode::RegBase || AM.Base.Reg.getNode()) {
+ // If so, check to see if the index register is set.
+ if (AM.IndexReg.getNode() == 0 && !AM.isRI) {
+ AM.IndexReg = N;
+ return false;
+ }
+
+ // Otherwise, we cannot select it.
+ return true;
+ }
+
+ // Default, generate it as a register.
+ AM.BaseType = SystemZRRIAddressMode::RegBase;
+ AM.Base.Reg = N;
+ return false;
+}
+
+void SystemZDAGToDAGISel::getAddressOperandsRI(const SystemZRRIAddressMode &AM,
+ SDValue &Base, SDValue &Disp) {
+ if (AM.BaseType == SystemZRRIAddressMode::RegBase)
+ Base = AM.Base.Reg;
+ else
+ Base = CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, TLI.getPointerTy());
+ Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i64);
+}
+
+void SystemZDAGToDAGISel::getAddressOperands(const SystemZRRIAddressMode &AM,
+ SDValue &Base, SDValue &Disp,
+ SDValue &Index) {
+ getAddressOperandsRI(AM, Base, Disp);
+ Index = AM.IndexReg;
+}
+
+/// Returns true if the address can be represented by a base register plus
+/// an unsigned 12-bit displacement [r+imm].
+bool SystemZDAGToDAGISel::SelectAddrRI12Only(SDNode *Op, SDValue& Addr,
+ SDValue &Base, SDValue &Disp) {
+ return SelectAddrRI12(Op, Addr, Base, Disp, /*is12BitOnly*/true);
+}
+
+bool SystemZDAGToDAGISel::SelectAddrRI12(SDNode *Op, SDValue& Addr,
+ SDValue &Base, SDValue &Disp,
+ bool is12BitOnly) {
+ SystemZRRIAddressMode AM20(/*isRI*/true), AM12(/*isRI*/true);
+ bool Done = false;
+
+ if (!Addr.hasOneUse()) {
+ unsigned Opcode = Addr.getOpcode();
+ if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) {
+ // If we are able to fold N into addressing mode, then we'll allow it even
+ // if N has multiple uses. In general, addressing computation is used as
+ // addresses by all of its uses. But watch out for CopyToReg uses, that
+ // means the address computation is liveout. It will be computed by a LA
+ // so we want to avoid computing the address twice.
+ for (SDNode::use_iterator UI = Addr.getNode()->use_begin(),
+ UE = Addr.getNode()->use_end(); UI != UE; ++UI) {
+ if (UI->getOpcode() == ISD::CopyToReg) {
+ MatchAddressBase(Addr, AM12);
+ Done = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!Done && MatchAddress(Addr, AM12, /* is12Bit */ true))
+ return false;
+
+ // Check, whether we can match stuff using 20-bit displacements
+ if (!Done && !is12BitOnly &&
+ !MatchAddress(Addr, AM20, /* is12Bit */ false))
+ if (AM12.Disp == 0 && AM20.Disp != 0)
+ return false;
+
+ DEBUG(errs() << "MatchAddress (final): "; AM12.dump());
+
+ EVT VT = Addr.getValueType();
+ if (AM12.BaseType == SystemZRRIAddressMode::RegBase) {
+ if (!AM12.Base.Reg.getNode())
+ AM12.Base.Reg = CurDAG->getRegister(0, VT);
+ }
+
+ assert(AM12.IndexReg.getNode() == 0 && "Invalid reg-imm address mode!");
+
+ getAddressOperandsRI(AM12, Base, Disp);
+
+ return true;
+}
+
+/// Returns true if the address can be represented by a base register plus
+/// a signed 20-bit displacement [r+imm].
+bool SystemZDAGToDAGISel::SelectAddrRI(SDNode *Op, SDValue& Addr,
+ SDValue &Base, SDValue &Disp) {
+ SystemZRRIAddressMode AM(/*isRI*/true);
+ bool Done = false;
+
+ if (!Addr.hasOneUse()) {
+ unsigned Opcode = Addr.getOpcode();
+ if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) {
+ // If we are able to fold N into addressing mode, then we'll allow it even
+ // if N has multiple uses. In general, addressing computation is used as
+ // addresses by all of its uses. But watch out for CopyToReg uses, that
+ // means the address computation is liveout. It will be computed by a LA
+ // so we want to avoid computing the address twice.
+ for (SDNode::use_iterator UI = Addr.getNode()->use_begin(),
+ UE = Addr.getNode()->use_end(); UI != UE; ++UI) {
+ if (UI->getOpcode() == ISD::CopyToReg) {
+ MatchAddressBase(Addr, AM);
+ Done = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!Done && MatchAddress(Addr, AM, /* is12Bit */ false))
+ return false;
+
+ DEBUG(errs() << "MatchAddress (final): "; AM.dump());
+
+ EVT VT = Addr.getValueType();
+ if (AM.BaseType == SystemZRRIAddressMode::RegBase) {
+ if (!AM.Base.Reg.getNode())
+ AM.Base.Reg = CurDAG->getRegister(0, VT);
+ }
+
+ assert(AM.IndexReg.getNode() == 0 && "Invalid reg-imm address mode!");
+
+ getAddressOperandsRI(AM, Base, Disp);
+
+ return true;
+}
+
+/// Returns true if the address can be represented by a base register plus
+/// index register plus an unsigned 12-bit displacement [base + idx + imm].
+bool SystemZDAGToDAGISel::SelectAddrRRI12(SDNode *Op, SDValue Addr,
+ SDValue &Base, SDValue &Disp, SDValue &Index) {
+ SystemZRRIAddressMode AM20, AM12;
+ bool Done = false;
+
+ if (!Addr.hasOneUse()) {
+ unsigned Opcode = Addr.getOpcode();
+ if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) {
+ // If we are able to fold N into addressing mode, then we'll allow it even
+ // if N has multiple uses. In general, addressing computation is used as
+ // addresses by all of its uses. But watch out for CopyToReg uses, that
+ // means the address computation is liveout. It will be computed by a LA
+ // so we want to avoid computing the address twice.
+ for (SDNode::use_iterator UI = Addr.getNode()->use_begin(),
+ UE = Addr.getNode()->use_end(); UI != UE; ++UI) {
+ if (UI->getOpcode() == ISD::CopyToReg) {
+ MatchAddressBase(Addr, AM12);
+ Done = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!Done && MatchAddress(Addr, AM12, /* is12Bit */ true))
+ return false;
+
+ // Check, whether we can match stuff using 20-bit displacements
+ if (!Done && !MatchAddress(Addr, AM20, /* is12Bit */ false))
+ if (AM12.Disp == 0 && AM20.Disp != 0)
+ return false;
+
+ DEBUG(errs() << "MatchAddress (final): "; AM12.dump());
+
+ EVT VT = Addr.getValueType();
+ if (AM12.BaseType == SystemZRRIAddressMode::RegBase) {
+ if (!AM12.Base.Reg.getNode())
+ AM12.Base.Reg = CurDAG->getRegister(0, VT);
+ }
+
+ if (!AM12.IndexReg.getNode())
+ AM12.IndexReg = CurDAG->getRegister(0, VT);
+
+ getAddressOperands(AM12, Base, Disp, Index);
+
+ return true;
+}
+
+/// Returns true if the address can be represented by a base register plus
+/// index register plus a signed 20-bit displacement [base + idx + imm].
+bool SystemZDAGToDAGISel::SelectAddrRRI20(SDNode *Op, SDValue Addr,
+ SDValue &Base, SDValue &Disp, SDValue &Index) {
+ SystemZRRIAddressMode AM;
+ bool Done = false;
+
+ if (!Addr.hasOneUse()) {
+ unsigned Opcode = Addr.getOpcode();
+ if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) {
+ // If we are able to fold N into addressing mode, then we'll allow it even
+ // if N has multiple uses. In general, addressing computation is used as
+ // addresses by all of its uses. But watch out for CopyToReg uses, that
+ // means the address computation is liveout. It will be computed by a LA
+ // so we want to avoid computing the address twice.
+ for (SDNode::use_iterator UI = Addr.getNode()->use_begin(),
+ UE = Addr.getNode()->use_end(); UI != UE; ++UI) {
+ if (UI->getOpcode() == ISD::CopyToReg) {
+ MatchAddressBase(Addr, AM);
+ Done = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!Done && MatchAddress(Addr, AM, /* is12Bit */ false))
+ return false;
+
+ DEBUG(errs() << "MatchAddress (final): "; AM.dump());
+
+ EVT VT = Addr.getValueType();
+ if (AM.BaseType == SystemZRRIAddressMode::RegBase) {
+ if (!AM.Base.Reg.getNode())
+ AM.Base.Reg = CurDAG->getRegister(0, VT);
+ }
+
+ if (!AM.IndexReg.getNode())
+ AM.IndexReg = CurDAG->getRegister(0, VT);
+
+ getAddressOperands(AM, Base, Disp, Index);
+
+ return true;
+}
+
+/// SelectLAAddr - it calls SelectAddr and determines if the maximal addressing
+/// mode it matches can be cost effectively emitted as an LA/LAY instruction.
+bool SystemZDAGToDAGISel::SelectLAAddr(SDNode *Op, SDValue Addr,
+ SDValue &Base, SDValue &Disp, SDValue &Index) {
+ SystemZRRIAddressMode AM;
+
+ if (MatchAddress(Addr, AM, false))
+ return false;
+
+ EVT VT = Addr.getValueType();
+ unsigned Complexity = 0;
+ if (AM.BaseType == SystemZRRIAddressMode::RegBase)
+ if (AM.Base.Reg.getNode())
+ Complexity = 1;
+ else
+ AM.Base.Reg = CurDAG->getRegister(0, VT);
+ else if (AM.BaseType == SystemZRRIAddressMode::FrameIndexBase)
+ Complexity = 4;
+
+ if (AM.IndexReg.getNode())
+ Complexity += 1;
+ else
+ AM.IndexReg = CurDAG->getRegister(0, VT);
+
+ if (AM.Disp && (AM.Base.Reg.getNode() || AM.IndexReg.getNode()))
+ Complexity += 1;
+
+ if (Complexity > 2) {
+ getAddressOperands(AM, Base, Disp, Index);
+ return true;
+ }
+
+ return false;
+}
+
+bool SystemZDAGToDAGISel::TryFoldLoad(SDNode *P, SDValue N,
+ SDValue &Base, SDValue &Disp, SDValue &Index) {
+ if (ISD::isNON_EXTLoad(N.getNode()) &&
+ IsLegalToFold(N, P, P, OptLevel))
+ return SelectAddrRRI20(P, N.getOperand(1), Base, Disp, Index);
+ return false;
+}
+
+SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) {
+ EVT NVT = Node->getValueType(0);
+ DebugLoc dl = Node->getDebugLoc();
+ unsigned Opcode = Node->getOpcode();
+
+ // Dump information about the Node being selected
+ DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");
+
+ // If we have a custom node, we already have selected!
+ if (Node->isMachineOpcode()) {
+ DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
+ return NULL; // Already selected.
+ }
+
+ switch (Opcode) {
+ default: break;
+ case ISD::SDIVREM: {
+ unsigned Opc, MOpc;
+ SDValue N0 = Node->getOperand(0);
+ SDValue N1 = Node->getOperand(1);
+
+ EVT ResVT;
+ bool is32Bit = false;
+ switch (NVT.getSimpleVT().SimpleTy) {
+ default: assert(0 && "Unsupported VT!");
+ case MVT::i32:
+ Opc = SystemZ::SDIVREM32r; MOpc = SystemZ::SDIVREM32m;
+ ResVT = MVT::v2i64;
+ is32Bit = true;
+ break;
+ case MVT::i64:
+ Opc = SystemZ::SDIVREM64r; MOpc = SystemZ::SDIVREM64m;
+ ResVT = MVT::v2i64;
+ break;
+ }
+
+ SDValue Tmp0, Tmp1, Tmp2;
+ bool foldedLoad = TryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2);
+
+ // Prepare the dividend
+ SDNode *Dividend;
+ if (is32Bit)
+ Dividend = CurDAG->getMachineNode(SystemZ::MOVSX64rr32, dl, MVT::i64, N0);
+ else
+ Dividend = N0.getNode();
+
+ // Insert prepared dividend into suitable 'subreg'
+ SDNode *Tmp = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
+ dl, ResVT);
+ Dividend =
+ CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl, ResVT,
+ SDValue(Tmp, 0), SDValue(Dividend, 0),
+ CurDAG->getTargetConstant(SystemZ::subreg_odd, MVT::i32));
+
+ SDNode *Result;
+ SDValue DivVal = SDValue(Dividend, 0);
+ if (foldedLoad) {
+ SDValue Ops[] = { DivVal, Tmp0, Tmp1, Tmp2, N1.getOperand(0) };
+ Result = CurDAG->getMachineNode(MOpc, dl, ResVT, MVT::Other,
+ Ops, array_lengthof(Ops));
+ // Update the chain.
+ ReplaceUses(N1.getValue(1), SDValue(Result, 1));
+ } else {
+ Result = CurDAG->getMachineNode(Opc, dl, ResVT, SDValue(Dividend, 0), N1);
+ }
+
+ // Copy the division (odd subreg) result, if it is needed.
+ if (!SDValue(Node, 0).use_empty()) {
+ unsigned SubRegIdx = (is32Bit ?
+ SystemZ::subreg_odd32 : SystemZ::subreg_odd);
+ SDNode *Div = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
+ dl, NVT,
+ SDValue(Result, 0),
+ CurDAG->getTargetConstant(SubRegIdx,
+ MVT::i32));
+
+ ReplaceUses(SDValue(Node, 0), SDValue(Div, 0));
+ DEBUG(errs() << "=> "; Result->dump(CurDAG); errs() << "\n");
+ }
+
+ // Copy the remainder (even subreg) result, if it is needed.
+ if (!SDValue(Node, 1).use_empty()) {
+ unsigned SubRegIdx = (is32Bit ?
+ SystemZ::subreg_even32 : SystemZ::subreg_even);
+ SDNode *Rem = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
+ dl, NVT,
+ SDValue(Result, 0),
+ CurDAG->getTargetConstant(SubRegIdx,
+ MVT::i32));
+
+ ReplaceUses(SDValue(Node, 1), SDValue(Rem, 0));
+ DEBUG(errs() << "=> "; Result->dump(CurDAG); errs() << "\n");
+ }
+
+ return NULL;
+ }
+ case ISD::UDIVREM: {
+ unsigned Opc, MOpc, ClrOpc;
+ SDValue N0 = Node->getOperand(0);
+ SDValue N1 = Node->getOperand(1);
+ EVT ResVT;
+
+ bool is32Bit = false;
+ switch (NVT.getSimpleVT().SimpleTy) {
+ default: assert(0 && "Unsupported VT!");
+ case MVT::i32:
+ Opc = SystemZ::UDIVREM32r; MOpc = SystemZ::UDIVREM32m;
+ ClrOpc = SystemZ::MOV64Pr0_even;
+ ResVT = MVT::v2i32;
+ is32Bit = true;
+ break;
+ case MVT::i64:
+ Opc = SystemZ::UDIVREM64r; MOpc = SystemZ::UDIVREM64m;
+ ClrOpc = SystemZ::MOV128r0_even;
+ ResVT = MVT::v2i64;
+ break;
+ }
+
+ SDValue Tmp0, Tmp1, Tmp2;
+ bool foldedLoad = TryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2);
+
+ // Prepare the dividend
+ SDNode *Dividend = N0.getNode();
+
+ // Insert prepared dividend into suitable 'subreg'
+ SDNode *Tmp = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
+ dl, ResVT);
+ {
+ unsigned SubRegIdx = (is32Bit ?
+ SystemZ::subreg_odd32 : SystemZ::subreg_odd);
+ Dividend =
+ CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl, ResVT,
+ SDValue(Tmp, 0), SDValue(Dividend, 0),
+ CurDAG->getTargetConstant(SubRegIdx, MVT::i32));
+ }
+
+ // Zero out even subreg
+ Dividend = CurDAG->getMachineNode(ClrOpc, dl, ResVT, SDValue(Dividend, 0));
+
+ SDValue DivVal = SDValue(Dividend, 0);
+ SDNode *Result;
+ if (foldedLoad) {
+ SDValue Ops[] = { DivVal, Tmp0, Tmp1, Tmp2, N1.getOperand(0) };
+ Result = CurDAG->getMachineNode(MOpc, dl, ResVT, MVT::Other,
+ Ops, array_lengthof(Ops));
+ // Update the chain.
+ ReplaceUses(N1.getValue(1), SDValue(Result, 1));
+ } else {
+ Result = CurDAG->getMachineNode(Opc, dl, ResVT, DivVal, N1);
+ }
+
+ // Copy the division (odd subreg) result, if it is needed.
+ if (!SDValue(Node, 0).use_empty()) {
+ unsigned SubRegIdx = (is32Bit ?
+ SystemZ::subreg_odd32 : SystemZ::subreg_odd);
+ SDNode *Div = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
+ dl, NVT,
+ SDValue(Result, 0),
+ CurDAG->getTargetConstant(SubRegIdx,
+ MVT::i32));
+ ReplaceUses(SDValue(Node, 0), SDValue(Div, 0));
+ DEBUG(errs() << "=> "; Result->dump(CurDAG); errs() << "\n");
+ }
+
+ // Copy the remainder (even subreg) result, if it is needed.
+ if (!SDValue(Node, 1).use_empty()) {
+ unsigned SubRegIdx = (is32Bit ?
+ SystemZ::subreg_even32 : SystemZ::subreg_even);
+ SDNode *Rem = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
+ dl, NVT,
+ SDValue(Result, 0),
+ CurDAG->getTargetConstant(SubRegIdx,
+ MVT::i32));
+ ReplaceUses(SDValue(Node, 1), SDValue(Rem, 0));
+ DEBUG(errs() << "=> "; Result->dump(CurDAG); errs() << "\n");
+ }
+
+ return NULL;
+ }
+ }
+
+ // Select the default instruction
+ SDNode *ResNode = SelectCode(Node);
+
+ DEBUG(errs() << "=> ";
+ if (ResNode == NULL || ResNode == Node)
+ Node->dump(CurDAG);
+ else
+ ResNode->dump(CurDAG);
+ errs() << "\n";
+ );
+ return ResNode;
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
new file mode 100644
index 0000000..76f2901
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -0,0 +1,859 @@
+//===-- SystemZISelLowering.cpp - SystemZ DAG Lowering Implementation -----==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SystemZTargetLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "systemz-lower"
+
+#include "SystemZISelLowering.h"
+#include "SystemZ.h"
+#include "SystemZTargetMachine.h"
+#include "SystemZSubtarget.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/CallingConv.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/GlobalAlias.h"
+#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/VectorExtras.h"
+using namespace llvm;
+
+SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
+ TargetLowering(tm, new TargetLoweringObjectFileELF()),
+ Subtarget(*tm.getSubtargetImpl()), TM(tm) {
+
+ RegInfo = TM.getRegisterInfo();
+
+ // Set up the register classes.
+ addRegisterClass(MVT::i32, SystemZ::GR32RegisterClass);
+ addRegisterClass(MVT::i64, SystemZ::GR64RegisterClass);
+ addRegisterClass(MVT::v2i32,SystemZ::GR64PRegisterClass);
+ addRegisterClass(MVT::v2i64,SystemZ::GR128RegisterClass);
+
+ if (!UseSoftFloat) {
+ addRegisterClass(MVT::f32, SystemZ::FP32RegisterClass);
+ addRegisterClass(MVT::f64, SystemZ::FP64RegisterClass);
+ }
+
+ // Compute derived properties from the register classes
+ computeRegisterProperties();
+
+ // Set shifts properties
+ setShiftAmountType(MVT::i64);
+
+ // Provide all sorts of operation actions
+ setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
+ setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
+ setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
+
+ setLoadExtAction(ISD::SEXTLOAD, MVT::f32, Expand);
+ setLoadExtAction(ISD::ZEXTLOAD, MVT::f32, Expand);
+ setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
+
+ setLoadExtAction(ISD::SEXTLOAD, MVT::f64, Expand);
+ setLoadExtAction(ISD::ZEXTLOAD, MVT::f64, Expand);
+ setLoadExtAction(ISD::EXTLOAD, MVT::f64, Expand);
+
+ setStackPointerRegisterToSaveRestore(SystemZ::R15D);
+
+ // TODO: It may be better to default to latency-oriented scheduling, however
+ // LLVM's current latency-oriented scheduler can't handle physreg definitions
+ // such as SystemZ has with PSW, so set this to the register-pressure
+ // scheduler, because it can.
+ setSchedulingPreference(Sched::RegPressure);
+
+ setBooleanContents(ZeroOrOneBooleanContent);
+
+ setOperationAction(ISD::BR_JT, MVT::Other, Expand);
+ setOperationAction(ISD::BRCOND, MVT::Other, Expand);
+ setOperationAction(ISD::BR_CC, MVT::i32, Custom);
+ setOperationAction(ISD::BR_CC, MVT::i64, Custom);
+ setOperationAction(ISD::BR_CC, MVT::f32, Custom);
+ setOperationAction(ISD::BR_CC, MVT::f64, Custom);
+ setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
+ setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
+ setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
+ setOperationAction(ISD::JumpTable, MVT::i64, Custom);
+ setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
+
+ setOperationAction(ISD::SDIV, MVT::i32, Expand);
+ setOperationAction(ISD::UDIV, MVT::i32, Expand);
+ setOperationAction(ISD::SDIV, MVT::i64, Expand);
+ setOperationAction(ISD::UDIV, MVT::i64, Expand);
+ setOperationAction(ISD::SREM, MVT::i32, Expand);
+ setOperationAction(ISD::UREM, MVT::i32, Expand);
+ setOperationAction(ISD::SREM, MVT::i64, Expand);
+ setOperationAction(ISD::UREM, MVT::i64, Expand);
+
+ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
+
+ setOperationAction(ISD::CTPOP, MVT::i32, Expand);
+ setOperationAction(ISD::CTPOP, MVT::i64, Expand);
+ setOperationAction(ISD::CTTZ, MVT::i32, Expand);
+ setOperationAction(ISD::CTTZ, MVT::i64, Expand);
+ setOperationAction(ISD::CTLZ, MVT::i32, Promote);
+ setOperationAction(ISD::CTLZ, MVT::i64, Legal);
+
+ // FIXME: Can we lower these 2 efficiently?
+ setOperationAction(ISD::SETCC, MVT::i32, Expand);
+ setOperationAction(ISD::SETCC, MVT::i64, Expand);
+ setOperationAction(ISD::SETCC, MVT::f32, Expand);
+ setOperationAction(ISD::SETCC, MVT::f64, Expand);
+ setOperationAction(ISD::SELECT, MVT::i32, Expand);
+ setOperationAction(ISD::SELECT, MVT::i64, Expand);
+ setOperationAction(ISD::SELECT, MVT::f32, Expand);
+ setOperationAction(ISD::SELECT, MVT::f64, Expand);
+ setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
+ setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
+ setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
+ setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
+
+ setOperationAction(ISD::MULHS, MVT::i64, Expand);
+ setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
+
+ // FIXME: Can we support these natively?
+ setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
+ setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand);
+ setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand);
+ setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand);
+
+ // Lower some FP stuff
+ setOperationAction(ISD::FSIN, MVT::f32, Expand);
+ setOperationAction(ISD::FSIN, MVT::f64, Expand);
+ setOperationAction(ISD::FCOS, MVT::f32, Expand);
+ setOperationAction(ISD::FCOS, MVT::f64, Expand);
+ setOperationAction(ISD::FREM, MVT::f32, Expand);
+ setOperationAction(ISD::FREM, MVT::f64, Expand);
+
+ // We have only 64-bit bitconverts
+ setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand);
+ setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand);
+
+ setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
+ setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
+ setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
+ setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
+
+ setTruncStoreAction(MVT::f64, MVT::f32, Expand);
+}
+
+SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
+ SelectionDAG &DAG) const {
+ switch (Op.getOpcode()) {
+ case ISD::BR_CC: return LowerBR_CC(Op, DAG);
+ case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
+ case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
+ case ISD::JumpTable: return LowerJumpTable(Op, DAG);
+ case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
+ default:
+ llvm_unreachable("Should not custom lower this!");
+ return SDValue();
+ }
+}
+
+bool SystemZTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
+ if (UseSoftFloat || (VT != MVT::f32 && VT != MVT::f64))
+ return false;
+
+ // +0.0 lzer
+ // +0.0f lzdr
+ // -0.0 lzer + lner
+ // -0.0f lzdr + lndr
+ return Imm.isZero() || Imm.isNegZero();
+}
+
+//===----------------------------------------------------------------------===//
+// SystemZ Inline Assembly Support
+//===----------------------------------------------------------------------===//
+
+/// getConstraintType - Given a constraint letter, return the type of
+/// constraint it is for this target.
+TargetLowering::ConstraintType
+SystemZTargetLowering::getConstraintType(const std::string &Constraint) const {
+ if (Constraint.size() == 1) {
+ switch (Constraint[0]) {
+ case 'r':
+ return C_RegisterClass;
+ default:
+ break;
+ }
+ }
+ return TargetLowering::getConstraintType(Constraint);
+}
+
+std::pair<unsigned, const TargetRegisterClass*>
+SystemZTargetLowering::
+getRegForInlineAsmConstraint(const std::string &Constraint,
+ EVT VT) const {
+ if (Constraint.size() == 1) {
+ // GCC Constraint Letters
+ switch (Constraint[0]) {
+ default: break;
+ case 'r': // GENERAL_REGS
+ if (VT == MVT::i32)
+ return std::make_pair(0U, SystemZ::GR32RegisterClass);
+ else if (VT == MVT::i128)
+ return std::make_pair(0U, SystemZ::GR128RegisterClass);
+
+ return std::make_pair(0U, SystemZ::GR64RegisterClass);
+ }
+ }
+
+ return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
+}
+
+//===----------------------------------------------------------------------===//
+// Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+
+#include "SystemZGenCallingConv.inc"
+
+SDValue
+SystemZTargetLowering::LowerFormalArguments(SDValue Chain,
+ CallingConv::ID CallConv,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg>
+ &Ins,
+ DebugLoc dl,
+ SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals)
+ const {
+
+ switch (CallConv) {
+ default:
+ llvm_unreachable("Unsupported calling convention");
+ case CallingConv::C:
+ case CallingConv::Fast:
+ return LowerCCCArguments(Chain, CallConv, isVarArg, Ins, dl, DAG, InVals);
+ }
+}
+
+SDValue
+SystemZTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
+ CallingConv::ID CallConv, bool isVarArg,
+ bool &isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const {
+ // SystemZ target does not yet support tail call optimization.
+ isTailCall = false;
+
+ switch (CallConv) {
+ default:
+ llvm_unreachable("Unsupported calling convention");
+ case CallingConv::Fast:
+ case CallingConv::C:
+ return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
+ Outs, Ins, dl, DAG, InVals);
+ }
+}
+
+/// LowerCCCArguments - transform physical registers into virtual registers and
+/// generate load operations for arguments places on the stack.
+// FIXME: struct return stuff
+// FIXME: varargs
+SDValue
+SystemZTargetLowering::LowerCCCArguments(SDValue Chain,
+ CallingConv::ID CallConv,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg>
+ &Ins,
+ DebugLoc dl,
+ SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals)
+ const {
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ MachineRegisterInfo &RegInfo = MF.getRegInfo();
+
+ // Assign locations to all of the incoming arguments.
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
+ ArgLocs, *DAG.getContext());
+ CCInfo.AnalyzeFormalArguments(Ins, CC_SystemZ);
+
+ if (isVarArg)
+ report_fatal_error("Varargs not supported yet");
+
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ SDValue ArgValue;
+ CCValAssign &VA = ArgLocs[i];
+ EVT LocVT = VA.getLocVT();
+ if (VA.isRegLoc()) {
+ // Arguments passed in registers
+ TargetRegisterClass *RC;
+ switch (LocVT.getSimpleVT().SimpleTy) {
+ default:
+#ifndef NDEBUG
+ errs() << "LowerFormalArguments Unhandled argument type: "
+ << LocVT.getSimpleVT().SimpleTy
+ << "\n";
+#endif
+ llvm_unreachable(0);
+ case MVT::i64:
+ RC = SystemZ::GR64RegisterClass;
+ break;
+ case MVT::f32:
+ RC = SystemZ::FP32RegisterClass;
+ break;
+ case MVT::f64:
+ RC = SystemZ::FP64RegisterClass;
+ break;
+ }
+
+ unsigned VReg = RegInfo.createVirtualRegister(RC);
+ RegInfo.addLiveIn(VA.getLocReg(), VReg);
+ ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, LocVT);
+ } else {
+ // Sanity check
+ assert(VA.isMemLoc());
+
+ // Create the nodes corresponding to a load from this parameter slot.
+ // Create the frame index object for this incoming parameter...
+ int FI = MFI->CreateFixedObject(LocVT.getSizeInBits()/8,
+ VA.getLocMemOffset(), true, false);
+
+ // Create the SelectionDAG nodes corresponding to a load
+ // from this parameter
+ SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
+ ArgValue = DAG.getLoad(LocVT, dl, Chain, FIN,
+ PseudoSourceValue::getFixedStack(FI), 0,
+ false, false, 0);
+ }
+
+ // If this is an 8/16/32-bit value, it is really passed promoted to 64
+ // bits. Insert an assert[sz]ext to capture this, then truncate to the
+ // right size.
+ if (VA.getLocInfo() == CCValAssign::SExt)
+ ArgValue = DAG.getNode(ISD::AssertSext, dl, LocVT, ArgValue,
+ DAG.getValueType(VA.getValVT()));
+ else if (VA.getLocInfo() == CCValAssign::ZExt)
+ ArgValue = DAG.getNode(ISD::AssertZext, dl, LocVT, ArgValue,
+ DAG.getValueType(VA.getValVT()));
+
+ if (VA.getLocInfo() != CCValAssign::Full)
+ ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
+
+ InVals.push_back(ArgValue);
+ }
+
+ return Chain;
+}
+
+/// LowerCCCCallTo - functions arguments are copied from virtual regs to
+/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
+/// TODO: sret.
+SDValue
+SystemZTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
+ CallingConv::ID CallConv, bool isVarArg,
+ bool isTailCall,
+ const SmallVectorImpl<ISD::OutputArg>
+ &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const {
+
+ MachineFunction &MF = DAG.getMachineFunction();
+
+ // Offset to first argument stack slot.
+ const unsigned FirstArgOffset = 160;
+
+ // Analyze operands of the call, assigning locations to each operand.
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
+ ArgLocs, *DAG.getContext());
+
+ CCInfo.AnalyzeCallOperands(Outs, CC_SystemZ);
+
+ // Get a count of how many bytes are to be pushed on the stack.
+ unsigned NumBytes = CCInfo.getNextStackOffset();
+
+ Chain = DAG.getCALLSEQ_START(Chain ,DAG.getConstant(NumBytes,
+ getPointerTy(), true));
+
+ SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
+ SmallVector<SDValue, 12> MemOpChains;
+ SDValue StackPtr;
+
+ // Walk the register/memloc assignments, inserting copies/loads.
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ CCValAssign &VA = ArgLocs[i];
+
+ SDValue Arg = Outs[i].Val;
+
+ // Promote the value if needed.
+ switch (VA.getLocInfo()) {
+ default: assert(0 && "Unknown loc info!");
+ case CCValAssign::Full: break;
+ case CCValAssign::SExt:
+ Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
+ break;
+ case CCValAssign::ZExt:
+ Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
+ break;
+ case CCValAssign::AExt:
+ Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
+ break;
+ }
+
+ // Arguments that can be passed on register must be kept at RegsToPass
+ // vector
+ if (VA.isRegLoc()) {
+ RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
+ } else {
+ assert(VA.isMemLoc());
+
+ if (StackPtr.getNode() == 0)
+ StackPtr =
+ DAG.getCopyFromReg(Chain, dl,
+ (RegInfo->hasFP(MF) ?
+ SystemZ::R11D : SystemZ::R15D),
+ getPointerTy());
+
+ unsigned Offset = FirstArgOffset + VA.getLocMemOffset();
+ SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(),
+ StackPtr,
+ DAG.getIntPtrConstant(Offset));
+
+ MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
+ PseudoSourceValue::getStack(), Offset,
+ false, false, 0));
+ }
+ }
+
+ // Transform all store nodes into one single node because all store nodes are
+ // independent of each other.
+ if (!MemOpChains.empty())
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ &MemOpChains[0], MemOpChains.size());
+
+ // Build a sequence of copy-to-reg nodes chained together with token chain and
+ // flag operands which copy the outgoing args into registers. The InFlag in
+ // necessary since all emited instructions must be stuck together.
+ SDValue InFlag;
+ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
+ Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
+ RegsToPass[i].second, InFlag);
+ InFlag = Chain.getValue(1);
+ }
+
+ // If the callee is a GlobalAddress node (quite common, every direct call is)
+ // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
+ // Likewise ExternalSymbol -> TargetExternalSymbol.
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
+ Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
+ else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
+ Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy());
+
+ // Returns a chain & a flag for retval copy to use.
+ SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
+ SmallVector<SDValue, 8> Ops;
+ Ops.push_back(Chain);
+ Ops.push_back(Callee);
+
+ // Add argument registers to the end of the list so that they are
+ // known live into the call.
+ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
+ Ops.push_back(DAG.getRegister(RegsToPass[i].first,
+ RegsToPass[i].second.getValueType()));
+
+ if (InFlag.getNode())
+ Ops.push_back(InFlag);
+
+ Chain = DAG.getNode(SystemZISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
+ InFlag = Chain.getValue(1);
+
+ // Create the CALLSEQ_END node.
+ Chain = DAG.getCALLSEQ_END(Chain,
+ DAG.getConstant(NumBytes, getPointerTy(), true),
+ DAG.getConstant(0, getPointerTy(), true),
+ InFlag);
+ InFlag = Chain.getValue(1);
+
+ // Handle result values, copying them out of physregs into vregs that we
+ // return.
+ return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl,
+ DAG, InVals);
+}
+
+/// LowerCallResult - Lower the result values of a call into the
+/// appropriate copies out of appropriate physical registers.
+///
+SDValue
+SystemZTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg>
+ &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const {
+
+ // Assign locations to each value returned by this call.
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs,
+ *DAG.getContext());
+
+ CCInfo.AnalyzeCallResult(Ins, RetCC_SystemZ);
+
+ // Copy all of the result registers out of their specified physreg.
+ for (unsigned i = 0; i != RVLocs.size(); ++i) {
+ CCValAssign &VA = RVLocs[i];
+
+ Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(),
+ VA.getLocVT(), InFlag).getValue(1);
+ SDValue RetValue = Chain.getValue(0);
+ InFlag = Chain.getValue(2);
+
+ // If this is an 8/16/32-bit value, it is really passed promoted to 64
+ // bits. Insert an assert[sz]ext to capture this, then truncate to the
+ // right size.
+ if (VA.getLocInfo() == CCValAssign::SExt)
+ RetValue = DAG.getNode(ISD::AssertSext, dl, VA.getLocVT(), RetValue,
+ DAG.getValueType(VA.getValVT()));
+ else if (VA.getLocInfo() == CCValAssign::ZExt)
+ RetValue = DAG.getNode(ISD::AssertZext, dl, VA.getLocVT(), RetValue,
+ DAG.getValueType(VA.getValVT()));
+
+ if (VA.getLocInfo() != CCValAssign::Full)
+ RetValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), RetValue);
+
+ InVals.push_back(RetValue);
+ }
+
+ return Chain;
+}
+
+
+SDValue
+SystemZTargetLowering::LowerReturn(SDValue Chain,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ DebugLoc dl, SelectionDAG &DAG) const {
+
+ // CCValAssign - represent the assignment of the return value to a location
+ SmallVector<CCValAssign, 16> RVLocs;
+
+ // CCState - Info about the registers and stack slot.
+ CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
+ RVLocs, *DAG.getContext());
+
+ // Analize return values.
+ CCInfo.AnalyzeReturn(Outs, RetCC_SystemZ);
+
+ // If this is the first return lowered for this function, add the regs to the
+ // liveout set for the function.
+ if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
+ for (unsigned i = 0; i != RVLocs.size(); ++i)
+ if (RVLocs[i].isRegLoc())
+ DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
+ }
+
+ SDValue Flag;
+
+ // Copy the result values into the output registers.
+ for (unsigned i = 0; i != RVLocs.size(); ++i) {
+ CCValAssign &VA = RVLocs[i];
+ SDValue ResValue = Outs[i].Val;
+ assert(VA.isRegLoc() && "Can only return in registers!");
+
+ // If this is an 8/16/32-bit value, it is really should be passed promoted
+ // to 64 bits.
+ if (VA.getLocInfo() == CCValAssign::SExt)
+ ResValue = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), ResValue);
+ else if (VA.getLocInfo() == CCValAssign::ZExt)
+ ResValue = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), ResValue);
+ else if (VA.getLocInfo() == CCValAssign::AExt)
+ ResValue = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), ResValue);
+
+ Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), ResValue, Flag);
+
+ // Guarantee that all emitted copies are stuck together,
+ // avoiding something bad.
+ Flag = Chain.getValue(1);
+ }
+
+ if (Flag.getNode())
+ return DAG.getNode(SystemZISD::RET_FLAG, dl, MVT::Other, Chain, Flag);
+
+ // Return Void
+ return DAG.getNode(SystemZISD::RET_FLAG, dl, MVT::Other, Chain);
+}
+
+SDValue SystemZTargetLowering::EmitCmp(SDValue LHS, SDValue RHS,
+ ISD::CondCode CC, SDValue &SystemZCC,
+ SelectionDAG &DAG) const {
+ // FIXME: Emit a test if RHS is zero
+
+ bool isUnsigned = false;
+ SystemZCC::CondCodes TCC;
+ switch (CC) {
+ default:
+ llvm_unreachable("Invalid integer condition!");
+ case ISD::SETEQ:
+ case ISD::SETOEQ:
+ TCC = SystemZCC::E;
+ break;
+ case ISD::SETUEQ:
+ TCC = SystemZCC::NLH;
+ break;
+ case ISD::SETNE:
+ case ISD::SETONE:
+ TCC = SystemZCC::NE;
+ break;
+ case ISD::SETUNE:
+ TCC = SystemZCC::LH;
+ break;
+ case ISD::SETO:
+ TCC = SystemZCC::O;
+ break;
+ case ISD::SETUO:
+ TCC = SystemZCC::NO;
+ break;
+ case ISD::SETULE:
+ if (LHS.getValueType().isFloatingPoint()) {
+ TCC = SystemZCC::NH;
+ break;
+ }
+ isUnsigned = true; // FALLTHROUGH
+ case ISD::SETLE:
+ case ISD::SETOLE:
+ TCC = SystemZCC::LE;
+ break;
+ case ISD::SETUGE:
+ if (LHS.getValueType().isFloatingPoint()) {
+ TCC = SystemZCC::NL;
+ break;
+ }
+ isUnsigned = true; // FALLTHROUGH
+ case ISD::SETGE:
+ case ISD::SETOGE:
+ TCC = SystemZCC::HE;
+ break;
+ case ISD::SETUGT:
+ if (LHS.getValueType().isFloatingPoint()) {
+ TCC = SystemZCC::NLE;
+ break;
+ }
+ isUnsigned = true; // FALLTHROUGH
+ case ISD::SETGT:
+ case ISD::SETOGT:
+ TCC = SystemZCC::H;
+ break;
+ case ISD::SETULT:
+ if (LHS.getValueType().isFloatingPoint()) {
+ TCC = SystemZCC::NHE;
+ break;
+ }
+ isUnsigned = true; // FALLTHROUGH
+ case ISD::SETLT:
+ case ISD::SETOLT:
+ TCC = SystemZCC::L;
+ break;
+ }
+
+ SystemZCC = DAG.getConstant(TCC, MVT::i32);
+
+ DebugLoc dl = LHS.getDebugLoc();
+ return DAG.getNode((isUnsigned ? SystemZISD::UCMP : SystemZISD::CMP),
+ dl, MVT::i64, LHS, RHS);
+}
+
+
+SDValue SystemZTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
+ SDValue Chain = Op.getOperand(0);
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
+ SDValue LHS = Op.getOperand(2);
+ SDValue RHS = Op.getOperand(3);
+ SDValue Dest = Op.getOperand(4);
+ DebugLoc dl = Op.getDebugLoc();
+
+ SDValue SystemZCC;
+ SDValue Flag = EmitCmp(LHS, RHS, CC, SystemZCC, DAG);
+ return DAG.getNode(SystemZISD::BRCOND, dl, Op.getValueType(),
+ Chain, Dest, SystemZCC, Flag);
+}
+
+SDValue SystemZTargetLowering::LowerSELECT_CC(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDValue LHS = Op.getOperand(0);
+ SDValue RHS = Op.getOperand(1);
+ SDValue TrueV = Op.getOperand(2);
+ SDValue FalseV = Op.getOperand(3);
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
+ DebugLoc dl = Op.getDebugLoc();
+
+ SDValue SystemZCC;
+ SDValue Flag = EmitCmp(LHS, RHS, CC, SystemZCC, DAG);
+
+ SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
+ SmallVector<SDValue, 4> Ops;
+ Ops.push_back(TrueV);
+ Ops.push_back(FalseV);
+ Ops.push_back(SystemZCC);
+ Ops.push_back(Flag);
+
+ return DAG.getNode(SystemZISD::SELECT, dl, VTs, &Ops[0], Ops.size());
+}
+
+SDValue SystemZTargetLowering::LowerGlobalAddress(SDValue Op,
+ SelectionDAG &DAG) const {
+ DebugLoc dl = Op.getDebugLoc();
+ const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
+ int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
+
+ bool IsPic = getTargetMachine().getRelocationModel() == Reloc::PIC_;
+ bool ExtraLoadRequired =
+ Subtarget.GVRequiresExtraLoad(GV, getTargetMachine(), false);
+
+ SDValue Result;
+ if (!IsPic && !ExtraLoadRequired) {
+ Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), Offset);
+ Offset = 0;
+ } else {
+ unsigned char OpFlags = 0;
+ if (ExtraLoadRequired)
+ OpFlags = SystemZII::MO_GOTENT;
+
+ Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), 0, OpFlags);
+ }
+
+ Result = DAG.getNode(SystemZISD::PCRelativeWrapper, dl,
+ getPointerTy(), Result);
+
+ if (ExtraLoadRequired)
+ Result = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Result,
+ PseudoSourceValue::getGOT(), 0, false, false, 0);
+
+ // If there was a non-zero offset that we didn't fold, create an explicit
+ // addition for it.
+ if (Offset != 0)
+ Result = DAG.getNode(ISD::ADD, dl, getPointerTy(), Result,
+ DAG.getConstant(Offset, getPointerTy()));
+
+ return Result;
+}
+
+// FIXME: PIC here
+SDValue SystemZTargetLowering::LowerJumpTable(SDValue Op,
+ SelectionDAG &DAG) const {
+ DebugLoc dl = Op.getDebugLoc();
+ JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
+ SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), getPointerTy());
+
+ return DAG.getNode(SystemZISD::PCRelativeWrapper, dl, getPointerTy(), Result);
+}
+
+
+// FIXME: PIC here
+// FIXME: This is just dirty hack. We need to lower cpool properly
+SDValue SystemZTargetLowering::LowerConstantPool(SDValue Op,
+ SelectionDAG &DAG) const {
+ DebugLoc dl = Op.getDebugLoc();
+ ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
+
+ SDValue Result = DAG.getTargetConstantPool(CP->getConstVal(), getPointerTy(),
+ CP->getAlignment(),
+ CP->getOffset());
+
+ return DAG.getNode(SystemZISD::PCRelativeWrapper, dl, getPointerTy(), Result);
+}
+
+const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {
+ switch (Opcode) {
+ case SystemZISD::RET_FLAG: return "SystemZISD::RET_FLAG";
+ case SystemZISD::CALL: return "SystemZISD::CALL";
+ case SystemZISD::BRCOND: return "SystemZISD::BRCOND";
+ case SystemZISD::CMP: return "SystemZISD::CMP";
+ case SystemZISD::UCMP: return "SystemZISD::UCMP";
+ case SystemZISD::SELECT: return "SystemZISD::SELECT";
+ case SystemZISD::PCRelativeWrapper: return "SystemZISD::PCRelativeWrapper";
+ default: return NULL;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Other Lowering Code
+//===----------------------------------------------------------------------===//
+
+MachineBasicBlock*
+SystemZTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
+ MachineBasicBlock *BB) const {
+ const SystemZInstrInfo &TII = *TM.getInstrInfo();
+ DebugLoc dl = MI->getDebugLoc();
+ assert((MI->getOpcode() == SystemZ::Select32 ||
+ MI->getOpcode() == SystemZ::SelectF32 ||
+ MI->getOpcode() == SystemZ::Select64 ||
+ MI->getOpcode() == SystemZ::SelectF64) &&
+ "Unexpected instr type to insert");
+
+ // To "insert" a SELECT instruction, we actually have to insert the diamond
+ // control-flow pattern. The incoming instruction knows the destination vreg
+ // to set, the condition code register to branch on, the true/false values to
+ // select between, and a branch opcode to use.
+ const BasicBlock *LLVM_BB = BB->getBasicBlock();
+ MachineFunction::iterator I = BB;
+ ++I;
+
+ // thisMBB:
+ // ...
+ // TrueVal = ...
+ // cmpTY ccX, r1, r2
+ // jCC copy1MBB
+ // fallthrough --> copy0MBB
+ MachineBasicBlock *thisMBB = BB;
+ MachineFunction *F = BB->getParent();
+ MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *copy1MBB = F->CreateMachineBasicBlock(LLVM_BB);
+ SystemZCC::CondCodes CC = (SystemZCC::CondCodes)MI->getOperand(3).getImm();
+ BuildMI(BB, dl, TII.getBrCond(CC)).addMBB(copy1MBB);
+ F->insert(I, copy0MBB);
+ F->insert(I, copy1MBB);
+ // Update machine-CFG edges by transferring all successors of the current
+ // block to the new block which will contain the Phi node for the select.
+ copy1MBB->transferSuccessors(BB);
+ // Next, add the true and fallthrough blocks as its successors.
+ BB->addSuccessor(copy0MBB);
+ BB->addSuccessor(copy1MBB);
+
+ // copy0MBB:
+ // %FalseValue = ...
+ // # fallthrough to copy1MBB
+ BB = copy0MBB;
+
+ // Update machine-CFG edges
+ BB->addSuccessor(copy1MBB);
+
+ // copy1MBB:
+ // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
+ // ...
+ BB = copy1MBB;
+ BuildMI(BB, dl, TII.get(SystemZ::PHI),
+ MI->getOperand(0).getReg())
+ .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB)
+ .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB);
+
+ F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
+ return BB;
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h
new file mode 100644
index 0000000..94bd906
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -0,0 +1,145 @@
+//==-- SystemZISelLowering.h - SystemZ DAG Lowering Interface ----*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that SystemZ uses to lower LLVM code into a
+// selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_SystemZ_ISELLOWERING_H
+#define LLVM_TARGET_SystemZ_ISELLOWERING_H
+
+#include "SystemZ.h"
+#include "SystemZRegisterInfo.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/Target/TargetLowering.h"
+
+namespace llvm {
+ namespace SystemZISD {
+ enum {
+ FIRST_NUMBER = ISD::BUILTIN_OP_END,
+
+ /// Return with a flag operand. Operand 0 is the chain operand.
+ RET_FLAG,
+
+ /// CALL - These operations represent an abstract call
+ /// instruction, which includes a bunch of information.
+ CALL,
+
+ /// PCRelativeWrapper - PC relative address
+ PCRelativeWrapper,
+
+ /// CMP, UCMP - Compare instruction
+ CMP,
+ UCMP,
+
+ /// BRCOND - Conditional branch. Operand 0 is chain operand, operand 1 is
+ /// the block to branch if condition is true, operand 2 is condition code
+ /// and operand 3 is the flag operand produced by a CMP instruction.
+ BRCOND,
+
+ /// SELECT - Operands 0 and 1 are selection variables, operand 2 is
+ /// condition code and operand 3 is the flag operand.
+ SELECT
+ };
+ }
+
+ class SystemZSubtarget;
+ class SystemZTargetMachine;
+
+ class SystemZTargetLowering : public TargetLowering {
+ public:
+ explicit SystemZTargetLowering(SystemZTargetMachine &TM);
+
+ /// LowerOperation - Provide custom lowering hooks for some operations.
+ virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
+
+ /// getTargetNodeName - This method returns the name of a target specific
+ /// DAG node.
+ virtual const char *getTargetNodeName(unsigned Opcode) const;
+
+ /// getFunctionAlignment - Return the Log2 alignment of this function.
+ virtual unsigned getFunctionAlignment(const Function *F) const {
+ return 1;
+ }
+
+ std::pair<unsigned, const TargetRegisterClass*>
+ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const;
+ TargetLowering::ConstraintType
+ getConstraintType(const std::string &Constraint) const;
+
+ SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
+
+ SDValue EmitCmp(SDValue LHS, SDValue RHS,
+ ISD::CondCode CC, SDValue &SystemZCC,
+ SelectionDAG &DAG) const;
+
+
+ MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI,
+ MachineBasicBlock *BB) const;
+
+ /// isFPImmLegal - Returns true if the target can instruction select the
+ /// specified FP immediate natively. If false, the legalizer will
+ /// materialize the FP immediate as a load from a constant pool.
+ virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const;
+
+ private:
+ SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
+ CallingConv::ID CallConv, bool isVarArg,
+ bool isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const;
+
+ SDValue LowerCCCArguments(SDValue Chain,
+ CallingConv::ID CallConv,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl,
+ SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const;
+
+ SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const;
+
+ virtual SDValue
+ LowerFormalArguments(SDValue Chain,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const;
+ virtual SDValue
+ LowerCall(SDValue Chain, SDValue Callee,
+ CallingConv::ID CallConv, bool isVarArg, bool &isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const;
+
+ virtual SDValue
+ LowerReturn(SDValue Chain,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ DebugLoc dl, SelectionDAG &DAG) const;
+
+ const SystemZSubtarget &Subtarget;
+ const SystemZTargetMachine &TM;
+ const SystemZRegisterInfo *RegInfo;
+ };
+} // namespace llvm
+
+#endif // LLVM_TARGET_SystemZ_ISELLOWERING_H
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZInstrBuilder.h b/contrib/llvm/lib/Target/SystemZ/SystemZInstrBuilder.h
new file mode 100644
index 0000000..fa87061
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZInstrBuilder.h
@@ -0,0 +1,128 @@
+//===- SystemZInstrBuilder.h - Functions to aid building insts -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file exposes functions that may be used with BuildMI from the
+// MachineInstrBuilder.h file to handle SystemZ'isms in a clean way.
+//
+// The BuildMem function may be used with the BuildMI function to add entire
+// memory references in a single, typed, function call.
+//
+// For reference, the order of operands for memory references is:
+// (Operand), Base, Displacement, Index.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SYSTEMZINSTRBUILDER_H
+#define SYSTEMZINSTRBUILDER_H
+
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineMemOperand.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
+
+namespace llvm {
+
+/// SystemZAddressMode - This struct holds a generalized full x86 address mode.
+/// The base register can be a frame index, which will eventually be replaced
+/// with R15 or R11 and Disp being offsetted accordingly.
+struct SystemZAddressMode {
+ enum {
+ RegBase,
+ FrameIndexBase
+ } BaseType;
+
+ union {
+ unsigned Reg;
+ int FrameIndex;
+ } Base;
+
+ unsigned IndexReg;
+ int32_t Disp;
+ const GlobalValue *GV;
+
+ SystemZAddressMode() : BaseType(RegBase), IndexReg(0), Disp(0) {
+ Base.Reg = 0;
+ }
+};
+
+/// addDirectMem - This function is used to add a direct memory reference to the
+/// current instruction -- that is, a dereference of an address in a register,
+/// with no index or displacement.
+///
+static inline const MachineInstrBuilder &
+addDirectMem(const MachineInstrBuilder &MIB, unsigned Reg) {
+ // Because memory references are always represented with 3
+ // values, this adds: Reg, [0, NoReg] to the instruction.
+ return MIB.addReg(Reg).addImm(0).addReg(0);
+}
+
+static inline const MachineInstrBuilder &
+addOffset(const MachineInstrBuilder &MIB, int Offset) {
+ return MIB.addImm(Offset).addReg(0);
+}
+
+/// addRegOffset - This function is used to add a memory reference of the form
+/// [Reg + Offset], i.e., one with no or index, but with a
+/// displacement. An example is: 10(%r15).
+///
+static inline const MachineInstrBuilder &
+addRegOffset(const MachineInstrBuilder &MIB,
+ unsigned Reg, bool isKill, int Offset) {
+ return addOffset(MIB.addReg(Reg, getKillRegState(isKill)), Offset);
+}
+
+/// addRegReg - This function is used to add a memory reference of the form:
+/// [Reg + Reg].
+static inline const MachineInstrBuilder &
+addRegReg(const MachineInstrBuilder &MIB,
+ unsigned Reg1, bool isKill1, unsigned Reg2, bool isKill2) {
+ return MIB.addReg(Reg1, getKillRegState(isKill1)).addImm(0)
+ .addReg(Reg2, getKillRegState(isKill2));
+}
+
+static inline const MachineInstrBuilder &
+addFullAddress(const MachineInstrBuilder &MIB, const SystemZAddressMode &AM) {
+ if (AM.BaseType == SystemZAddressMode::RegBase)
+ MIB.addReg(AM.Base.Reg);
+ else if (AM.BaseType == SystemZAddressMode::FrameIndexBase)
+ MIB.addFrameIndex(AM.Base.FrameIndex);
+ else
+ assert(0);
+
+ return MIB.addImm(AM.Disp).addReg(AM.IndexReg);
+}
+
+/// addFrameReference - This function is used to add a reference to the base of
+/// an abstract object on the stack frame of the current function. This
+/// reference has base register as the FrameIndex offset until it is resolved.
+/// This allows a constant offset to be specified as well...
+///
+static inline const MachineInstrBuilder &
+addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) {
+ MachineInstr *MI = MIB;
+ MachineFunction &MF = *MI->getParent()->getParent();
+ MachineFrameInfo &MFI = *MF.getFrameInfo();
+ const TargetInstrDesc &TID = MI->getDesc();
+ unsigned Flags = 0;
+ if (TID.mayLoad())
+ Flags |= MachineMemOperand::MOLoad;
+ if (TID.mayStore())
+ Flags |= MachineMemOperand::MOStore;
+ MachineMemOperand *MMO =
+ MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
+ Flags, Offset,
+ MFI.getObjectSize(FI),
+ MFI.getObjectAlignment(FI));
+ return addOffset(MIB.addFrameIndex(FI), Offset)
+ .addMemOperand(MMO);
+}
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZInstrFP.td b/contrib/llvm/lib/Target/SystemZ/SystemZInstrFP.td
new file mode 100644
index 0000000..8c5e905
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZInstrFP.td
@@ -0,0 +1,340 @@
+//===- SystemZInstrFP.td - SystemZ FP Instruction defs --------*- tblgen-*-===//
+//
+// 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 SystemZ (binary) floating point instructions in
+// TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: multiclassify!
+
+//===----------------------------------------------------------------------===//
+// FP Pattern fragments
+
+def fpimm0 : PatLeaf<(fpimm), [{
+ return N->isExactlyValue(+0.0);
+}]>;
+
+def fpimmneg0 : PatLeaf<(fpimm), [{
+ return N->isExactlyValue(-0.0);
+}]>;
+
+let Uses = [PSW], usesCustomInserter = 1 in {
+ def SelectF32 : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2, i8imm:$cc),
+ "# SelectF32 PSEUDO",
+ [(set FP32:$dst,
+ (SystemZselect FP32:$src1, FP32:$src2, imm:$cc, PSW))]>;
+ def SelectF64 : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2, i8imm:$cc),
+ "# SelectF64 PSEUDO",
+ [(set FP64:$dst,
+ (SystemZselect FP64:$src1, FP64:$src2, imm:$cc, PSW))]>;
+}
+
+//===----------------------------------------------------------------------===//
+// Move Instructions
+
+// Floating point constant loads.
+let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
+def LD_Fp032 : Pseudo<(outs FP32:$dst), (ins),
+ "lzer\t{$dst}",
+ [(set FP32:$dst, fpimm0)]>;
+def LD_Fp064 : Pseudo<(outs FP64:$dst), (ins),
+ "lzdr\t{$dst}",
+ [(set FP64:$dst, fpimm0)]>;
+}
+
+let neverHasSideEffects = 1 in {
+def FMOV32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
+ "ler\t{$dst, $src}",
+ []>;
+def FMOV64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
+ "ldr\t{$dst, $src}",
+ []>;
+}
+
+let canFoldAsLoad = 1, isReMaterializable = 1 in {
+def FMOV32rm : Pseudo<(outs FP32:$dst), (ins rriaddr12:$src),
+ "le\t{$dst, $src}",
+ [(set FP32:$dst, (load rriaddr12:$src))]>;
+def FMOV32rmy : Pseudo<(outs FP32:$dst), (ins rriaddr:$src),
+ "ley\t{$dst, $src}",
+ [(set FP32:$dst, (load rriaddr:$src))]>;
+def FMOV64rm : Pseudo<(outs FP64:$dst), (ins rriaddr12:$src),
+ "ld\t{$dst, $src}",
+ [(set FP64:$dst, (load rriaddr12:$src))]>;
+def FMOV64rmy : Pseudo<(outs FP64:$dst), (ins rriaddr:$src),
+ "ldy\t{$dst, $src}",
+ [(set FP64:$dst, (load rriaddr:$src))]>;
+}
+
+def FMOV32mr : Pseudo<(outs), (ins rriaddr12:$dst, FP32:$src),
+ "ste\t{$src, $dst}",
+ [(store FP32:$src, rriaddr12:$dst)]>;
+def FMOV32mry : Pseudo<(outs), (ins rriaddr:$dst, FP32:$src),
+ "stey\t{$src, $dst}",
+ [(store FP32:$src, rriaddr:$dst)]>;
+def FMOV64mr : Pseudo<(outs), (ins rriaddr12:$dst, FP64:$src),
+ "std\t{$src, $dst}",
+ [(store FP64:$src, rriaddr12:$dst)]>;
+def FMOV64mry : Pseudo<(outs), (ins rriaddr:$dst, FP64:$src),
+ "stdy\t{$src, $dst}",
+ [(store FP64:$src, rriaddr:$dst)]>;
+
+def FCOPYSIGN32 : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
+ "cpsdr\t{$dst, $src2, $src1}",
+ [(set FP32:$dst, (fcopysign FP32:$src1, FP32:$src2))]>;
+def FCOPYSIGN64 : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
+ "cpsdr\t{$dst, $src2, $src1}",
+ [(set FP64:$dst, (fcopysign FP64:$src1, FP64:$src2))]>;
+
+//===----------------------------------------------------------------------===//
+// Arithmetic Instructions
+
+
+let Defs = [PSW] in {
+def FNEG32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
+ "lcebr\t{$dst, $src}",
+ [(set FP32:$dst, (fneg FP32:$src)),
+ (implicit PSW)]>;
+def FNEG64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
+ "lcdbr\t{$dst, $src}",
+ [(set FP64:$dst, (fneg FP64:$src)),
+ (implicit PSW)]>;
+
+def FABS32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
+ "lpebr\t{$dst, $src}",
+ [(set FP32:$dst, (fabs FP32:$src)),
+ (implicit PSW)]>;
+def FABS64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
+ "lpdbr\t{$dst, $src}",
+ [(set FP64:$dst, (fabs FP64:$src)),
+ (implicit PSW)]>;
+
+def FNABS32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
+ "lnebr\t{$dst, $src}",
+ [(set FP32:$dst, (fneg(fabs FP32:$src))),
+ (implicit PSW)]>;
+def FNABS64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
+ "lndbr\t{$dst, $src}",
+ [(set FP64:$dst, (fneg(fabs FP64:$src))),
+ (implicit PSW)]>;
+}
+
+let isTwoAddress = 1 in {
+let Defs = [PSW] in {
+let isCommutable = 1 in { // X = ADD Y, Z == X = ADD Z, Y
+def FADD32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
+ "aebr\t{$dst, $src2}",
+ [(set FP32:$dst, (fadd FP32:$src1, FP32:$src2)),
+ (implicit PSW)]>;
+def FADD64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
+ "adbr\t{$dst, $src2}",
+ [(set FP64:$dst, (fadd FP64:$src1, FP64:$src2)),
+ (implicit PSW)]>;
+}
+
+def FADD32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
+ "aeb\t{$dst, $src2}",
+ [(set FP32:$dst, (fadd FP32:$src1, (load rriaddr12:$src2))),
+ (implicit PSW)]>;
+def FADD64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
+ "adb\t{$dst, $src2}",
+ [(set FP64:$dst, (fadd FP64:$src1, (load rriaddr12:$src2))),
+ (implicit PSW)]>;
+
+def FSUB32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
+ "sebr\t{$dst, $src2}",
+ [(set FP32:$dst, (fsub FP32:$src1, FP32:$src2)),
+ (implicit PSW)]>;
+def FSUB64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
+ "sdbr\t{$dst, $src2}",
+ [(set FP64:$dst, (fsub FP64:$src1, FP64:$src2)),
+ (implicit PSW)]>;
+
+def FSUB32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
+ "seb\t{$dst, $src2}",
+ [(set FP32:$dst, (fsub FP32:$src1, (load rriaddr12:$src2))),
+ (implicit PSW)]>;
+def FSUB64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
+ "sdb\t{$dst, $src2}",
+ [(set FP64:$dst, (fsub FP64:$src1, (load rriaddr12:$src2))),
+ (implicit PSW)]>;
+} // Defs = [PSW]
+
+let isCommutable = 1 in { // X = MUL Y, Z == X = MUL Z, Y
+def FMUL32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
+ "meebr\t{$dst, $src2}",
+ [(set FP32:$dst, (fmul FP32:$src1, FP32:$src2))]>;
+def FMUL64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
+ "mdbr\t{$dst, $src2}",
+ [(set FP64:$dst, (fmul FP64:$src1, FP64:$src2))]>;
+}
+
+def FMUL32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
+ "meeb\t{$dst, $src2}",
+ [(set FP32:$dst, (fmul FP32:$src1, (load rriaddr12:$src2)))]>;
+def FMUL64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
+ "mdb\t{$dst, $src2}",
+ [(set FP64:$dst, (fmul FP64:$src1, (load rriaddr12:$src2)))]>;
+
+def FMADD32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2, FP32:$src3),
+ "maebr\t{$dst, $src3, $src2}",
+ [(set FP32:$dst, (fadd (fmul FP32:$src2, FP32:$src3),
+ FP32:$src1))]>;
+def FMADD32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2, FP32:$src3),
+ "maeb\t{$dst, $src3, $src2}",
+ [(set FP32:$dst, (fadd (fmul (load rriaddr12:$src2),
+ FP32:$src3),
+ FP32:$src1))]>;
+
+def FMADD64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2, FP64:$src3),
+ "madbr\t{$dst, $src3, $src2}",
+ [(set FP64:$dst, (fadd (fmul FP64:$src2, FP64:$src3),
+ FP64:$src1))]>;
+def FMADD64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2, FP64:$src3),
+ "madb\t{$dst, $src3, $src2}",
+ [(set FP64:$dst, (fadd (fmul (load rriaddr12:$src2),
+ FP64:$src3),
+ FP64:$src1))]>;
+
+def FMSUB32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2, FP32:$src3),
+ "msebr\t{$dst, $src3, $src2}",
+ [(set FP32:$dst, (fsub (fmul FP32:$src2, FP32:$src3),
+ FP32:$src1))]>;
+def FMSUB32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2, FP32:$src3),
+ "mseb\t{$dst, $src3, $src2}",
+ [(set FP32:$dst, (fsub (fmul (load rriaddr12:$src2),
+ FP32:$src3),
+ FP32:$src1))]>;
+
+def FMSUB64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2, FP64:$src3),
+ "msdbr\t{$dst, $src3, $src2}",
+ [(set FP64:$dst, (fsub (fmul FP64:$src2, FP64:$src3),
+ FP64:$src1))]>;
+def FMSUB64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2, FP64:$src3),
+ "msdb\t{$dst, $src3, $src2}",
+ [(set FP64:$dst, (fsub (fmul (load rriaddr12:$src2),
+ FP64:$src3),
+ FP64:$src1))]>;
+
+def FDIV32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
+ "debr\t{$dst, $src2}",
+ [(set FP32:$dst, (fdiv FP32:$src1, FP32:$src2))]>;
+def FDIV64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
+ "ddbr\t{$dst, $src2}",
+ [(set FP64:$dst, (fdiv FP64:$src1, FP64:$src2))]>;
+
+def FDIV32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
+ "deb\t{$dst, $src2}",
+ [(set FP32:$dst, (fdiv FP32:$src1, (load rriaddr12:$src2)))]>;
+def FDIV64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
+ "ddb\t{$dst, $src2}",
+ [(set FP64:$dst, (fdiv FP64:$src1, (load rriaddr12:$src2)))]>;
+
+} // isTwoAddress = 1
+
+def FSQRT32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
+ "sqebr\t{$dst, $src}",
+ [(set FP32:$dst, (fsqrt FP32:$src))]>;
+def FSQRT64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
+ "sqdbr\t{$dst, $src}",
+ [(set FP64:$dst, (fsqrt FP64:$src))]>;
+
+def FSQRT32rm : Pseudo<(outs FP32:$dst), (ins rriaddr12:$src),
+ "sqeb\t{$dst, $src}",
+ [(set FP32:$dst, (fsqrt (load rriaddr12:$src)))]>;
+def FSQRT64rm : Pseudo<(outs FP64:$dst), (ins rriaddr12:$src),
+ "sqdb\t{$dst, $src}",
+ [(set FP64:$dst, (fsqrt (load rriaddr12:$src)))]>;
+
+def FROUND64r32 : Pseudo<(outs FP32:$dst), (ins FP64:$src),
+ "ledbr\t{$dst, $src}",
+ [(set FP32:$dst, (fround FP64:$src))]>;
+
+def FEXT32r64 : Pseudo<(outs FP64:$dst), (ins FP32:$src),
+ "ldebr\t{$dst, $src}",
+ [(set FP64:$dst, (fextend FP32:$src))]>;
+def FEXT32m64 : Pseudo<(outs FP64:$dst), (ins rriaddr12:$src),
+ "ldeb\t{$dst, $src}",
+ [(set FP64:$dst, (fextend (load rriaddr12:$src)))]>;
+
+let Defs = [PSW] in {
+def FCONVFP32 : Pseudo<(outs FP32:$dst), (ins GR32:$src),
+ "cefbr\t{$dst, $src}",
+ [(set FP32:$dst, (sint_to_fp GR32:$src)),
+ (implicit PSW)]>;
+def FCONVFP32r64: Pseudo<(outs FP32:$dst), (ins GR64:$src),
+ "cegbr\t{$dst, $src}",
+ [(set FP32:$dst, (sint_to_fp GR64:$src)),
+ (implicit PSW)]>;
+
+def FCONVFP64r32: Pseudo<(outs FP64:$dst), (ins GR32:$src),
+ "cdfbr\t{$dst, $src}",
+ [(set FP64:$dst, (sint_to_fp GR32:$src)),
+ (implicit PSW)]>;
+def FCONVFP64 : Pseudo<(outs FP64:$dst), (ins GR64:$src),
+ "cdgbr\t{$dst, $src}",
+ [(set FP64:$dst, (sint_to_fp GR64:$src)),
+ (implicit PSW)]>;
+
+def FCONVGR32 : Pseudo<(outs GR32:$dst), (ins FP32:$src),
+ "cfebr\t{$dst, 5, $src}",
+ [(set GR32:$dst, (fp_to_sint FP32:$src)),
+ (implicit PSW)]>;
+def FCONVGR32r64: Pseudo<(outs GR32:$dst), (ins FP64:$src),
+ "cfdbr\t{$dst, 5, $src}",
+ [(set GR32:$dst, (fp_to_sint FP64:$src)),
+ (implicit PSW)]>;
+
+def FCONVGR64r32: Pseudo<(outs GR64:$dst), (ins FP32:$src),
+ "cgebr\t{$dst, 5, $src}",
+ [(set GR64:$dst, (fp_to_sint FP32:$src)),
+ (implicit PSW)]>;
+def FCONVGR64 : Pseudo<(outs GR64:$dst), (ins FP64:$src),
+ "cgdbr\t{$dst, 5, $src}",
+ [(set GR64:$dst, (fp_to_sint FP64:$src)),
+ (implicit PSW)]>;
+} // Defs = [PSW]
+
+def FBCONVG64 : Pseudo<(outs GR64:$dst), (ins FP64:$src),
+ "lgdr\t{$dst, $src}",
+ [(set GR64:$dst, (bitconvert FP64:$src))]>;
+def FBCONVF64 : Pseudo<(outs FP64:$dst), (ins GR64:$src),
+ "ldgr\t{$dst, $src}",
+ [(set FP64:$dst, (bitconvert GR64:$src))]>;
+
+//===----------------------------------------------------------------------===//
+// Test instructions (like AND but do not produce any result)
+
+// Integer comparisons
+let Defs = [PSW] in {
+def FCMP32rr : Pseudo<(outs), (ins FP32:$src1, FP32:$src2),
+ "cebr\t$src1, $src2",
+ [(set PSW, (SystemZcmp FP32:$src1, FP32:$src2))]>;
+def FCMP64rr : Pseudo<(outs), (ins FP64:$src1, FP64:$src2),
+ "cdbr\t$src1, $src2",
+ [(set PSW, (SystemZcmp FP64:$src1, FP64:$src2))]>;
+
+def FCMP32rm : Pseudo<(outs), (ins FP32:$src1, rriaddr12:$src2),
+ "ceb\t$src1, $src2",
+ [(set PSW, (SystemZcmp FP32:$src1,
+ (load rriaddr12:$src2)))]>;
+def FCMP64rm : Pseudo<(outs), (ins FP64:$src1, rriaddr12:$src2),
+ "cdb\t$src1, $src2",
+ [(set PSW, (SystemZcmp FP64:$src1,
+ (load rriaddr12:$src2)))]>;
+} // Defs = [PSW]
+
+//===----------------------------------------------------------------------===//
+// Non-Instruction Patterns
+//===----------------------------------------------------------------------===//
+
+// Floating point constant -0.0
+def : Pat<(f32 fpimmneg0), (FNEG32rr (LD_Fp032))>;
+def : Pat<(f64 fpimmneg0), (FNEG64rr (LD_Fp064))>;
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZInstrFormats.td b/contrib/llvm/lib/Target/SystemZ/SystemZInstrFormats.td
new file mode 100644
index 0000000..b4a8993
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZInstrFormats.td
@@ -0,0 +1,133 @@
+//===- SystemZInstrFormats.td - SystemZ Instruction Formats ----*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Format specifies the encoding used by the instruction. This is part of the
+// ad-hoc solution used to emit machine instruction encodings by our machine
+// code emitter.
+class Format<bits<5> val> {
+ bits<5> Value = val;
+}
+
+def Pseudo : Format<0>;
+def EForm : Format<1>;
+def IForm : Format<2>;
+def RIForm : Format<3>;
+def RIEForm : Format<4>;
+def RILForm : Format<5>;
+def RISForm : Format<6>;
+def RRForm : Format<7>;
+def RREForm : Format<8>;
+def RRFForm : Format<9>;
+def RRRForm : Format<10>;
+def RRSForm : Format<11>;
+def RSForm : Format<12>;
+def RSIForm : Format<13>;
+def RSILForm : Format<14>;
+def RSYForm : Format<15>;
+def RXForm : Format<16>;
+def RXEForm : Format<17>;
+def RXFForm : Format<18>;
+def RXYForm : Format<19>;
+def SForm : Format<20>;
+def SIForm : Format<21>;
+def SILForm : Format<22>;
+def SIYForm : Format<23>;
+def SSForm : Format<24>;
+def SSEForm : Format<25>;
+def SSFForm : Format<26>;
+
+class InstSystemZ<bits<16> op, Format f, dag outs, dag ins> : Instruction {
+ let Namespace = "SystemZ";
+
+ bits<16> Opcode = op;
+
+ Format Form = f;
+ bits<5> FormBits = Form.Value;
+
+ dag OutOperandList = outs;
+ dag InOperandList = ins;
+}
+
+class I8<bits<8> op, Format f, dag outs, dag ins, string asmstr,
+ list<dag> pattern>
+ : InstSystemZ<0, f, outs, ins> {
+ let Opcode{0-7} = op;
+ let Opcode{8-15} = 0;
+
+ let Pattern = pattern;
+ let AsmString = asmstr;
+}
+
+class I12<bits<12> op, Format f, dag outs, dag ins, string asmstr,
+ list<dag> pattern>
+ : InstSystemZ<0, f, outs, ins> {
+ let Opcode{0-11} = op;
+ let Opcode{12-15} = 0;
+
+ let Pattern = pattern;
+ let AsmString = asmstr;
+}
+
+class I16<bits<16> op, Format f, dag outs, dag ins, string asmstr,
+ list<dag> pattern>
+ : InstSystemZ<op, f, outs, ins> {
+ let Pattern = pattern;
+ let AsmString = asmstr;
+}
+
+class RRI<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I8<op, RRForm, outs, ins, asmstr, pattern>;
+
+class RII<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I12<op, RIForm, outs, ins, asmstr, pattern>;
+
+class RILI<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I12<op, RILForm, outs, ins, asmstr, pattern>;
+
+class RREI<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I16<op, RREForm, outs, ins, asmstr, pattern>;
+
+class RXI<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I8<op, RXForm, outs, ins, asmstr, pattern> {
+ let AddedComplexity = 1;
+}
+
+class RXYI<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I16<op, RXYForm, outs, ins, asmstr, pattern>;
+
+class RSI<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I8<op, RSForm, outs, ins, asmstr, pattern> {
+ let AddedComplexity = 1;
+}
+
+class RSYI<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I16<op, RSYForm, outs, ins, asmstr, pattern>;
+
+class SII<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I8<op, SIForm, outs, ins, asmstr, pattern> {
+ let AddedComplexity = 1;
+}
+
+class SIYI<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I16<op, SIYForm, outs, ins, asmstr, pattern>;
+
+class SILI<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : I16<op, SILForm, outs, ins, asmstr, pattern>;
+
+
+//===----------------------------------------------------------------------===//
+// Pseudo instructions
+//===----------------------------------------------------------------------===//
+
+class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : InstSystemZ<0, Pseudo, outs, ins> {
+
+ let Pattern = pattern;
+ let AsmString = asmstr;
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
new file mode 100644
index 0000000..043686c
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
@@ -0,0 +1,644 @@
+//===- SystemZInstrInfo.cpp - SystemZ Instruction Information --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SystemZ implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZ.h"
+#include "SystemZInstrBuilder.h"
+#include "SystemZInstrInfo.h"
+#include "SystemZMachineFunctionInfo.h"
+#include "SystemZTargetMachine.h"
+#include "SystemZGenInstrInfo.inc"
+#include "llvm/Function.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace llvm;
+
+SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm)
+ : TargetInstrInfoImpl(SystemZInsts, array_lengthof(SystemZInsts)),
+ RI(tm, *this), TM(tm) {
+ // Fill the spill offsets map
+ static const unsigned SpillOffsTab[][2] = {
+ { SystemZ::R2D, 0x10 },
+ { SystemZ::R3D, 0x18 },
+ { SystemZ::R4D, 0x20 },
+ { SystemZ::R5D, 0x28 },
+ { SystemZ::R6D, 0x30 },
+ { SystemZ::R7D, 0x38 },
+ { SystemZ::R8D, 0x40 },
+ { SystemZ::R9D, 0x48 },
+ { SystemZ::R10D, 0x50 },
+ { SystemZ::R11D, 0x58 },
+ { SystemZ::R12D, 0x60 },
+ { SystemZ::R13D, 0x68 },
+ { SystemZ::R14D, 0x70 },
+ { SystemZ::R15D, 0x78 }
+ };
+
+ RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
+
+ for (unsigned i = 0, e = array_lengthof(SpillOffsTab); i != e; ++i)
+ RegSpillOffsets[SpillOffsTab[i][0]] = SpillOffsTab[i][1];
+}
+
+/// isGVStub - Return true if the GV requires an extra load to get the
+/// real address.
+static inline bool isGVStub(GlobalValue *GV, SystemZTargetMachine &TM) {
+ return TM.getSubtarget<SystemZSubtarget>().GVRequiresExtraLoad(GV, TM, false);
+}
+
+void SystemZInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned SrcReg, bool isKill, int FrameIdx,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const {
+ DebugLoc DL;
+ if (MI != MBB.end()) DL = MI->getDebugLoc();
+
+ unsigned Opc = 0;
+ if (RC == &SystemZ::GR32RegClass ||
+ RC == &SystemZ::ADDR32RegClass)
+ Opc = SystemZ::MOV32mr;
+ else if (RC == &SystemZ::GR64RegClass ||
+ RC == &SystemZ::ADDR64RegClass) {
+ Opc = SystemZ::MOV64mr;
+ } else if (RC == &SystemZ::FP32RegClass) {
+ Opc = SystemZ::FMOV32mr;
+ } else if (RC == &SystemZ::FP64RegClass) {
+ Opc = SystemZ::FMOV64mr;
+ } else if (RC == &SystemZ::GR64PRegClass) {
+ Opc = SystemZ::MOV64Pmr;
+ } else if (RC == &SystemZ::GR128RegClass) {
+ Opc = SystemZ::MOV128mr;
+ } else
+ llvm_unreachable("Unsupported regclass to store");
+
+ addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIdx)
+ .addReg(SrcReg, getKillRegState(isKill));
+}
+
+void SystemZInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned DestReg, int FrameIdx,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const{
+ DebugLoc DL;
+ if (MI != MBB.end()) DL = MI->getDebugLoc();
+
+ unsigned Opc = 0;
+ if (RC == &SystemZ::GR32RegClass ||
+ RC == &SystemZ::ADDR32RegClass)
+ Opc = SystemZ::MOV32rm;
+ else if (RC == &SystemZ::GR64RegClass ||
+ RC == &SystemZ::ADDR64RegClass) {
+ Opc = SystemZ::MOV64rm;
+ } else if (RC == &SystemZ::FP32RegClass) {
+ Opc = SystemZ::FMOV32rm;
+ } else if (RC == &SystemZ::FP64RegClass) {
+ Opc = SystemZ::FMOV64rm;
+ } else if (RC == &SystemZ::GR64PRegClass) {
+ Opc = SystemZ::MOV64Prm;
+ } else if (RC == &SystemZ::GR128RegClass) {
+ Opc = SystemZ::MOV128rm;
+ } else
+ llvm_unreachable("Unsupported regclass to load");
+
+ addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DestReg), FrameIdx);
+}
+
+bool SystemZInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned DestReg, unsigned SrcReg,
+ const TargetRegisterClass *DestRC,
+ const TargetRegisterClass *SrcRC,
+ DebugLoc DL) const {
+
+ // Determine if DstRC and SrcRC have a common superclass.
+ const TargetRegisterClass *CommonRC = DestRC;
+ if (DestRC == SrcRC)
+ /* Same regclass for source and dest */;
+ else if (CommonRC->hasSuperClass(SrcRC))
+ CommonRC = SrcRC;
+ else if (!CommonRC->hasSubClass(SrcRC))
+ CommonRC = 0;
+
+ if (CommonRC) {
+ if (CommonRC == &SystemZ::GR64RegClass ||
+ CommonRC == &SystemZ::ADDR64RegClass) {
+ BuildMI(MBB, I, DL, get(SystemZ::MOV64rr), DestReg).addReg(SrcReg);
+ } else if (CommonRC == &SystemZ::GR32RegClass ||
+ CommonRC == &SystemZ::ADDR32RegClass) {
+ BuildMI(MBB, I, DL, get(SystemZ::MOV32rr), DestReg).addReg(SrcReg);
+ } else if (CommonRC == &SystemZ::GR64PRegClass) {
+ BuildMI(MBB, I, DL, get(SystemZ::MOV64rrP), DestReg).addReg(SrcReg);
+ } else if (CommonRC == &SystemZ::GR128RegClass) {
+ BuildMI(MBB, I, DL, get(SystemZ::MOV128rr), DestReg).addReg(SrcReg);
+ } else if (CommonRC == &SystemZ::FP32RegClass) {
+ BuildMI(MBB, I, DL, get(SystemZ::FMOV32rr), DestReg).addReg(SrcReg);
+ } else if (CommonRC == &SystemZ::FP64RegClass) {
+ BuildMI(MBB, I, DL, get(SystemZ::FMOV64rr), DestReg).addReg(SrcReg);
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ if ((SrcRC == &SystemZ::GR64RegClass &&
+ DestRC == &SystemZ::ADDR64RegClass) ||
+ (DestRC == &SystemZ::GR64RegClass &&
+ SrcRC == &SystemZ::ADDR64RegClass)) {
+ BuildMI(MBB, I, DL, get(SystemZ::MOV64rr), DestReg).addReg(SrcReg);
+ return true;
+ } else if ((SrcRC == &SystemZ::GR32RegClass &&
+ DestRC == &SystemZ::ADDR32RegClass) ||
+ (DestRC == &SystemZ::GR32RegClass &&
+ SrcRC == &SystemZ::ADDR32RegClass)) {
+ BuildMI(MBB, I, DL, get(SystemZ::MOV32rr), DestReg).addReg(SrcReg);
+ return true;
+ }
+
+ return false;
+}
+
+bool
+SystemZInstrInfo::isMoveInstr(const MachineInstr& MI,
+ unsigned &SrcReg, unsigned &DstReg,
+ unsigned &SrcSubIdx, unsigned &DstSubIdx) const {
+ switch (MI.getOpcode()) {
+ default:
+ return false;
+ case SystemZ::MOV32rr:
+ case SystemZ::MOV64rr:
+ case SystemZ::MOV64rrP:
+ case SystemZ::MOV128rr:
+ case SystemZ::FMOV32rr:
+ case SystemZ::FMOV64rr:
+ assert(MI.getNumOperands() >= 2 &&
+ MI.getOperand(0).isReg() &&
+ MI.getOperand(1).isReg() &&
+ "invalid register-register move instruction");
+ SrcReg = MI.getOperand(1).getReg();
+ DstReg = MI.getOperand(0).getReg();
+ SrcSubIdx = MI.getOperand(1).getSubReg();
+ DstSubIdx = MI.getOperand(0).getSubReg();
+ return true;
+ }
+}
+
+unsigned SystemZInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const {
+ switch (MI->getOpcode()) {
+ default: break;
+ case SystemZ::MOV32rm:
+ case SystemZ::MOV32rmy:
+ case SystemZ::MOV64rm:
+ case SystemZ::MOVSX32rm8:
+ case SystemZ::MOVSX32rm16y:
+ case SystemZ::MOVSX64rm8:
+ case SystemZ::MOVSX64rm16:
+ case SystemZ::MOVSX64rm32:
+ case SystemZ::MOVZX32rm8:
+ case SystemZ::MOVZX32rm16:
+ case SystemZ::MOVZX64rm8:
+ case SystemZ::MOVZX64rm16:
+ case SystemZ::MOVZX64rm32:
+ case SystemZ::FMOV32rm:
+ case SystemZ::FMOV32rmy:
+ case SystemZ::FMOV64rm:
+ case SystemZ::FMOV64rmy:
+ case SystemZ::MOV64Prm:
+ case SystemZ::MOV64Prmy:
+ case SystemZ::MOV128rm:
+ if (MI->getOperand(1).isFI() &&
+ MI->getOperand(2).isImm() && MI->getOperand(3).isReg() &&
+ MI->getOperand(2).getImm() == 0 && MI->getOperand(3).getReg() == 0) {
+ FrameIndex = MI->getOperand(1).getIndex();
+ return MI->getOperand(0).getReg();
+ }
+ break;
+ }
+ return 0;
+}
+
+unsigned SystemZInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const {
+ switch (MI->getOpcode()) {
+ default: break;
+ case SystemZ::MOV32mr:
+ case SystemZ::MOV32mry:
+ case SystemZ::MOV64mr:
+ case SystemZ::MOV32m8r:
+ case SystemZ::MOV32m8ry:
+ case SystemZ::MOV32m16r:
+ case SystemZ::MOV32m16ry:
+ case SystemZ::MOV64m8r:
+ case SystemZ::MOV64m8ry:
+ case SystemZ::MOV64m16r:
+ case SystemZ::MOV64m16ry:
+ case SystemZ::MOV64m32r:
+ case SystemZ::MOV64m32ry:
+ case SystemZ::FMOV32mr:
+ case SystemZ::FMOV32mry:
+ case SystemZ::FMOV64mr:
+ case SystemZ::FMOV64mry:
+ case SystemZ::MOV64Pmr:
+ case SystemZ::MOV64Pmry:
+ case SystemZ::MOV128mr:
+ if (MI->getOperand(0).isFI() &&
+ MI->getOperand(1).isImm() && MI->getOperand(2).isReg() &&
+ MI->getOperand(1).getImm() == 0 && MI->getOperand(2).getReg() == 0) {
+ FrameIndex = MI->getOperand(0).getIndex();
+ return MI->getOperand(3).getReg();
+ }
+ break;
+ }
+ return 0;
+}
+
+bool
+SystemZInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI,
+ const TargetRegisterInfo *TRI) const {
+ if (CSI.empty())
+ return false;
+
+ DebugLoc DL;
+ if (MI != MBB.end()) DL = MI->getDebugLoc();
+
+ MachineFunction &MF = *MBB.getParent();
+ SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
+ unsigned CalleeFrameSize = 0;
+
+ // Scan the callee-saved and find the bounds of register spill area.
+ unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0;
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ unsigned Reg = CSI[i].getReg();
+ const TargetRegisterClass *RegClass = CSI[i].getRegClass();
+ if (RegClass != &SystemZ::FP64RegClass) {
+ unsigned Offset = RegSpillOffsets[Reg];
+ CalleeFrameSize += 8;
+ if (StartOffset > Offset) {
+ LowReg = Reg; StartOffset = Offset;
+ }
+ if (EndOffset < Offset) {
+ HighReg = Reg; EndOffset = RegSpillOffsets[Reg];
+ }
+ }
+ }
+
+ // Save information for epilogue inserter.
+ MFI->setCalleeSavedFrameSize(CalleeFrameSize);
+ MFI->setLowReg(LowReg); MFI->setHighReg(HighReg);
+
+ // Save GPRs
+ if (StartOffset) {
+ // Build a store instruction. Use STORE MULTIPLE instruction if there are many
+ // registers to store, otherwise - just STORE.
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, MI, DL, get((LowReg == HighReg ?
+ SystemZ::MOV64mr : SystemZ::MOV64mrm)));
+
+ // Add store operands.
+ MIB.addReg(SystemZ::R15D).addImm(StartOffset);
+ if (LowReg == HighReg)
+ MIB.addReg(0);
+ MIB.addReg(LowReg, RegState::Kill);
+ if (LowReg != HighReg)
+ MIB.addReg(HighReg, RegState::Kill);
+
+ // Do a second scan adding regs as being killed by instruction
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ unsigned Reg = CSI[i].getReg();
+ // Add the callee-saved register as live-in. It's killed at the spill.
+ MBB.addLiveIn(Reg);
+ if (Reg != LowReg && Reg != HighReg)
+ MIB.addReg(Reg, RegState::ImplicitKill);
+ }
+ }
+
+ // Save FPRs
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ unsigned Reg = CSI[i].getReg();
+ const TargetRegisterClass *RegClass = CSI[i].getRegClass();
+ if (RegClass == &SystemZ::FP64RegClass) {
+ MBB.addLiveIn(Reg);
+ storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RegClass,
+ &RI);
+ }
+ }
+
+ return true;
+}
+
+bool
+SystemZInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI,
+ const TargetRegisterInfo *TRI) const {
+ if (CSI.empty())
+ return false;
+
+ DebugLoc DL;
+ if (MI != MBB.end()) DL = MI->getDebugLoc();
+
+ MachineFunction &MF = *MBB.getParent();
+ const TargetRegisterInfo *RegInfo= MF.getTarget().getRegisterInfo();
+ SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
+
+ // Restore FP registers
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ unsigned Reg = CSI[i].getReg();
+ const TargetRegisterClass *RegClass = CSI[i].getRegClass();
+ if (RegClass == &SystemZ::FP64RegClass)
+ loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RegClass, &RI);
+ }
+
+ // Restore GP registers
+ unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg();
+ unsigned StartOffset = RegSpillOffsets[LowReg];
+
+ if (StartOffset) {
+ // Build a load instruction. Use LOAD MULTIPLE instruction if there are many
+ // registers to load, otherwise - just LOAD.
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, MI, DL, get((LowReg == HighReg ?
+ SystemZ::MOV64rm : SystemZ::MOV64rmm)));
+ // Add store operands.
+ MIB.addReg(LowReg, RegState::Define);
+ if (LowReg != HighReg)
+ MIB.addReg(HighReg, RegState::Define);
+
+ MIB.addReg((RegInfo->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D));
+ MIB.addImm(StartOffset);
+ if (LowReg == HighReg)
+ MIB.addReg(0);
+
+ // Do a second scan adding regs as being defined by instruction
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ unsigned Reg = CSI[i].getReg();
+ if (Reg != LowReg && Reg != HighReg)
+ MIB.addReg(Reg, RegState::ImplicitDefine);
+ }
+ }
+
+ return true;
+}
+
+bool SystemZInstrInfo::
+ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
+ assert(Cond.size() == 1 && "Invalid Xbranch condition!");
+
+ SystemZCC::CondCodes CC = static_cast<SystemZCC::CondCodes>(Cond[0].getImm());
+ Cond[0].setImm(getOppositeCondition(CC));
+ return false;
+}
+
+bool SystemZInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
+ const TargetInstrDesc &TID = MI->getDesc();
+ if (!TID.isTerminator()) return false;
+
+ // Conditional branch is a special case.
+ if (TID.isBranch() && !TID.isBarrier())
+ return true;
+ if (!TID.isPredicable())
+ return true;
+ return !isPredicated(MI);
+}
+
+bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const {
+ // Start from the bottom of the block and work up, examining the
+ // terminator instructions.
+ MachineBasicBlock::iterator I = MBB.end();
+ while (I != MBB.begin()) {
+ --I;
+ if (I->isDebugValue())
+ continue;
+ // Working from the bottom, when we see a non-terminator
+ // instruction, we're done.
+ if (!isUnpredicatedTerminator(I))
+ break;
+
+ // A terminator that isn't a branch can't easily be handled
+ // by this analysis.
+ if (!I->getDesc().isBranch())
+ return true;
+
+ // Handle unconditional branches.
+ if (I->getOpcode() == SystemZ::JMP) {
+ if (!AllowModify) {
+ TBB = I->getOperand(0).getMBB();
+ continue;
+ }
+
+ // If the block has any instructions after a JMP, delete them.
+ while (llvm::next(I) != MBB.end())
+ llvm::next(I)->eraseFromParent();
+ Cond.clear();
+ FBB = 0;
+
+ // Delete the JMP if it's equivalent to a fall-through.
+ if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
+ TBB = 0;
+ I->eraseFromParent();
+ I = MBB.end();
+ continue;
+ }
+
+ // TBB is used to indicate the unconditinal destination.
+ TBB = I->getOperand(0).getMBB();
+ continue;
+ }
+
+ // Handle conditional branches.
+ SystemZCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode());
+ if (BranchCode == SystemZCC::INVALID)
+ return true; // Can't handle indirect branch.
+
+ // Working from the bottom, handle the first conditional branch.
+ if (Cond.empty()) {
+ FBB = TBB;
+ TBB = I->getOperand(0).getMBB();
+ Cond.push_back(MachineOperand::CreateImm(BranchCode));
+ continue;
+ }
+
+ // Handle subsequent conditional branches. Only handle the case where all
+ // conditional branches branch to the same destination.
+ assert(Cond.size() == 1);
+ assert(TBB);
+
+ // Only handle the case where all conditional branches branch to
+ // the same destination.
+ if (TBB != I->getOperand(0).getMBB())
+ return true;
+
+ SystemZCC::CondCodes OldBranchCode = (SystemZCC::CondCodes)Cond[0].getImm();
+ // If the conditions are the same, we can leave them alone.
+ if (OldBranchCode == BranchCode)
+ continue;
+
+ return true;
+ }
+
+ return false;
+}
+
+unsigned SystemZInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
+ MachineBasicBlock::iterator I = MBB.end();
+ unsigned Count = 0;
+
+ while (I != MBB.begin()) {
+ --I;
+ if (I->isDebugValue())
+ continue;
+ if (I->getOpcode() != SystemZ::JMP &&
+ getCondFromBranchOpc(I->getOpcode()) == SystemZCC::INVALID)
+ break;
+ // Remove the branch.
+ I->eraseFromParent();
+ I = MBB.end();
+ ++Count;
+ }
+
+ return Count;
+}
+
+unsigned
+SystemZInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB,
+ const SmallVectorImpl<MachineOperand> &Cond) const {
+ // FIXME: this should probably have a DebugLoc operand
+ DebugLoc DL;
+ // Shouldn't be a fall through.
+ assert(TBB && "InsertBranch must not be told to insert a fallthrough");
+ assert((Cond.size() == 1 || Cond.size() == 0) &&
+ "SystemZ branch conditions have one component!");
+
+ if (Cond.empty()) {
+ // Unconditional branch?
+ assert(!FBB && "Unconditional branch with multiple successors!");
+ BuildMI(&MBB, DL, get(SystemZ::JMP)).addMBB(TBB);
+ return 1;
+ }
+
+ // Conditional branch.
+ unsigned Count = 0;
+ SystemZCC::CondCodes CC = (SystemZCC::CondCodes)Cond[0].getImm();
+ BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
+ ++Count;
+
+ if (FBB) {
+ // Two-way Conditional branch. Insert the second branch.
+ BuildMI(&MBB, DL, get(SystemZ::JMP)).addMBB(FBB);
+ ++Count;
+ }
+ return Count;
+}
+
+const TargetInstrDesc&
+SystemZInstrInfo::getBrCond(SystemZCC::CondCodes CC) const {
+ switch (CC) {
+ default:
+ llvm_unreachable("Unknown condition code!");
+ case SystemZCC::O: return get(SystemZ::JO);
+ case SystemZCC::H: return get(SystemZ::JH);
+ case SystemZCC::NLE: return get(SystemZ::JNLE);
+ case SystemZCC::L: return get(SystemZ::JL);
+ case SystemZCC::NHE: return get(SystemZ::JNHE);
+ case SystemZCC::LH: return get(SystemZ::JLH);
+ case SystemZCC::NE: return get(SystemZ::JNE);
+ case SystemZCC::E: return get(SystemZ::JE);
+ case SystemZCC::NLH: return get(SystemZ::JNLH);
+ case SystemZCC::HE: return get(SystemZ::JHE);
+ case SystemZCC::NL: return get(SystemZ::JNL);
+ case SystemZCC::LE: return get(SystemZ::JLE);
+ case SystemZCC::NH: return get(SystemZ::JNH);
+ case SystemZCC::NO: return get(SystemZ::JNO);
+ }
+}
+
+SystemZCC::CondCodes
+SystemZInstrInfo::getCondFromBranchOpc(unsigned Opc) const {
+ switch (Opc) {
+ default: return SystemZCC::INVALID;
+ case SystemZ::JO: return SystemZCC::O;
+ case SystemZ::JH: return SystemZCC::H;
+ case SystemZ::JNLE: return SystemZCC::NLE;
+ case SystemZ::JL: return SystemZCC::L;
+ case SystemZ::JNHE: return SystemZCC::NHE;
+ case SystemZ::JLH: return SystemZCC::LH;
+ case SystemZ::JNE: return SystemZCC::NE;
+ case SystemZ::JE: return SystemZCC::E;
+ case SystemZ::JNLH: return SystemZCC::NLH;
+ case SystemZ::JHE: return SystemZCC::HE;
+ case SystemZ::JNL: return SystemZCC::NL;
+ case SystemZ::JLE: return SystemZCC::LE;
+ case SystemZ::JNH: return SystemZCC::NH;
+ case SystemZ::JNO: return SystemZCC::NO;
+ }
+}
+
+SystemZCC::CondCodes
+SystemZInstrInfo::getOppositeCondition(SystemZCC::CondCodes CC) const {
+ switch (CC) {
+ default:
+ llvm_unreachable("Invalid condition!");
+ case SystemZCC::O: return SystemZCC::NO;
+ case SystemZCC::H: return SystemZCC::NH;
+ case SystemZCC::NLE: return SystemZCC::LE;
+ case SystemZCC::L: return SystemZCC::NL;
+ case SystemZCC::NHE: return SystemZCC::HE;
+ case SystemZCC::LH: return SystemZCC::NLH;
+ case SystemZCC::NE: return SystemZCC::E;
+ case SystemZCC::E: return SystemZCC::NE;
+ case SystemZCC::NLH: return SystemZCC::LH;
+ case SystemZCC::HE: return SystemZCC::NHE;
+ case SystemZCC::NL: return SystemZCC::L;
+ case SystemZCC::LE: return SystemZCC::NLE;
+ case SystemZCC::NH: return SystemZCC::H;
+ case SystemZCC::NO: return SystemZCC::O;
+ }
+}
+
+const TargetInstrDesc&
+SystemZInstrInfo::getLongDispOpc(unsigned Opc) const {
+ switch (Opc) {
+ default:
+ llvm_unreachable("Don't have long disp version of this instruction");
+ case SystemZ::MOV32mr: return get(SystemZ::MOV32mry);
+ case SystemZ::MOV32rm: return get(SystemZ::MOV32rmy);
+ case SystemZ::MOVSX32rm16: return get(SystemZ::MOVSX32rm16y);
+ case SystemZ::MOV32m8r: return get(SystemZ::MOV32m8ry);
+ case SystemZ::MOV32m16r: return get(SystemZ::MOV32m16ry);
+ case SystemZ::MOV64m8r: return get(SystemZ::MOV64m8ry);
+ case SystemZ::MOV64m16r: return get(SystemZ::MOV64m16ry);
+ case SystemZ::MOV64m32r: return get(SystemZ::MOV64m32ry);
+ case SystemZ::MOV8mi: return get(SystemZ::MOV8miy);
+ case SystemZ::MUL32rm: return get(SystemZ::MUL32rmy);
+ case SystemZ::CMP32rm: return get(SystemZ::CMP32rmy);
+ case SystemZ::UCMP32rm: return get(SystemZ::UCMP32rmy);
+ case SystemZ::FMOV32mr: return get(SystemZ::FMOV32mry);
+ case SystemZ::FMOV64mr: return get(SystemZ::FMOV64mry);
+ case SystemZ::FMOV32rm: return get(SystemZ::FMOV32rmy);
+ case SystemZ::FMOV64rm: return get(SystemZ::FMOV64rmy);
+ case SystemZ::MOV64Pmr: return get(SystemZ::MOV64Pmry);
+ case SystemZ::MOV64Prm: return get(SystemZ::MOV64Prmy);
+ }
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
new file mode 100644
index 0000000..a753f14
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
@@ -0,0 +1,123 @@
+//===- SystemZInstrInfo.h - SystemZ Instruction Information -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SystemZ implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_SYSTEMZINSTRINFO_H
+#define LLVM_TARGET_SYSTEMZINSTRINFO_H
+
+#include "SystemZ.h"
+#include "SystemZRegisterInfo.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/Target/TargetInstrInfo.h"
+
+namespace llvm {
+
+class SystemZTargetMachine;
+
+/// SystemZII - This namespace holds all of the target specific flags that
+/// instruction info tracks.
+///
+namespace SystemZII {
+ enum {
+ //===------------------------------------------------------------------===//
+ // SystemZ Specific MachineOperand flags.
+
+ MO_NO_FLAG = 0,
+
+ /// MO_GOTENT - On a symbol operand this indicates that the immediate is
+ /// the offset to the location of the symbol name from the base of the GOT.
+ ///
+ /// SYMBOL_LABEL @GOTENT
+ MO_GOTENT = 1,
+
+ /// MO_PLT - On a symbol operand this indicates that the immediate is
+ /// offset to the PLT entry of symbol name from the current code location.
+ ///
+ /// SYMBOL_LABEL @PLT
+ MO_PLT = 2
+ };
+}
+
+class SystemZInstrInfo : public TargetInstrInfoImpl {
+ const SystemZRegisterInfo RI;
+ SystemZTargetMachine &TM;
+ IndexedMap<unsigned> RegSpillOffsets;
+public:
+ explicit SystemZInstrInfo(SystemZTargetMachine &TM);
+
+ /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
+ /// such, whenever a client has an instance of instruction info, it should
+ /// always be able to get register info as well (through this method).
+ ///
+ virtual const SystemZRegisterInfo &getRegisterInfo() const { return RI; }
+
+ bool copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+ unsigned DestReg, unsigned SrcReg,
+ const TargetRegisterClass *DestRC,
+ const TargetRegisterClass *SrcRC,
+ DebugLoc DL) const;
+
+ bool isMoveInstr(const MachineInstr& MI,
+ unsigned &SrcReg, unsigned &DstReg,
+ unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
+ unsigned isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const;
+ unsigned isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const;
+
+ virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned SrcReg, bool isKill,
+ int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const;
+ virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned DestReg, int FrameIdx,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const;
+
+ virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI,
+ const TargetRegisterInfo *TRI) const;
+ virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI,
+ const TargetRegisterInfo *TRI) const;
+
+ bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
+ virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const;
+ virtual bool AnalyzeBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const;
+ virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB,
+ const SmallVectorImpl<MachineOperand> &Cond) const;
+ virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const;
+
+ SystemZCC::CondCodes getOppositeCondition(SystemZCC::CondCodes CC) const;
+ SystemZCC::CondCodes getCondFromBranchOpc(unsigned Opc) const;
+ const TargetInstrDesc& getBrCond(SystemZCC::CondCodes CC) const;
+ const TargetInstrDesc& getLongDispOpc(unsigned Opc) const;
+
+ const TargetInstrDesc& getMemoryInstr(unsigned Opc, int64_t Offset = 0) const {
+ if (Offset < 0 || Offset >= 4096)
+ return getLongDispOpc(Opc);
+ else
+ return get(Opc);
+ }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
new file mode 100644
index 0000000..22bde4e
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -0,0 +1,1146 @@
+//===- SystemZInstrInfo.td - SystemZ Instruction defs ---------*- tblgen-*-===//
+//
+// 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 SystemZ instructions in TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// SystemZ Instruction Predicate Definitions.
+def IsZ10 : Predicate<"Subtarget.isZ10()">;
+
+include "SystemZInstrFormats.td"
+
+//===----------------------------------------------------------------------===//
+// Type Constraints.
+//===----------------------------------------------------------------------===//
+class SDTCisI8<int OpNum> : SDTCisVT<OpNum, i8>;
+class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
+class SDTCisI32<int OpNum> : SDTCisVT<OpNum, i32>;
+class SDTCisI64<int OpNum> : SDTCisVT<OpNum, i64>;
+
+//===----------------------------------------------------------------------===//
+// Type Profiles.
+//===----------------------------------------------------------------------===//
+def SDT_SystemZCall : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
+def SDT_SystemZCallSeqStart : SDCallSeqStart<[SDTCisI64<0>]>;
+def SDT_SystemZCallSeqEnd : SDCallSeqEnd<[SDTCisI64<0>, SDTCisI64<1>]>;
+def SDT_CmpTest : SDTypeProfile<1, 2, [SDTCisI64<0>,
+ SDTCisSameAs<1, 2>]>;
+def SDT_BrCond : SDTypeProfile<0, 3,
+ [SDTCisVT<0, OtherVT>,
+ SDTCisI8<1>, SDTCisVT<2, i64>]>;
+def SDT_SelectCC : SDTypeProfile<1, 4,
+ [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
+ SDTCisI8<3>, SDTCisVT<4, i64>]>;
+def SDT_Address : SDTypeProfile<1, 1,
+ [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
+
+//===----------------------------------------------------------------------===//
+// SystemZ Specific Node Definitions.
+//===----------------------------------------------------------------------===//
+def SystemZretflag : SDNode<"SystemZISD::RET_FLAG", SDTNone,
+ [SDNPHasChain, SDNPOptInFlag]>;
+def SystemZcall : SDNode<"SystemZISD::CALL", SDT_SystemZCall,
+ [SDNPHasChain, SDNPOutFlag, SDNPOptInFlag, SDNPVariadic]>;
+def SystemZcallseq_start :
+ SDNode<"ISD::CALLSEQ_START", SDT_SystemZCallSeqStart,
+ [SDNPHasChain, SDNPOutFlag]>;
+def SystemZcallseq_end :
+ SDNode<"ISD::CALLSEQ_END", SDT_SystemZCallSeqEnd,
+ [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
+def SystemZcmp : SDNode<"SystemZISD::CMP", SDT_CmpTest>;
+def SystemZucmp : SDNode<"SystemZISD::UCMP", SDT_CmpTest>;
+def SystemZbrcond : SDNode<"SystemZISD::BRCOND", SDT_BrCond,
+ [SDNPHasChain]>;
+def SystemZselect : SDNode<"SystemZISD::SELECT", SDT_SelectCC>;
+def SystemZpcrelwrapper : SDNode<"SystemZISD::PCRelativeWrapper", SDT_Address, []>;
+
+
+include "SystemZOperands.td"
+
+//===----------------------------------------------------------------------===//
+// Instruction list..
+
+def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt),
+ "#ADJCALLSTACKDOWN",
+ [(SystemZcallseq_start timm:$amt)]>;
+def ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2),
+ "#ADJCALLSTACKUP",
+ [(SystemZcallseq_end timm:$amt1, timm:$amt2)]>;
+
+let Uses = [PSW], usesCustomInserter = 1 in {
+ def Select32 : Pseudo<(outs GR32:$dst), (ins GR32:$src1, GR32:$src2, i8imm:$cc),
+ "# Select32 PSEUDO",
+ [(set GR32:$dst,
+ (SystemZselect GR32:$src1, GR32:$src2, imm:$cc, PSW))]>;
+ def Select64 : Pseudo<(outs GR64:$dst), (ins GR64:$src1, GR64:$src2, i8imm:$cc),
+ "# Select64 PSEUDO",
+ [(set GR64:$dst,
+ (SystemZselect GR64:$src1, GR64:$src2, imm:$cc, PSW))]>;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Control Flow Instructions...
+//
+
+// FIXME: Provide proper encoding!
+let isReturn = 1, isTerminator = 1, isBarrier = 1, hasCtrlDep = 1 in {
+ def RET : Pseudo<(outs), (ins), "br\t%r14", [(SystemZretflag)]>;
+}
+
+let isBranch = 1, isTerminator = 1 in {
+ let isBarrier = 1 in {
+ def JMP : Pseudo<(outs), (ins brtarget:$dst), "j\t{$dst}", [(br bb:$dst)]>;
+
+ let isIndirectBranch = 1 in
+ def JMPr : Pseudo<(outs), (ins GR64:$dst), "br\t{$dst}", [(brind GR64:$dst)]>;
+ }
+
+ let Uses = [PSW] in {
+ def JO : Pseudo<(outs), (ins brtarget:$dst),
+ "jo\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_O, PSW)]>;
+ def JH : Pseudo<(outs), (ins brtarget:$dst),
+ "jh\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_H, PSW)]>;
+ def JNLE: Pseudo<(outs), (ins brtarget:$dst),
+ "jnle\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NLE, PSW)]>;
+ def JL : Pseudo<(outs), (ins brtarget:$dst),
+ "jl\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_L, PSW)]>;
+ def JNHE: Pseudo<(outs), (ins brtarget:$dst),
+ "jnhe\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NHE, PSW)]>;
+ def JLH : Pseudo<(outs), (ins brtarget:$dst),
+ "jlh\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_LH, PSW)]>;
+ def JNE : Pseudo<(outs), (ins brtarget:$dst),
+ "jne\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NE, PSW)]>;
+ def JE : Pseudo<(outs), (ins brtarget:$dst),
+ "je\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_E, PSW)]>;
+ def JNLH: Pseudo<(outs), (ins brtarget:$dst),
+ "jnlh\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NLH, PSW)]>;
+ def JHE : Pseudo<(outs), (ins brtarget:$dst),
+ "jhe\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_HE, PSW)]>;
+ def JNL : Pseudo<(outs), (ins brtarget:$dst),
+ "jnl\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NL, PSW)]>;
+ def JLE : Pseudo<(outs), (ins brtarget:$dst),
+ "jle\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_LE, PSW)]>;
+ def JNH : Pseudo<(outs), (ins brtarget:$dst),
+ "jnh\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NH, PSW)]>;
+ def JNO : Pseudo<(outs), (ins brtarget:$dst),
+ "jno\t$dst",
+ [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NO, PSW)]>;
+ } // Uses = [PSW]
+} // isBranch = 1
+
+//===----------------------------------------------------------------------===//
+// Call Instructions...
+//
+
+let isCall = 1 in
+ // All calls clobber the non-callee saved registers. Uses for argument
+ // registers are added manually.
+ let Defs = [R0D, R1D, R2D, R3D, R4D, R5D, R14D,
+ F0L, F1L, F2L, F3L, F4L, F5L, F6L, F7L] in {
+ def CALLi : Pseudo<(outs), (ins imm_pcrel:$dst, variable_ops),
+ "brasl\t%r14, $dst", [(SystemZcall imm:$dst)]>;
+ def CALLr : Pseudo<(outs), (ins ADDR64:$dst, variable_ops),
+ "basr\t%r14, $dst", [(SystemZcall ADDR64:$dst)]>;
+ }
+
+//===----------------------------------------------------------------------===//
+// Miscellaneous Instructions.
+//
+
+let isReMaterializable = 1 in
+// FIXME: Provide imm12 variant
+// FIXME: Address should be halfword aligned...
+def LA64r : RXI<0x47,
+ (outs GR64:$dst), (ins laaddr:$src),
+ "lay\t{$dst, $src}",
+ [(set GR64:$dst, laaddr:$src)]>;
+def LA64rm : RXYI<0x71E3,
+ (outs GR64:$dst), (ins i64imm:$src),
+ "larl\t{$dst, $src}",
+ [(set GR64:$dst,
+ (SystemZpcrelwrapper tglobaladdr:$src))]>;
+
+let neverHasSideEffects = 1 in
+def NOP : Pseudo<(outs), (ins), "# no-op", []>;
+
+//===----------------------------------------------------------------------===//
+// Move Instructions
+
+let neverHasSideEffects = 1 in {
+def MOV32rr : RRI<0x18,
+ (outs GR32:$dst), (ins GR32:$src),
+ "lr\t{$dst, $src}",
+ []>;
+def MOV64rr : RREI<0xB904,
+ (outs GR64:$dst), (ins GR64:$src),
+ "lgr\t{$dst, $src}",
+ []>;
+def MOV128rr : Pseudo<(outs GR128:$dst), (ins GR128:$src),
+ "# MOV128 PSEUDO!\n"
+ "\tlgr\t${dst:subreg_odd}, ${src:subreg_odd}\n"
+ "\tlgr\t${dst:subreg_even}, ${src:subreg_even}",
+ []>;
+def MOV64rrP : Pseudo<(outs GR64P:$dst), (ins GR64P:$src),
+ "# MOV64P PSEUDO!\n"
+ "\tlr\t${dst:subreg_odd}, ${src:subreg_odd}\n"
+ "\tlr\t${dst:subreg_even}, ${src:subreg_even}",
+ []>;
+}
+
+def MOVSX64rr32 : RREI<0xB914,
+ (outs GR64:$dst), (ins GR32:$src),
+ "lgfr\t{$dst, $src}",
+ [(set GR64:$dst, (sext GR32:$src))]>;
+def MOVZX64rr32 : RREI<0xB916,
+ (outs GR64:$dst), (ins GR32:$src),
+ "llgfr\t{$dst, $src}",
+ [(set GR64:$dst, (zext GR32:$src))]>;
+
+let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
+def MOV32ri16 : RII<0x8A7,
+ (outs GR32:$dst), (ins s16imm:$src),
+ "lhi\t{$dst, $src}",
+ [(set GR32:$dst, immSExt16:$src)]>;
+def MOV64ri16 : RII<0x9A7,
+ (outs GR64:$dst), (ins s16imm64:$src),
+ "lghi\t{$dst, $src}",
+ [(set GR64:$dst, immSExt16:$src)]>;
+
+def MOV64rill16 : RII<0xFA5,
+ (outs GR64:$dst), (ins i64imm:$src),
+ "llill\t{$dst, $src}",
+ [(set GR64:$dst, i64ll16:$src)]>;
+def MOV64rilh16 : RII<0xEA5,
+ (outs GR64:$dst), (ins i64imm:$src),
+ "llilh\t{$dst, $src}",
+ [(set GR64:$dst, i64lh16:$src)]>;
+def MOV64rihl16 : RII<0xDA5,
+ (outs GR64:$dst), (ins i64imm:$src),
+ "llihl\t{$dst, $src}",
+ [(set GR64:$dst, i64hl16:$src)]>;
+def MOV64rihh16 : RII<0xCA5,
+ (outs GR64:$dst), (ins i64imm:$src),
+ "llihh\t{$dst, $src}",
+ [(set GR64:$dst, i64hh16:$src)]>;
+
+def MOV64ri32 : RILI<0x1C0,
+ (outs GR64:$dst), (ins s32imm64:$src),
+ "lgfi\t{$dst, $src}",
+ [(set GR64:$dst, immSExt32:$src)]>;
+def MOV64rilo32 : RILI<0xFC0,
+ (outs GR64:$dst), (ins i64imm:$src),
+ "llilf\t{$dst, $src}",
+ [(set GR64:$dst, i64lo32:$src)]>;
+def MOV64rihi32 : RILI<0xEC0, (outs GR64:$dst), (ins i64imm:$src),
+ "llihf\t{$dst, $src}",
+ [(set GR64:$dst, i64hi32:$src)]>;
+}
+
+let canFoldAsLoad = 1, isReMaterializable = 1 in {
+def MOV32rm : RXI<0x58,
+ (outs GR32:$dst), (ins rriaddr12:$src),
+ "l\t{$dst, $src}",
+ [(set GR32:$dst, (load rriaddr12:$src))]>;
+def MOV32rmy : RXYI<0x58E3,
+ (outs GR32:$dst), (ins rriaddr:$src),
+ "ly\t{$dst, $src}",
+ [(set GR32:$dst, (load rriaddr:$src))]>;
+def MOV64rm : RXYI<0x04E3,
+ (outs GR64:$dst), (ins rriaddr:$src),
+ "lg\t{$dst, $src}",
+ [(set GR64:$dst, (load rriaddr:$src))]>;
+def MOV64Prm : Pseudo<(outs GR64P:$dst), (ins rriaddr12:$src),
+ "# MOV64P PSEUDO!\n"
+ "\tl\t${dst:subreg_odd}, $src\n"
+ "\tl\t${dst:subreg_even}, 4+$src",
+ [(set GR64P:$dst, (load rriaddr12:$src))]>;
+def MOV64Prmy : Pseudo<(outs GR64P:$dst), (ins rriaddr:$src),
+ "# MOV64P PSEUDO!\n"
+ "\tly\t${dst:subreg_odd}, $src\n"
+ "\tly\t${dst:subreg_even}, 4+$src",
+ [(set GR64P:$dst, (load rriaddr:$src))]>;
+def MOV128rm : Pseudo<(outs GR128:$dst), (ins rriaddr:$src),
+ "# MOV128 PSEUDO!\n"
+ "\tlg\t${dst:subreg_odd}, $src\n"
+ "\tlg\t${dst:subreg_even}, 8+$src",
+ [(set GR128:$dst, (load rriaddr:$src))]>;
+}
+
+def MOV32mr : RXI<0x50,
+ (outs), (ins rriaddr12:$dst, GR32:$src),
+ "st\t{$src, $dst}",
+ [(store GR32:$src, rriaddr12:$dst)]>;
+def MOV32mry : RXYI<0x50E3,
+ (outs), (ins rriaddr:$dst, GR32:$src),
+ "sty\t{$src, $dst}",
+ [(store GR32:$src, rriaddr:$dst)]>;
+def MOV64mr : RXYI<0x24E3,
+ (outs), (ins rriaddr:$dst, GR64:$src),
+ "stg\t{$src, $dst}",
+ [(store GR64:$src, rriaddr:$dst)]>;
+def MOV64Pmr : Pseudo<(outs), (ins rriaddr12:$dst, GR64P:$src),
+ "# MOV64P PSEUDO!\n"
+ "\tst\t${src:subreg_odd}, $dst\n"
+ "\tst\t${src:subreg_even}, 4+$dst",
+ [(store GR64P:$src, rriaddr12:$dst)]>;
+def MOV64Pmry : Pseudo<(outs), (ins rriaddr:$dst, GR64P:$src),
+ "# MOV64P PSEUDO!\n"
+ "\tsty\t${src:subreg_odd}, $dst\n"
+ "\tsty\t${src:subreg_even}, 4+$dst",
+ [(store GR64P:$src, rriaddr:$dst)]>;
+def MOV128mr : Pseudo<(outs), (ins rriaddr:$dst, GR128:$src),
+ "# MOV128 PSEUDO!\n"
+ "\tstg\t${src:subreg_odd}, $dst\n"
+ "\tstg\t${src:subreg_even}, 8+$dst",
+ [(store GR128:$src, rriaddr:$dst)]>;
+
+def MOV8mi : SII<0x92,
+ (outs), (ins riaddr12:$dst, i32i8imm:$src),
+ "mvi\t{$dst, $src}",
+ [(truncstorei8 (i32 i32immSExt8:$src), riaddr12:$dst)]>;
+def MOV8miy : SIYI<0x52EB,
+ (outs), (ins riaddr:$dst, i32i8imm:$src),
+ "mviy\t{$dst, $src}",
+ [(truncstorei8 (i32 i32immSExt8:$src), riaddr:$dst)]>;
+
+let AddedComplexity = 2 in {
+def MOV16mi : SILI<0xE544,
+ (outs), (ins riaddr12:$dst, s16imm:$src),
+ "mvhhi\t{$dst, $src}",
+ [(truncstorei16 (i32 i32immSExt16:$src), riaddr12:$dst)]>,
+ Requires<[IsZ10]>;
+def MOV32mi16 : SILI<0xE54C,
+ (outs), (ins riaddr12:$dst, s32imm:$src),
+ "mvhi\t{$dst, $src}",
+ [(store (i32 immSExt16:$src), riaddr12:$dst)]>,
+ Requires<[IsZ10]>;
+def MOV64mi16 : SILI<0xE548,
+ (outs), (ins riaddr12:$dst, s32imm64:$src),
+ "mvghi\t{$dst, $src}",
+ [(store (i64 immSExt16:$src), riaddr12:$dst)]>,
+ Requires<[IsZ10]>;
+}
+
+// sexts
+def MOVSX32rr8 : RREI<0xB926,
+ (outs GR32:$dst), (ins GR32:$src),
+ "lbr\t{$dst, $src}",
+ [(set GR32:$dst, (sext_inreg GR32:$src, i8))]>;
+def MOVSX64rr8 : RREI<0xB906,
+ (outs GR64:$dst), (ins GR64:$src),
+ "lgbr\t{$dst, $src}",
+ [(set GR64:$dst, (sext_inreg GR64:$src, i8))]>;
+def MOVSX32rr16 : RREI<0xB927,
+ (outs GR32:$dst), (ins GR32:$src),
+ "lhr\t{$dst, $src}",
+ [(set GR32:$dst, (sext_inreg GR32:$src, i16))]>;
+def MOVSX64rr16 : RREI<0xB907,
+ (outs GR64:$dst), (ins GR64:$src),
+ "lghr\t{$dst, $src}",
+ [(set GR64:$dst, (sext_inreg GR64:$src, i16))]>;
+
+// extloads
+def MOVSX32rm8 : RXYI<0x76E3,
+ (outs GR32:$dst), (ins rriaddr:$src),
+ "lb\t{$dst, $src}",
+ [(set GR32:$dst, (sextloadi32i8 rriaddr:$src))]>;
+def MOVSX32rm16 : RXI<0x48,
+ (outs GR32:$dst), (ins rriaddr12:$src),
+ "lh\t{$dst, $src}",
+ [(set GR32:$dst, (sextloadi32i16 rriaddr12:$src))]>;
+def MOVSX32rm16y : RXYI<0x78E3,
+ (outs GR32:$dst), (ins rriaddr:$src),
+ "lhy\t{$dst, $src}",
+ [(set GR32:$dst, (sextloadi32i16 rriaddr:$src))]>;
+def MOVSX64rm8 : RXYI<0x77E3,
+ (outs GR64:$dst), (ins rriaddr:$src),
+ "lgb\t{$dst, $src}",
+ [(set GR64:$dst, (sextloadi64i8 rriaddr:$src))]>;
+def MOVSX64rm16 : RXYI<0x15E3,
+ (outs GR64:$dst), (ins rriaddr:$src),
+ "lgh\t{$dst, $src}",
+ [(set GR64:$dst, (sextloadi64i16 rriaddr:$src))]>;
+def MOVSX64rm32 : RXYI<0x14E3,
+ (outs GR64:$dst), (ins rriaddr:$src),
+ "lgf\t{$dst, $src}",
+ [(set GR64:$dst, (sextloadi64i32 rriaddr:$src))]>;
+
+def MOVZX32rm8 : RXYI<0x94E3,
+ (outs GR32:$dst), (ins rriaddr:$src),
+ "llc\t{$dst, $src}",
+ [(set GR32:$dst, (zextloadi32i8 rriaddr:$src))]>;
+def MOVZX32rm16 : RXYI<0x95E3,
+ (outs GR32:$dst), (ins rriaddr:$src),
+ "llh\t{$dst, $src}",
+ [(set GR32:$dst, (zextloadi32i16 rriaddr:$src))]>;
+def MOVZX64rm8 : RXYI<0x90E3,
+ (outs GR64:$dst), (ins rriaddr:$src),
+ "llgc\t{$dst, $src}",
+ [(set GR64:$dst, (zextloadi64i8 rriaddr:$src))]>;
+def MOVZX64rm16 : RXYI<0x91E3,
+ (outs GR64:$dst), (ins rriaddr:$src),
+ "llgh\t{$dst, $src}",
+ [(set GR64:$dst, (zextloadi64i16 rriaddr:$src))]>;
+def MOVZX64rm32 : RXYI<0x16E3,
+ (outs GR64:$dst), (ins rriaddr:$src),
+ "llgf\t{$dst, $src}",
+ [(set GR64:$dst, (zextloadi64i32 rriaddr:$src))]>;
+
+// truncstores
+def MOV32m8r : RXI<0x42,
+ (outs), (ins rriaddr12:$dst, GR32:$src),
+ "stc\t{$src, $dst}",
+ [(truncstorei8 GR32:$src, rriaddr12:$dst)]>;
+
+def MOV32m8ry : RXYI<0x72E3,
+ (outs), (ins rriaddr:$dst, GR32:$src),
+ "stcy\t{$src, $dst}",
+ [(truncstorei8 GR32:$src, rriaddr:$dst)]>;
+
+def MOV32m16r : RXI<0x40,
+ (outs), (ins rriaddr12:$dst, GR32:$src),
+ "sth\t{$src, $dst}",
+ [(truncstorei16 GR32:$src, rriaddr12:$dst)]>;
+
+def MOV32m16ry : RXYI<0x70E3,
+ (outs), (ins rriaddr:$dst, GR32:$src),
+ "sthy\t{$src, $dst}",
+ [(truncstorei16 GR32:$src, rriaddr:$dst)]>;
+
+def MOV64m8r : RXI<0x42,
+ (outs), (ins rriaddr12:$dst, GR64:$src),
+ "stc\t{$src, $dst}",
+ [(truncstorei8 GR64:$src, rriaddr12:$dst)]>;
+
+def MOV64m8ry : RXYI<0x72E3,
+ (outs), (ins rriaddr:$dst, GR64:$src),
+ "stcy\t{$src, $dst}",
+ [(truncstorei8 GR64:$src, rriaddr:$dst)]>;
+
+def MOV64m16r : RXI<0x40,
+ (outs), (ins rriaddr12:$dst, GR64:$src),
+ "sth\t{$src, $dst}",
+ [(truncstorei16 GR64:$src, rriaddr12:$dst)]>;
+
+def MOV64m16ry : RXYI<0x70E3,
+ (outs), (ins rriaddr:$dst, GR64:$src),
+ "sthy\t{$src, $dst}",
+ [(truncstorei16 GR64:$src, rriaddr:$dst)]>;
+
+def MOV64m32r : RXI<0x50,
+ (outs), (ins rriaddr12:$dst, GR64:$src),
+ "st\t{$src, $dst}",
+ [(truncstorei32 GR64:$src, rriaddr12:$dst)]>;
+
+def MOV64m32ry : RXYI<0x50E3,
+ (outs), (ins rriaddr:$dst, GR64:$src),
+ "sty\t{$src, $dst}",
+ [(truncstorei32 GR64:$src, rriaddr:$dst)]>;
+
+// multiple regs moves
+// FIXME: should we use multiple arg nodes?
+def MOV32mrm : RSYI<0x90EB,
+ (outs), (ins riaddr:$dst, GR32:$from, GR32:$to),
+ "stmy\t{$from, $to, $dst}",
+ []>;
+def MOV64mrm : RSYI<0x24EB,
+ (outs), (ins riaddr:$dst, GR64:$from, GR64:$to),
+ "stmg\t{$from, $to, $dst}",
+ []>;
+def MOV32rmm : RSYI<0x90EB,
+ (outs GR32:$from, GR32:$to), (ins riaddr:$dst),
+ "lmy\t{$from, $to, $dst}",
+ []>;
+def MOV64rmm : RSYI<0x04EB,
+ (outs GR64:$from, GR64:$to), (ins riaddr:$dst),
+ "lmg\t{$from, $to, $dst}",
+ []>;
+
+let isReMaterializable = 1, isAsCheapAsAMove = 1, isTwoAddress = 1 in {
+def MOV64Pr0_even : Pseudo<(outs GR64P:$dst), (ins GR64P:$src),
+ "lhi\t${dst:subreg_even}, 0",
+ []>;
+def MOV128r0_even : Pseudo<(outs GR128:$dst), (ins GR128:$src),
+ "lghi\t${dst:subreg_even}, 0",
+ []>;
+}
+
+// Byte swaps
+def BSWAP32rr : RREI<0xB91F,
+ (outs GR32:$dst), (ins GR32:$src),
+ "lrvr\t{$dst, $src}",
+ [(set GR32:$dst, (bswap GR32:$src))]>;
+def BSWAP64rr : RREI<0xB90F,
+ (outs GR64:$dst), (ins GR64:$src),
+ "lrvgr\t{$dst, $src}",
+ [(set GR64:$dst, (bswap GR64:$src))]>;
+
+// FIXME: this is invalid pattern for big-endian
+//def BSWAP16rm : RXYI<0x1FE3, (outs GR32:$dst), (ins rriaddr:$src),
+// "lrvh\t{$dst, $src}",
+// [(set GR32:$dst, (bswap (extloadi32i16 rriaddr:$src)))]>;
+def BSWAP32rm : RXYI<0x1EE3, (outs GR32:$dst), (ins rriaddr:$src),
+ "lrv\t{$dst, $src}",
+ [(set GR32:$dst, (bswap (load rriaddr:$src)))]>;
+def BSWAP64rm : RXYI<0x0FE3, (outs GR64:$dst), (ins rriaddr:$src),
+ "lrvg\t{$dst, $src}",
+ [(set GR64:$dst, (bswap (load rriaddr:$src)))]>;
+
+//def BSWAP16mr : RXYI<0xE33F, (outs), (ins rriaddr:$dst, GR32:$src),
+// "strvh\t{$src, $dst}",
+// [(truncstorei16 (bswap GR32:$src), rriaddr:$dst)]>;
+def BSWAP32mr : RXYI<0xE33E, (outs), (ins rriaddr:$dst, GR32:$src),
+ "strv\t{$src, $dst}",
+ [(store (bswap GR32:$src), rriaddr:$dst)]>;
+def BSWAP64mr : RXYI<0xE32F, (outs), (ins rriaddr:$dst, GR64:$src),
+ "strvg\t{$src, $dst}",
+ [(store (bswap GR64:$src), rriaddr:$dst)]>;
+
+//===----------------------------------------------------------------------===//
+// Arithmetic Instructions
+
+let Defs = [PSW] in {
+def NEG32rr : RRI<0x13,
+ (outs GR32:$dst), (ins GR32:$src),
+ "lcr\t{$dst, $src}",
+ [(set GR32:$dst, (ineg GR32:$src)),
+ (implicit PSW)]>;
+def NEG64rr : RREI<0xB903, (outs GR64:$dst), (ins GR64:$src),
+ "lcgr\t{$dst, $src}",
+ [(set GR64:$dst, (ineg GR64:$src)),
+ (implicit PSW)]>;
+def NEG64rr32 : RREI<0xB913, (outs GR64:$dst), (ins GR32:$src),
+ "lcgfr\t{$dst, $src}",
+ [(set GR64:$dst, (ineg (sext GR32:$src))),
+ (implicit PSW)]>;
+}
+
+let isTwoAddress = 1 in {
+
+let Defs = [PSW] in {
+
+let isCommutable = 1 in { // X = ADD Y, Z == X = ADD Z, Y
+def ADD32rr : RRI<0x1A, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "ar\t{$dst, $src2}",
+ [(set GR32:$dst, (add GR32:$src1, GR32:$src2)),
+ (implicit PSW)]>;
+def ADD64rr : RREI<0xB908, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+ "agr\t{$dst, $src2}",
+ [(set GR64:$dst, (add GR64:$src1, GR64:$src2)),
+ (implicit PSW)]>;
+}
+
+def ADD32rm : RXI<0x5A, (outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+ "a\t{$dst, $src2}",
+ [(set GR32:$dst, (add GR32:$src1, (load rriaddr12:$src2))),
+ (implicit PSW)]>;
+def ADD32rmy : RXYI<0xE35A, (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+ "ay\t{$dst, $src2}",
+ [(set GR32:$dst, (add GR32:$src1, (load rriaddr:$src2))),
+ (implicit PSW)]>;
+def ADD64rm : RXYI<0xE308, (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+ "ag\t{$dst, $src2}",
+ [(set GR64:$dst, (add GR64:$src1, (load rriaddr:$src2))),
+ (implicit PSW)]>;
+
+
+def ADD32ri16 : RII<0xA7A,
+ (outs GR32:$dst), (ins GR32:$src1, s16imm:$src2),
+ "ahi\t{$dst, $src2}",
+ [(set GR32:$dst, (add GR32:$src1, immSExt16:$src2)),
+ (implicit PSW)]>;
+def ADD32ri : RILI<0xC29,
+ (outs GR32:$dst), (ins GR32:$src1, s32imm:$src2),
+ "afi\t{$dst, $src2}",
+ [(set GR32:$dst, (add GR32:$src1, imm:$src2)),
+ (implicit PSW)]>;
+def ADD64ri16 : RILI<0xA7B,
+ (outs GR64:$dst), (ins GR64:$src1, s16imm64:$src2),
+ "aghi\t{$dst, $src2}",
+ [(set GR64:$dst, (add GR64:$src1, immSExt16:$src2)),
+ (implicit PSW)]>;
+def ADD64ri32 : RILI<0xC28,
+ (outs GR64:$dst), (ins GR64:$src1, s32imm64:$src2),
+ "agfi\t{$dst, $src2}",
+ [(set GR64:$dst, (add GR64:$src1, immSExt32:$src2)),
+ (implicit PSW)]>;
+
+let isCommutable = 1 in { // X = ADC Y, Z == X = ADC Z, Y
+def ADC32rr : RRI<0x1E, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "alr\t{$dst, $src2}",
+ [(set GR32:$dst, (addc GR32:$src1, GR32:$src2))]>;
+def ADC64rr : RREI<0xB90A, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+ "algr\t{$dst, $src2}",
+ [(set GR64:$dst, (addc GR64:$src1, GR64:$src2))]>;
+}
+
+def ADC32ri : RILI<0xC2B,
+ (outs GR32:$dst), (ins GR32:$src1, s32imm:$src2),
+ "alfi\t{$dst, $src2}",
+ [(set GR32:$dst, (addc GR32:$src1, imm:$src2))]>;
+def ADC64ri32 : RILI<0xC2A,
+ (outs GR64:$dst), (ins GR64:$src1, s32imm64:$src2),
+ "algfi\t{$dst, $src2}",
+ [(set GR64:$dst, (addc GR64:$src1, immSExt32:$src2))]>;
+
+let Uses = [PSW] in {
+def ADDE32rr : RREI<0xB998, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "alcr\t{$dst, $src2}",
+ [(set GR32:$dst, (adde GR32:$src1, GR32:$src2)),
+ (implicit PSW)]>;
+def ADDE64rr : RREI<0xB988, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+ "alcgr\t{$dst, $src2}",
+ [(set GR64:$dst, (adde GR64:$src1, GR64:$src2)),
+ (implicit PSW)]>;
+}
+
+let isCommutable = 1 in { // X = AND Y, Z == X = AND Z, Y
+def AND32rr : RRI<0x14,
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "nr\t{$dst, $src2}",
+ [(set GR32:$dst, (and GR32:$src1, GR32:$src2))]>;
+def AND64rr : RREI<0xB980,
+ (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+ "ngr\t{$dst, $src2}",
+ [(set GR64:$dst, (and GR64:$src1, GR64:$src2))]>;
+}
+
+def AND32rm : RXI<0x54, (outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+ "n\t{$dst, $src2}",
+ [(set GR32:$dst, (and GR32:$src1, (load rriaddr12:$src2))),
+ (implicit PSW)]>;
+def AND32rmy : RXYI<0xE354, (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+ "ny\t{$dst, $src2}",
+ [(set GR32:$dst, (and GR32:$src1, (load rriaddr:$src2))),
+ (implicit PSW)]>;
+def AND64rm : RXYI<0xE360, (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+ "ng\t{$dst, $src2}",
+ [(set GR64:$dst, (and GR64:$src1, (load rriaddr:$src2))),
+ (implicit PSW)]>;
+
+def AND32rill16 : RII<0xA57,
+ (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
+ "nill\t{$dst, $src2}",
+ [(set GR32:$dst, (and GR32:$src1, i32ll16c:$src2))]>;
+def AND64rill16 : RII<0xA57,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "nill\t{$dst, $src2}",
+ [(set GR64:$dst, (and GR64:$src1, i64ll16c:$src2))]>;
+
+def AND32rilh16 : RII<0xA56,
+ (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
+ "nilh\t{$dst, $src2}",
+ [(set GR32:$dst, (and GR32:$src1, i32lh16c:$src2))]>;
+def AND64rilh16 : RII<0xA56,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "nilh\t{$dst, $src2}",
+ [(set GR64:$dst, (and GR64:$src1, i64lh16c:$src2))]>;
+
+def AND64rihl16 : RII<0xA55,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "nihl\t{$dst, $src2}",
+ [(set GR64:$dst, (and GR64:$src1, i64hl16c:$src2))]>;
+def AND64rihh16 : RII<0xA54,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "nihh\t{$dst, $src2}",
+ [(set GR64:$dst, (and GR64:$src1, i64hh16c:$src2))]>;
+
+def AND32ri : RILI<0xC0B,
+ (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
+ "nilf\t{$dst, $src2}",
+ [(set GR32:$dst, (and GR32:$src1, imm:$src2))]>;
+def AND64rilo32 : RILI<0xC0B,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "nilf\t{$dst, $src2}",
+ [(set GR64:$dst, (and GR64:$src1, i64lo32c:$src2))]>;
+def AND64rihi32 : RILI<0xC0A,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "nihf\t{$dst, $src2}",
+ [(set GR64:$dst, (and GR64:$src1, i64hi32c:$src2))]>;
+
+let isCommutable = 1 in { // X = OR Y, Z == X = OR Z, Y
+def OR32rr : RRI<0x16,
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "or\t{$dst, $src2}",
+ [(set GR32:$dst, (or GR32:$src1, GR32:$src2))]>;
+def OR64rr : RREI<0xB981,
+ (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+ "ogr\t{$dst, $src2}",
+ [(set GR64:$dst, (or GR64:$src1, GR64:$src2))]>;
+}
+
+def OR32rm : RXI<0x56, (outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+ "o\t{$dst, $src2}",
+ [(set GR32:$dst, (or GR32:$src1, (load rriaddr12:$src2))),
+ (implicit PSW)]>;
+def OR32rmy : RXYI<0xE356, (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+ "oy\t{$dst, $src2}",
+ [(set GR32:$dst, (or GR32:$src1, (load rriaddr:$src2))),
+ (implicit PSW)]>;
+def OR64rm : RXYI<0xE381, (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+ "og\t{$dst, $src2}",
+ [(set GR64:$dst, (or GR64:$src1, (load rriaddr:$src2))),
+ (implicit PSW)]>;
+
+ // FIXME: Provide proper encoding!
+def OR32ri16 : RII<0xA5B,
+ (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
+ "oill\t{$dst, $src2}",
+ [(set GR32:$dst, (or GR32:$src1, i32ll16:$src2))]>;
+def OR32ri16h : RII<0xA5A,
+ (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
+ "oilh\t{$dst, $src2}",
+ [(set GR32:$dst, (or GR32:$src1, i32lh16:$src2))]>;
+def OR32ri : RILI<0xC0D,
+ (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
+ "oilf\t{$dst, $src2}",
+ [(set GR32:$dst, (or GR32:$src1, imm:$src2))]>;
+
+def OR64rill16 : RII<0xA5B,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "oill\t{$dst, $src2}",
+ [(set GR64:$dst, (or GR64:$src1, i64ll16:$src2))]>;
+def OR64rilh16 : RII<0xA5A,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "oilh\t{$dst, $src2}",
+ [(set GR64:$dst, (or GR64:$src1, i64lh16:$src2))]>;
+def OR64rihl16 : RII<0xA59,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "oihl\t{$dst, $src2}",
+ [(set GR64:$dst, (or GR64:$src1, i64hl16:$src2))]>;
+def OR64rihh16 : RII<0xA58,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "oihh\t{$dst, $src2}",
+ [(set GR64:$dst, (or GR64:$src1, i64hh16:$src2))]>;
+
+def OR64rilo32 : RILI<0xC0D,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "oilf\t{$dst, $src2}",
+ [(set GR64:$dst, (or GR64:$src1, i64lo32:$src2))]>;
+def OR64rihi32 : RILI<0xC0C,
+ (outs GR64:$dst), (ins GR64:$src1, i64imm:$src2),
+ "oihf\t{$dst, $src2}",
+ [(set GR64:$dst, (or GR64:$src1, i64hi32:$src2))]>;
+
+def SUB32rr : RRI<0x1B,
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "sr\t{$dst, $src2}",
+ [(set GR32:$dst, (sub GR32:$src1, GR32:$src2))]>;
+def SUB64rr : RREI<0xB909,
+ (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+ "sgr\t{$dst, $src2}",
+ [(set GR64:$dst, (sub GR64:$src1, GR64:$src2))]>;
+
+def SUB32rm : RXI<0x5B, (outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+ "s\t{$dst, $src2}",
+ [(set GR32:$dst, (sub GR32:$src1, (load rriaddr12:$src2))),
+ (implicit PSW)]>;
+def SUB32rmy : RXYI<0xE35B, (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+ "sy\t{$dst, $src2}",
+ [(set GR32:$dst, (sub GR32:$src1, (load rriaddr:$src2))),
+ (implicit PSW)]>;
+def SUB64rm : RXYI<0xE309, (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+ "sg\t{$dst, $src2}",
+ [(set GR64:$dst, (sub GR64:$src1, (load rriaddr:$src2))),
+ (implicit PSW)]>;
+
+def SBC32rr : RRI<0x1F,
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "slr\t{$dst, $src2}",
+ [(set GR32:$dst, (subc GR32:$src1, GR32:$src2))]>;
+def SBC64rr : RREI<0xB90B,
+ (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+ "slgr\t{$dst, $src2}",
+ [(set GR64:$dst, (subc GR64:$src1, GR64:$src2))]>;
+
+def SBC32ri : RILI<0xC25,
+ (outs GR32:$dst), (ins GR32:$src1, s32imm:$src2),
+ "sllfi\t{$dst, $src2}",
+ [(set GR32:$dst, (subc GR32:$src1, imm:$src2))]>;
+def SBC64ri32 : RILI<0xC24,
+ (outs GR64:$dst), (ins GR64:$src1, s32imm64:$src2),
+ "slgfi\t{$dst, $src2}",
+ [(set GR64:$dst, (subc GR64:$src1, immSExt32:$src2))]>;
+
+let Uses = [PSW] in {
+def SUBE32rr : RREI<0xB999, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "slbr\t{$dst, $src2}",
+ [(set GR32:$dst, (sube GR32:$src1, GR32:$src2)),
+ (implicit PSW)]>;
+def SUBE64rr : RREI<0xB989, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+ "slbgr\t{$dst, $src2}",
+ [(set GR64:$dst, (sube GR64:$src1, GR64:$src2)),
+ (implicit PSW)]>;
+}
+
+let isCommutable = 1 in { // X = XOR Y, Z == X = XOR Z, Y
+def XOR32rr : RRI<0x17,
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "xr\t{$dst, $src2}",
+ [(set GR32:$dst, (xor GR32:$src1, GR32:$src2))]>;
+def XOR64rr : RREI<0xB982,
+ (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+ "xgr\t{$dst, $src2}",
+ [(set GR64:$dst, (xor GR64:$src1, GR64:$src2))]>;
+}
+
+def XOR32rm : RXI<0x57,(outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+ "x\t{$dst, $src2}",
+ [(set GR32:$dst, (xor GR32:$src1, (load rriaddr12:$src2))),
+ (implicit PSW)]>;
+def XOR32rmy : RXYI<0xE357, (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+ "xy\t{$dst, $src2}",
+ [(set GR32:$dst, (xor GR32:$src1, (load rriaddr:$src2))),
+ (implicit PSW)]>;
+def XOR64rm : RXYI<0xE382, (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+ "xg\t{$dst, $src2}",
+ [(set GR64:$dst, (xor GR64:$src1, (load rriaddr:$src2))),
+ (implicit PSW)]>;
+
+def XOR32ri : RILI<0xC07,
+ (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
+ "xilf\t{$dst, $src2}",
+ [(set GR32:$dst, (xor GR32:$src1, imm:$src2))]>;
+
+} // Defs = [PSW]
+
+let isCommutable = 1 in { // X = MUL Y, Z == X = MUL Z, Y
+def MUL32rr : RREI<0xB252,
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "msr\t{$dst, $src2}",
+ [(set GR32:$dst, (mul GR32:$src1, GR32:$src2))]>;
+def MUL64rr : RREI<0xB90C,
+ (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+ "msgr\t{$dst, $src2}",
+ [(set GR64:$dst, (mul GR64:$src1, GR64:$src2))]>;
+}
+
+def MUL64rrP : RRI<0x1C,
+ (outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2),
+ "mr\t{$dst, $src2}",
+ []>;
+def UMUL64rrP : RREI<0xB996,
+ (outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2),
+ "mlr\t{$dst, $src2}",
+ []>;
+def UMUL128rrP : RREI<0xB986,
+ (outs GR128:$dst), (ins GR128:$src1, GR64:$src2),
+ "mlgr\t{$dst, $src2}",
+ []>;
+
+def MUL32ri16 : RII<0xA7C,
+ (outs GR32:$dst), (ins GR32:$src1, s16imm:$src2),
+ "mhi\t{$dst, $src2}",
+ [(set GR32:$dst, (mul GR32:$src1, i32immSExt16:$src2))]>;
+def MUL64ri16 : RII<0xA7D,
+ (outs GR64:$dst), (ins GR64:$src1, s16imm64:$src2),
+ "mghi\t{$dst, $src2}",
+ [(set GR64:$dst, (mul GR64:$src1, immSExt16:$src2))]>;
+
+let AddedComplexity = 2 in {
+def MUL32ri : RILI<0xC21,
+ (outs GR32:$dst), (ins GR32:$src1, s32imm:$src2),
+ "msfi\t{$dst, $src2}",
+ [(set GR32:$dst, (mul GR32:$src1, imm:$src2))]>,
+ Requires<[IsZ10]>;
+def MUL64ri32 : RILI<0xC20,
+ (outs GR64:$dst), (ins GR64:$src1, s32imm64:$src2),
+ "msgfi\t{$dst, $src2}",
+ [(set GR64:$dst, (mul GR64:$src1, i64immSExt32:$src2))]>,
+ Requires<[IsZ10]>;
+}
+
+def MUL32rm : RXI<0x71,
+ (outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+ "ms\t{$dst, $src2}",
+ [(set GR32:$dst, (mul GR32:$src1, (load rriaddr12:$src2)))]>;
+def MUL32rmy : RXYI<0xE351,
+ (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+ "msy\t{$dst, $src2}",
+ [(set GR32:$dst, (mul GR32:$src1, (load rriaddr:$src2)))]>;
+def MUL64rm : RXYI<0xE30C,
+ (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+ "msg\t{$dst, $src2}",
+ [(set GR64:$dst, (mul GR64:$src1, (load rriaddr:$src2)))]>;
+
+def MULSX64rr32 : RREI<0xB91C,
+ (outs GR64:$dst), (ins GR64:$src1, GR32:$src2),
+ "msgfr\t{$dst, $src2}",
+ [(set GR64:$dst, (mul GR64:$src1, (sext GR32:$src2)))]>;
+
+def SDIVREM32r : RREI<0xB91D,
+ (outs GR128:$dst), (ins GR128:$src1, GR32:$src2),
+ "dsgfr\t{$dst, $src2}",
+ []>;
+def SDIVREM64r : RREI<0xB90D,
+ (outs GR128:$dst), (ins GR128:$src1, GR64:$src2),
+ "dsgr\t{$dst, $src2}",
+ []>;
+
+def UDIVREM32r : RREI<0xB997,
+ (outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2),
+ "dlr\t{$dst, $src2}",
+ []>;
+def UDIVREM64r : RREI<0xB987,
+ (outs GR128:$dst), (ins GR128:$src1, GR64:$src2),
+ "dlgr\t{$dst, $src2}",
+ []>;
+let mayLoad = 1 in {
+def SDIVREM32m : RXYI<0xE31D,
+ (outs GR128:$dst), (ins GR128:$src1, rriaddr:$src2),
+ "dsgf\t{$dst, $src2}",
+ []>;
+def SDIVREM64m : RXYI<0xE30D,
+ (outs GR128:$dst), (ins GR128:$src1, rriaddr:$src2),
+ "dsg\t{$dst, $src2}",
+ []>;
+
+def UDIVREM32m : RXYI<0xE397, (outs GR64P:$dst), (ins GR64P:$src1, rriaddr:$src2),
+ "dl\t{$dst, $src2}",
+ []>;
+def UDIVREM64m : RXYI<0xE387, (outs GR128:$dst), (ins GR128:$src1, rriaddr:$src2),
+ "dlg\t{$dst, $src2}",
+ []>;
+} // mayLoad
+} // isTwoAddress = 1
+
+//===----------------------------------------------------------------------===//
+// Shifts
+
+let isTwoAddress = 1 in
+def SRL32rri : RSI<0x88,
+ (outs GR32:$dst), (ins GR32:$src, riaddr32:$amt),
+ "srl\t{$src, $amt}",
+ [(set GR32:$dst, (srl GR32:$src, riaddr32:$amt))]>;
+def SRL64rri : RSYI<0xEB0C,
+ (outs GR64:$dst), (ins GR64:$src, riaddr:$amt),
+ "srlg\t{$dst, $src, $amt}",
+ [(set GR64:$dst, (srl GR64:$src, riaddr:$amt))]>;
+
+let isTwoAddress = 1 in
+def SHL32rri : RSI<0x89,
+ (outs GR32:$dst), (ins GR32:$src, riaddr32:$amt),
+ "sll\t{$src, $amt}",
+ [(set GR32:$dst, (shl GR32:$src, riaddr32:$amt))]>;
+def SHL64rri : RSYI<0xEB0D,
+ (outs GR64:$dst), (ins GR64:$src, riaddr:$amt),
+ "sllg\t{$dst, $src, $amt}",
+ [(set GR64:$dst, (shl GR64:$src, riaddr:$amt))]>;
+
+let Defs = [PSW] in {
+let isTwoAddress = 1 in
+def SRA32rri : RSI<0x8A,
+ (outs GR32:$dst), (ins GR32:$src, riaddr32:$amt),
+ "sra\t{$src, $amt}",
+ [(set GR32:$dst, (sra GR32:$src, riaddr32:$amt)),
+ (implicit PSW)]>;
+
+def SRA64rri : RSYI<0xEB0A,
+ (outs GR64:$dst), (ins GR64:$src, riaddr:$amt),
+ "srag\t{$dst, $src, $amt}",
+ [(set GR64:$dst, (sra GR64:$src, riaddr:$amt)),
+ (implicit PSW)]>;
+} // Defs = [PSW]
+
+def ROTL32rri : RSYI<0xEB1D,
+ (outs GR32:$dst), (ins GR32:$src, riaddr32:$amt),
+ "rll\t{$dst, $src, $amt}",
+ [(set GR32:$dst, (rotl GR32:$src, riaddr32:$amt))]>;
+def ROTL64rri : RSYI<0xEB1C,
+ (outs GR64:$dst), (ins GR64:$src, riaddr:$amt),
+ "rllg\t{$dst, $src, $amt}",
+ [(set GR64:$dst, (rotl GR64:$src, riaddr:$amt))]>;
+
+//===----------------------------------------------------------------------===//
+// Test instructions (like AND but do not produce any result)
+
+// Integer comparisons
+let Defs = [PSW] in {
+def CMP32rr : RRI<0x19,
+ (outs), (ins GR32:$src1, GR32:$src2),
+ "cr\t$src1, $src2",
+ [(set PSW, (SystemZcmp GR32:$src1, GR32:$src2))]>;
+def CMP64rr : RREI<0xB920,
+ (outs), (ins GR64:$src1, GR64:$src2),
+ "cgr\t$src1, $src2",
+ [(set PSW, (SystemZcmp GR64:$src1, GR64:$src2))]>;
+
+def CMP32ri : RILI<0xC2D,
+ (outs), (ins GR32:$src1, s32imm:$src2),
+ "cfi\t$src1, $src2",
+ [(set PSW, (SystemZcmp GR32:$src1, imm:$src2))]>;
+def CMP64ri32 : RILI<0xC2C,
+ (outs), (ins GR64:$src1, s32imm64:$src2),
+ "cgfi\t$src1, $src2",
+ [(set PSW, (SystemZcmp GR64:$src1, i64immSExt32:$src2))]>;
+
+def CMP32rm : RXI<0x59,
+ (outs), (ins GR32:$src1, rriaddr12:$src2),
+ "c\t$src1, $src2",
+ [(set PSW, (SystemZcmp GR32:$src1, (load rriaddr12:$src2)))]>;
+def CMP32rmy : RXYI<0xE359,
+ (outs), (ins GR32:$src1, rriaddr:$src2),
+ "cy\t$src1, $src2",
+ [(set PSW, (SystemZcmp GR32:$src1, (load rriaddr:$src2)))]>;
+def CMP64rm : RXYI<0xE320,
+ (outs), (ins GR64:$src1, rriaddr:$src2),
+ "cg\t$src1, $src2",
+ [(set PSW, (SystemZcmp GR64:$src1, (load rriaddr:$src2)))]>;
+
+def UCMP32rr : RRI<0x15,
+ (outs), (ins GR32:$src1, GR32:$src2),
+ "clr\t$src1, $src2",
+ [(set PSW, (SystemZucmp GR32:$src1, GR32:$src2))]>;
+def UCMP64rr : RREI<0xB921,
+ (outs), (ins GR64:$src1, GR64:$src2),
+ "clgr\t$src1, $src2",
+ [(set PSW, (SystemZucmp GR64:$src1, GR64:$src2))]>;
+
+def UCMP32ri : RILI<0xC2F,
+ (outs), (ins GR32:$src1, i32imm:$src2),
+ "clfi\t$src1, $src2",
+ [(set PSW, (SystemZucmp GR32:$src1, imm:$src2))]>;
+def UCMP64ri32 : RILI<0xC2E,
+ (outs), (ins GR64:$src1, i64i32imm:$src2),
+ "clgfi\t$src1, $src2",
+ [(set PSW,(SystemZucmp GR64:$src1, i64immZExt32:$src2))]>;
+
+def UCMP32rm : RXI<0x55,
+ (outs), (ins GR32:$src1, rriaddr12:$src2),
+ "cl\t$src1, $src2",
+ [(set PSW, (SystemZucmp GR32:$src1,
+ (load rriaddr12:$src2)))]>;
+def UCMP32rmy : RXYI<0xE355,
+ (outs), (ins GR32:$src1, rriaddr:$src2),
+ "cly\t$src1, $src2",
+ [(set PSW, (SystemZucmp GR32:$src1,
+ (load rriaddr:$src2)))]>;
+def UCMP64rm : RXYI<0xE351,
+ (outs), (ins GR64:$src1, rriaddr:$src2),
+ "clg\t$src1, $src2",
+ [(set PSW, (SystemZucmp GR64:$src1,
+ (load rriaddr:$src2)))]>;
+
+def CMPSX64rr32 : RREI<0xB930,
+ (outs), (ins GR64:$src1, GR32:$src2),
+ "cgfr\t$src1, $src2",
+ [(set PSW, (SystemZucmp GR64:$src1,
+ (sext GR32:$src2)))]>;
+def UCMPZX64rr32 : RREI<0xB931,
+ (outs), (ins GR64:$src1, GR32:$src2),
+ "clgfr\t$src1, $src2",
+ [(set PSW, (SystemZucmp GR64:$src1,
+ (zext GR32:$src2)))]>;
+
+def CMPSX64rm32 : RXYI<0xE330,
+ (outs), (ins GR64:$src1, rriaddr:$src2),
+ "cgf\t$src1, $src2",
+ [(set PSW, (SystemZucmp GR64:$src1,
+ (sextloadi64i32 rriaddr:$src2)))]>;
+def UCMPZX64rm32 : RXYI<0xE331,
+ (outs), (ins GR64:$src1, rriaddr:$src2),
+ "clgf\t$src1, $src2",
+ [(set PSW, (SystemZucmp GR64:$src1,
+ (zextloadi64i32 rriaddr:$src2)))]>;
+
+// FIXME: Add other crazy ucmp forms
+
+} // Defs = [PSW]
+
+//===----------------------------------------------------------------------===//
+// Other crazy stuff
+let Defs = [PSW] in {
+def FLOGR64 : RREI<0xB983,
+ (outs GR128:$dst), (ins GR64:$src),
+ "flogr\t{$dst, $src}",
+ []>;
+} // Defs = [PSW]
+
+//===----------------------------------------------------------------------===//
+// Non-Instruction Patterns.
+//===----------------------------------------------------------------------===//
+
+// ConstPools, JumpTables
+def : Pat<(SystemZpcrelwrapper tjumptable:$src), (LA64rm tjumptable:$src)>;
+def : Pat<(SystemZpcrelwrapper tconstpool:$src), (LA64rm tconstpool:$src)>;
+
+// anyext
+def : Pat<(i64 (anyext GR32:$src)),
+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, subreg_32bit)>;
+
+// calls
+def : Pat<(SystemZcall (i64 tglobaladdr:$dst)), (CALLi tglobaladdr:$dst)>;
+def : Pat<(SystemZcall (i64 texternalsym:$dst)), (CALLi texternalsym:$dst)>;
+
+//===----------------------------------------------------------------------===//
+// Peepholes.
+//===----------------------------------------------------------------------===//
+
+// FIXME: use add/sub tricks with 32678/-32768
+
+// Arbitrary immediate support.
+def : Pat<(i32 imm:$src),
+ (EXTRACT_SUBREG (MOV64ri32 (GetI64FromI32 (i32 imm:$src))),
+ subreg_32bit)>;
+
+// Implement in terms of LLIHF/OILF.
+def : Pat<(i64 imm:$imm),
+ (OR64rilo32 (MOV64rihi32 (HI32 imm:$imm)), (LO32 imm:$imm))>;
+
+// trunc patterns
+def : Pat<(i32 (trunc GR64:$src)),
+ (EXTRACT_SUBREG GR64:$src, subreg_32bit)>;
+
+// sext_inreg patterns
+def : Pat<(sext_inreg GR64:$src, i32),
+ (MOVSX64rr32 (EXTRACT_SUBREG GR64:$src, subreg_32bit))>;
+
+// extload patterns
+def : Pat<(extloadi32i8 rriaddr:$src), (MOVZX32rm8 rriaddr:$src)>;
+def : Pat<(extloadi32i16 rriaddr:$src), (MOVZX32rm16 rriaddr:$src)>;
+def : Pat<(extloadi64i8 rriaddr:$src), (MOVZX64rm8 rriaddr:$src)>;
+def : Pat<(extloadi64i16 rriaddr:$src), (MOVZX64rm16 rriaddr:$src)>;
+def : Pat<(extloadi64i32 rriaddr:$src), (MOVZX64rm32 rriaddr:$src)>;
+
+// muls
+def : Pat<(mulhs GR32:$src1, GR32:$src2),
+ (EXTRACT_SUBREG (MUL64rrP (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
+ GR32:$src1, subreg_odd32),
+ GR32:$src2),
+ subreg_even32)>;
+
+def : Pat<(mulhu GR32:$src1, GR32:$src2),
+ (EXTRACT_SUBREG (UMUL64rrP (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
+ GR32:$src1, subreg_odd32),
+ GR32:$src2),
+ subreg_even32)>;
+def : Pat<(mulhu GR64:$src1, GR64:$src2),
+ (EXTRACT_SUBREG (UMUL128rrP (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)),
+ GR64:$src1, subreg_odd),
+ GR64:$src2),
+ subreg_even)>;
+
+def : Pat<(ctlz GR64:$src),
+ (EXTRACT_SUBREG (FLOGR64 GR64:$src), subreg_even)>;
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZMCAsmInfo.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZMCAsmInfo.cpp
new file mode 100644
index 0000000..f9ccc47
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZMCAsmInfo.cpp
@@ -0,0 +1,29 @@
+//===-- SystemZMCAsmInfo.cpp - SystemZ asm properties ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declarations of the SystemZMCAsmInfo properties.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZMCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionELF.h"
+using namespace llvm;
+
+SystemZMCAsmInfo::SystemZMCAsmInfo(const Target &T, const StringRef &TT) {
+ PrivateGlobalPrefix = ".L";
+ WeakRefDirective = "\t.weak\t";
+ PCSymbol = ".";
+}
+
+const MCSection *SystemZMCAsmInfo::
+getNonexecutableStackSection(MCContext &Ctx) const{
+ return Ctx.getELFSection(".note.GNU-stack", MCSectionELF::SHT_PROGBITS,
+ 0, SectionKind::getMetadata(), false);
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZMCAsmInfo.h b/contrib/llvm/lib/Target/SystemZ/SystemZMCAsmInfo.h
new file mode 100644
index 0000000..87908f2
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZMCAsmInfo.h
@@ -0,0 +1,30 @@
+//====-- SystemZMCAsmInfo.h - SystemZ asm properties -----------*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the SystemZMCAsmInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SystemZTARGETASMINFO_H
+#define SystemZTARGETASMINFO_H
+
+#include "llvm/MC/MCAsmInfo.h"
+
+namespace llvm {
+ class Target;
+ class StringRef;
+
+ struct SystemZMCAsmInfo : public MCAsmInfo {
+ explicit SystemZMCAsmInfo(const Target &T, const StringRef &TT);
+ virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const;
+ };
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZMachineFunctionInfo.h b/contrib/llvm/lib/Target/SystemZ/SystemZMachineFunctionInfo.h
new file mode 100644
index 0000000..fd6e330
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZMachineFunctionInfo.h
@@ -0,0 +1,51 @@
+//==- SystemZMachineFuctionInfo.h - SystemZ machine function info -*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares SystemZ-specific per-machine-function information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SYSTEMZMACHINEFUNCTIONINFO_H
+#define SYSTEMZMACHINEFUNCTIONINFO_H
+
+#include "llvm/CodeGen/MachineFunction.h"
+
+namespace llvm {
+
+/// SystemZMachineFunctionInfo - This class is derived from MachineFunction and
+/// contains private SystemZ target-specific information for each MachineFunction.
+class SystemZMachineFunctionInfo : public MachineFunctionInfo {
+ /// CalleeSavedFrameSize - Size of the callee-saved register portion of the
+ /// stack frame in bytes.
+ unsigned CalleeSavedFrameSize;
+
+ /// LowReg - Low register of range of callee-saved registers to store.
+ unsigned LowReg;
+
+ /// HighReg - High register of range of callee-saved registers to store.
+ unsigned HighReg;
+public:
+ SystemZMachineFunctionInfo() : CalleeSavedFrameSize(0) {}
+
+ explicit SystemZMachineFunctionInfo(MachineFunction &MF)
+ : CalleeSavedFrameSize(0) {}
+
+ unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; }
+ void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; }
+
+ unsigned getLowReg() const { return LowReg; }
+ void setLowReg(unsigned Reg) { LowReg = Reg; }
+
+ unsigned getHighReg() const { return HighReg; }
+ void setHighReg(unsigned Reg) { HighReg = Reg; }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZOperands.td b/contrib/llvm/lib/Target/SystemZ/SystemZOperands.td
new file mode 100644
index 0000000..0de50fd
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZOperands.td
@@ -0,0 +1,310 @@
+//=====- SystemZOperands.td - SystemZ Operands defs ---------*- tblgen-*-=====//
+//
+// 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 various SystemZ instruction operands.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instruction Pattern Stuff.
+//===----------------------------------------------------------------------===//
+
+// SystemZ specific condition code. These correspond to CondCode in
+// SystemZ.h. They must be kept in synch.
+def SYSTEMZ_COND_O : PatLeaf<(i8 0)>;
+def SYSTEMZ_COND_H : PatLeaf<(i8 1)>;
+def SYSTEMZ_COND_NLE : PatLeaf<(i8 2)>;
+def SYSTEMZ_COND_L : PatLeaf<(i8 3)>;
+def SYSTEMZ_COND_NHE : PatLeaf<(i8 4)>;
+def SYSTEMZ_COND_LH : PatLeaf<(i8 5)>;
+def SYSTEMZ_COND_NE : PatLeaf<(i8 6)>;
+def SYSTEMZ_COND_E : PatLeaf<(i8 7)>;
+def SYSTEMZ_COND_NLH : PatLeaf<(i8 8)>;
+def SYSTEMZ_COND_HE : PatLeaf<(i8 9)>;
+def SYSTEMZ_COND_NL : PatLeaf<(i8 10)>;
+def SYSTEMZ_COND_LE : PatLeaf<(i8 11)>;
+def SYSTEMZ_COND_NH : PatLeaf<(i8 12)>;
+def SYSTEMZ_COND_NO : PatLeaf<(i8 13)>;
+
+def LO8 : SDNodeXForm<imm, [{
+ // Transformation function: return low 8 bits.
+ return getI8Imm(N->getZExtValue() & 0x00000000000000FFULL);
+}]>;
+
+def LL16 : SDNodeXForm<imm, [{
+ // Transformation function: return low 16 bits.
+ return getI16Imm(N->getZExtValue() & 0x000000000000FFFFULL);
+}]>;
+
+def LH16 : SDNodeXForm<imm, [{
+ // Transformation function: return bits 16-31.
+ return getI16Imm((N->getZExtValue() & 0x00000000FFFF0000ULL) >> 16);
+}]>;
+
+def HL16 : SDNodeXForm<imm, [{
+ // Transformation function: return bits 32-47.
+ return getI16Imm((N->getZExtValue() & 0x0000FFFF00000000ULL) >> 32);
+}]>;
+
+def HH16 : SDNodeXForm<imm, [{
+ // Transformation function: return bits 48-63.
+ return getI16Imm((N->getZExtValue() & 0xFFFF000000000000ULL) >> 48);
+}]>;
+
+def LO32 : SDNodeXForm<imm, [{
+ // Transformation function: return low 32 bits.
+ return getI32Imm(N->getZExtValue() & 0x00000000FFFFFFFFULL);
+}]>;
+
+def HI32 : SDNodeXForm<imm, [{
+ // Transformation function: return bits 32-63.
+ return getI32Imm(N->getZExtValue() >> 32);
+}]>;
+
+def GetI64FromI32 : SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant(N->getSExtValue(), MVT::i64);
+}]>;
+
+def i32ll16 : PatLeaf<(i32 imm), [{
+ // i32ll16 predicate - true if the 32-bit immediate has only rightmost 16
+ // bits set.
+ return ((N->getZExtValue() & 0x000000000000FFFFULL) == N->getZExtValue());
+}], LL16>;
+
+def i32lh16 : PatLeaf<(i32 imm), [{
+ // i32lh16 predicate - true if the 32-bit immediate has only bits 16-31 set.
+ return ((N->getZExtValue() & 0x00000000FFFF0000ULL) == N->getZExtValue());
+}], LH16>;
+
+def i32ll16c : PatLeaf<(i32 imm), [{
+ // i32ll16c predicate - true if the 32-bit immediate has all bits 16-31 set.
+ return ((N->getZExtValue() | 0x00000000FFFF0000ULL) == N->getZExtValue());
+}], LL16>;
+
+def i32lh16c : PatLeaf<(i32 imm), [{
+ // i32lh16c predicate - true if the 32-bit immediate has all rightmost 16
+ // bits set.
+ return ((N->getZExtValue() | 0x000000000000FFFFULL) == N->getZExtValue());
+}], LH16>;
+
+def i64ll16 : PatLeaf<(i64 imm), [{
+ // i64ll16 predicate - true if the 64-bit immediate has only rightmost 16
+ // bits set.
+ return ((N->getZExtValue() & 0x000000000000FFFFULL) == N->getZExtValue());
+}], LL16>;
+
+def i64lh16 : PatLeaf<(i64 imm), [{
+ // i64lh16 predicate - true if the 64-bit immediate has only bits 16-31 set.
+ return ((N->getZExtValue() & 0x00000000FFFF0000ULL) == N->getZExtValue());
+}], LH16>;
+
+def i64hl16 : PatLeaf<(i64 imm), [{
+ // i64hl16 predicate - true if the 64-bit immediate has only bits 32-47 set.
+ return ((N->getZExtValue() & 0x0000FFFF00000000ULL) == N->getZExtValue());
+}], HL16>;
+
+def i64hh16 : PatLeaf<(i64 imm), [{
+ // i64hh16 predicate - true if the 64-bit immediate has only bits 48-63 set.
+ return ((N->getZExtValue() & 0xFFFF000000000000ULL) == N->getZExtValue());
+}], HH16>;
+
+def i64ll16c : PatLeaf<(i64 imm), [{
+ // i64ll16c predicate - true if the 64-bit immediate has only rightmost 16
+ // bits set.
+ return ((N->getZExtValue() | 0xFFFFFFFFFFFF0000ULL) == N->getZExtValue());
+}], LL16>;
+
+def i64lh16c : PatLeaf<(i64 imm), [{
+ // i64lh16c predicate - true if the 64-bit immediate has only bits 16-31 set.
+ return ((N->getZExtValue() | 0xFFFFFFFF0000FFFFULL) == N->getZExtValue());
+}], LH16>;
+
+def i64hl16c : PatLeaf<(i64 imm), [{
+ // i64hl16c predicate - true if the 64-bit immediate has only bits 32-47 set.
+ return ((N->getZExtValue() | 0xFFFF0000FFFFFFFFULL) == N->getZExtValue());
+}], HL16>;
+
+def i64hh16c : PatLeaf<(i64 imm), [{
+ // i64hh16c predicate - true if the 64-bit immediate has only bits 48-63 set.
+ return ((N->getZExtValue() | 0x0000FFFFFFFFFFFFULL) == N->getZExtValue());
+}], HH16>;
+
+def immSExt16 : PatLeaf<(imm), [{
+ // immSExt16 predicate - true if the immediate fits in a 16-bit sign extended
+ // field.
+ if (N->getValueType(0) == MVT::i64) {
+ uint64_t val = N->getZExtValue();
+ return ((int64_t)val == (int16_t)val);
+ } else if (N->getValueType(0) == MVT::i32) {
+ uint32_t val = N->getZExtValue();
+ return ((int32_t)val == (int16_t)val);
+ }
+
+ return false;
+}], LL16>;
+
+def immSExt32 : PatLeaf<(i64 imm), [{
+ // immSExt32 predicate - true if the immediate fits in a 32-bit sign extended
+ // field.
+ uint64_t val = N->getZExtValue();
+ return ((int64_t)val == (int32_t)val);
+}], LO32>;
+
+def i64lo32 : PatLeaf<(i64 imm), [{
+ // i64lo32 predicate - true if the 64-bit immediate has only rightmost 32
+ // bits set.
+ return ((N->getZExtValue() & 0x00000000FFFFFFFFULL) == N->getZExtValue());
+}], LO32>;
+
+def i64hi32 : PatLeaf<(i64 imm), [{
+ // i64hi32 predicate - true if the 64-bit immediate has only bits 32-63 set.
+ return ((N->getZExtValue() & 0xFFFFFFFF00000000ULL) == N->getZExtValue());
+}], HI32>;
+
+def i64lo32c : PatLeaf<(i64 imm), [{
+ // i64lo32 predicate - true if the 64-bit immediate has only rightmost 32
+ // bits set.
+ return ((N->getZExtValue() | 0xFFFFFFFF00000000ULL) == N->getZExtValue());
+}], LO32>;
+
+def i64hi32c : PatLeaf<(i64 imm), [{
+ // i64hi32 predicate - true if the 64-bit immediate has only bits 32-63 set.
+ return ((N->getZExtValue() | 0x00000000FFFFFFFFULL) == N->getZExtValue());
+}], HI32>;
+
+def i32immSExt8 : PatLeaf<(i32 imm), [{
+ // i32immSExt8 predicate - True if the 32-bit immediate fits in a 8-bit
+ // sign extended field.
+ return (int32_t)N->getZExtValue() == (int8_t)N->getZExtValue();
+}], LO8>;
+
+def i32immSExt16 : PatLeaf<(i32 imm), [{
+ // i32immSExt16 predicate - True if the 32-bit immediate fits in a 16-bit
+ // sign extended field.
+ return (int32_t)N->getZExtValue() == (int16_t)N->getZExtValue();
+}], LL16>;
+
+def i64immSExt32 : PatLeaf<(i64 imm), [{
+ // i64immSExt32 predicate - True if the 64-bit immediate fits in a 32-bit
+ // sign extended field.
+ return (int64_t)N->getZExtValue() == (int32_t)N->getZExtValue();
+}], LO32>;
+
+def i64immZExt32 : PatLeaf<(i64 imm), [{
+ // i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit
+ // zero extended field.
+ return (uint64_t)N->getZExtValue() == (uint32_t)N->getZExtValue();
+}], LO32>;
+
+// extloads
+def extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>;
+def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>;
+def extloadi64i8 : PatFrag<(ops node:$ptr), (i64 (extloadi8 node:$ptr))>;
+def extloadi64i16 : PatFrag<(ops node:$ptr), (i64 (extloadi16 node:$ptr))>;
+def extloadi64i32 : PatFrag<(ops node:$ptr), (i64 (extloadi32 node:$ptr))>;
+
+def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>;
+def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>;
+def sextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (sextloadi8 node:$ptr))>;
+def sextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (sextloadi16 node:$ptr))>;
+def sextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (sextloadi32 node:$ptr))>;
+
+def zextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>;
+def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>;
+def zextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (zextloadi8 node:$ptr))>;
+def zextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (zextloadi16 node:$ptr))>;
+def zextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (zextloadi32 node:$ptr))>;
+
+// A couple of more descriptive operand definitions.
+// 32-bits but only 8 bits are significant.
+def i32i8imm : Operand<i32>;
+// 32-bits but only 16 bits are significant.
+def i32i16imm : Operand<i32>;
+// 64-bits but only 32 bits are significant.
+def i64i32imm : Operand<i64>;
+// Branch targets have OtherVT type.
+def brtarget : Operand<OtherVT>;
+
+// Unsigned i12
+def u12imm : Operand<i32> {
+ let PrintMethod = "printU12ImmOperand";
+}
+def u12imm64 : Operand<i64> {
+ let PrintMethod = "printU12ImmOperand";
+}
+
+// Signed i16
+def s16imm : Operand<i32> {
+ let PrintMethod = "printS16ImmOperand";
+}
+def s16imm64 : Operand<i64> {
+ let PrintMethod = "printS16ImmOperand";
+}
+// Signed i20
+def s20imm : Operand<i32> {
+ let PrintMethod = "printS20ImmOperand";
+}
+def s20imm64 : Operand<i64> {
+ let PrintMethod = "printS20ImmOperand";
+}
+// Signed i32
+def s32imm : Operand<i32> {
+ let PrintMethod = "printS32ImmOperand";
+}
+def s32imm64 : Operand<i64> {
+ let PrintMethod = "printS32ImmOperand";
+}
+
+def imm_pcrel : Operand<i64> {
+ let PrintMethod = "printPCRelImmOperand";
+}
+
+//===----------------------------------------------------------------------===//
+// SystemZ Operand Definitions.
+//===----------------------------------------------------------------------===//
+
+// Address operands
+
+// riaddr := reg + imm
+def riaddr32 : Operand<i64>,
+ ComplexPattern<i64, 2, "SelectAddrRI12Only", []> {
+ let PrintMethod = "printRIAddrOperand";
+ let MIOperandInfo = (ops ADDR64:$base, u12imm:$disp);
+}
+
+def riaddr12 : Operand<i64>,
+ ComplexPattern<i64, 2, "SelectAddrRI12", []> {
+ let PrintMethod = "printRIAddrOperand";
+ let MIOperandInfo = (ops ADDR64:$base, u12imm64:$disp);
+}
+
+def riaddr : Operand<i64>,
+ ComplexPattern<i64, 2, "SelectAddrRI", []> {
+ let PrintMethod = "printRIAddrOperand";
+ let MIOperandInfo = (ops ADDR64:$base, s20imm64:$disp);
+}
+
+//===----------------------------------------------------------------------===//
+
+// rriaddr := reg + reg + imm
+def rriaddr12 : Operand<i64>,
+ ComplexPattern<i64, 3, "SelectAddrRRI12", [], []> {
+ let PrintMethod = "printRRIAddrOperand";
+ let MIOperandInfo = (ops ADDR64:$base, u12imm64:$disp, ADDR64:$index);
+}
+def rriaddr : Operand<i64>,
+ ComplexPattern<i64, 3, "SelectAddrRRI20", [], []> {
+ let PrintMethod = "printRRIAddrOperand";
+ let MIOperandInfo = (ops ADDR64:$base, s20imm64:$disp, ADDR64:$index);
+}
+def laaddr : Operand<i64>,
+ ComplexPattern<i64, 3, "SelectLAAddr", [add, sub, or, frameindex], []> {
+ let PrintMethod = "printRRIAddrOperand";
+ let MIOperandInfo = (ops ADDR64:$base, s20imm64:$disp, ADDR64:$index);
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
new file mode 100644
index 0000000..638fd17
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -0,0 +1,343 @@
+//===- SystemZRegisterInfo.cpp - SystemZ Register Information -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SystemZ implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZ.h"
+#include "SystemZInstrInfo.h"
+#include "SystemZMachineFunctionInfo.h"
+#include "SystemZRegisterInfo.h"
+#include "SystemZSubtarget.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/ADT/BitVector.h"
+using namespace llvm;
+
+SystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm,
+ const SystemZInstrInfo &tii)
+ : SystemZGenRegisterInfo(SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN),
+ TM(tm), TII(tii) {
+}
+
+const unsigned*
+SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
+ static const unsigned CalleeSavedRegs[] = {
+ SystemZ::R6D, SystemZ::R7D, SystemZ::R8D, SystemZ::R9D,
+ SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D,
+ SystemZ::R14D, SystemZ::R15D,
+ SystemZ::F8L, SystemZ::F9L, SystemZ::F10L, SystemZ::F11L,
+ SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L,
+ 0
+ };
+
+ return CalleeSavedRegs;
+}
+
+const TargetRegisterClass* const*
+SystemZRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
+ static const TargetRegisterClass * const CalleeSavedRegClasses[] = {
+ &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
+ &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
+ &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
+ &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
+ &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
+ &SystemZ::FP64RegClass, &SystemZ::FP64RegClass,
+ &SystemZ::FP64RegClass, &SystemZ::FP64RegClass,
+ &SystemZ::FP64RegClass, &SystemZ::FP64RegClass,
+ &SystemZ::FP64RegClass, &SystemZ::FP64RegClass, 0
+ };
+ return CalleeSavedRegClasses;
+}
+
+BitVector SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
+ BitVector Reserved(getNumRegs());
+ if (hasFP(MF))
+ Reserved.set(SystemZ::R11D);
+ Reserved.set(SystemZ::R14D);
+ Reserved.set(SystemZ::R15D);
+ return Reserved;
+}
+
+/// needsFP - Return true if the specified function should have a dedicated
+/// frame pointer register. This is true if the function has variable sized
+/// allocas or if frame pointer elimination is disabled.
+bool SystemZRegisterInfo::hasFP(const MachineFunction &MF) const {
+ const MachineFrameInfo *MFI = MF.getFrameInfo();
+ return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects();
+}
+
+void SystemZRegisterInfo::
+eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const {
+ MBB.erase(I);
+}
+
+int SystemZRegisterInfo::getFrameIndexOffset(const MachineFunction &MF,
+ int FI) const {
+ const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
+ const MachineFrameInfo *MFI = MF.getFrameInfo();
+ const SystemZMachineFunctionInfo *SystemZMFI =
+ MF.getInfo<SystemZMachineFunctionInfo>();
+ int Offset = MFI->getObjectOffset(FI) + MFI->getOffsetAdjustment();
+ uint64_t StackSize = MFI->getStackSize();
+
+ // Fixed objects are really located in the "previous" frame.
+ if (FI < 0)
+ StackSize -= SystemZMFI->getCalleeSavedFrameSize();
+
+ Offset += StackSize - TFI.getOffsetOfLocalArea();
+
+ // Skip the register save area if we generated the stack frame.
+ if (StackSize || MFI->hasCalls())
+ Offset -= TFI.getOffsetOfLocalArea();
+
+ return Offset;
+}
+
+unsigned
+SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
+ int SPAdj, FrameIndexValue *Value,
+ RegScavenger *RS) const {
+ assert(SPAdj == 0 && "Unxpected");
+
+ unsigned i = 0;
+ MachineInstr &MI = *II;
+ MachineFunction &MF = *MI.getParent()->getParent();
+ while (!MI.getOperand(i).isFI()) {
+ ++i;
+ assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
+ }
+
+ int FrameIndex = MI.getOperand(i).getIndex();
+
+ unsigned BasePtr = (hasFP(MF) ? SystemZ::R11D : SystemZ::R15D);
+
+ // This must be part of a rri or ri operand memory reference. Replace the
+ // FrameIndex with base register with BasePtr. Add an offset to the
+ // displacement field.
+ MI.getOperand(i).ChangeToRegister(BasePtr, false);
+
+ // Offset is a either 12-bit unsigned or 20-bit signed integer.
+ // FIXME: handle "too long" displacements.
+ int Offset = getFrameIndexOffset(MF, FrameIndex) + MI.getOperand(i+1).getImm();
+
+ // Check whether displacement is too long to fit into 12 bit zext field.
+ MI.setDesc(TII.getMemoryInstr(MI.getOpcode(), Offset));
+
+ MI.getOperand(i+1).ChangeToImmediate(Offset);
+ return 0;
+}
+
+void
+SystemZRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
+ RegScavenger *RS) const {
+ // Determine whether R15/R14 will ever be clobbered inside the function. And
+ // if yes - mark it as 'callee' saved.
+ MachineFrameInfo *FFI = MF.getFrameInfo();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+
+ // Check whether high FPRs are ever used, if yes - we need to save R15 as
+ // well.
+ static const unsigned HighFPRs[] = {
+ SystemZ::F8L, SystemZ::F9L, SystemZ::F10L, SystemZ::F11L,
+ SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L,
+ SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S,
+ SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S,
+ };
+
+ bool HighFPRsUsed = false;
+ for (unsigned i = 0, e = array_lengthof(HighFPRs); i != e; ++i)
+ HighFPRsUsed |= MRI.isPhysRegUsed(HighFPRs[i]);
+
+ if (FFI->hasCalls())
+ /* FIXME: function is varargs */
+ /* FIXME: function grabs RA */
+ /* FIXME: function calls eh_return */
+ MRI.setPhysRegUsed(SystemZ::R14D);
+
+ if (HighFPRsUsed ||
+ FFI->hasCalls() ||
+ FFI->getObjectIndexEnd() != 0 || // Contains automatic variables
+ FFI->hasVarSizedObjects() // Function calls dynamic alloca's
+ /* FIXME: function is varargs */)
+ MRI.setPhysRegUsed(SystemZ::R15D);
+}
+
+/// emitSPUpdate - Emit a series of instructions to increment / decrement the
+/// stack pointer by a constant value.
+static
+void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
+ int64_t NumBytes, const TargetInstrInfo &TII) {
+ unsigned Opc; uint64_t Chunk;
+ bool isSub = NumBytes < 0;
+ uint64_t Offset = isSub ? -NumBytes : NumBytes;
+
+ if (Offset >= (1LL << 15) - 1) {
+ Opc = SystemZ::ADD64ri32;
+ Chunk = (1LL << 31) - 1;
+ } else {
+ Opc = SystemZ::ADD64ri16;
+ Chunk = (1LL << 15) - 1;
+ }
+
+ DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
+
+ while (Offset) {
+ uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
+ MachineInstr *MI =
+ BuildMI(MBB, MBBI, DL, TII.get(Opc), SystemZ::R15D)
+ .addReg(SystemZ::R15D).addImm(isSub ? -ThisVal : ThisVal);
+ // The PSW implicit def is dead.
+ MI->getOperand(3).setIsDead();
+ Offset -= ThisVal;
+ }
+}
+
+void SystemZRegisterInfo::emitPrologue(MachineFunction &MF) const {
+ MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
+ const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ SystemZMachineFunctionInfo *SystemZMFI =
+ MF.getInfo<SystemZMachineFunctionInfo>();
+ MachineBasicBlock::iterator MBBI = MBB.begin();
+ DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
+
+ // Get the number of bytes to allocate from the FrameInfo.
+ // Note that area for callee-saved stuff is already allocated, thus we need to
+ // 'undo' the stack movement.
+ uint64_t StackSize = MFI->getStackSize();
+ StackSize -= SystemZMFI->getCalleeSavedFrameSize();
+
+ uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
+
+ // Skip the callee-saved push instructions.
+ while (MBBI != MBB.end() &&
+ (MBBI->getOpcode() == SystemZ::MOV64mr ||
+ MBBI->getOpcode() == SystemZ::MOV64mrm))
+ ++MBBI;
+
+ if (MBBI != MBB.end())
+ DL = MBBI->getDebugLoc();
+
+ // adjust stack pointer: R15 -= numbytes
+ if (StackSize || MFI->hasCalls()) {
+ assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
+ "Invalid stack frame calculation!");
+ emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, TII);
+ }
+
+ if (hasFP(MF)) {
+ // Update R11 with the new base value...
+ BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D)
+ .addReg(SystemZ::R15D);
+
+ // Mark the FramePtr as live-in in every block except the entry.
+ for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
+ I != E; ++I)
+ I->addLiveIn(SystemZ::R11D);
+
+ }
+}
+
+void SystemZRegisterInfo::emitEpilogue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const {
+ const MachineFrameInfo *MFI = MF.getFrameInfo();
+ const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
+ MachineBasicBlock::iterator MBBI = prior(MBB.end());
+ SystemZMachineFunctionInfo *SystemZMFI =
+ MF.getInfo<SystemZMachineFunctionInfo>();
+ unsigned RetOpcode = MBBI->getOpcode();
+
+ switch (RetOpcode) {
+ case SystemZ::RET: break; // These are ok
+ default:
+ assert(0 && "Can only insert epilog into returning blocks");
+ }
+
+ // Get the number of bytes to allocate from the FrameInfo
+ // Note that area for callee-saved stuff is already allocated, thus we need to
+ // 'undo' the stack movement.
+ uint64_t StackSize =
+ MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
+ uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
+
+ // Skip the final terminator instruction.
+ while (MBBI != MBB.begin()) {
+ MachineBasicBlock::iterator PI = prior(MBBI);
+ --MBBI;
+ if (!PI->getDesc().isTerminator())
+ break;
+ }
+
+ // During callee-saved restores emission stack frame was not yet finialized
+ // (and thus - the stack size was unknown). Tune the offset having full stack
+ // size in hands.
+ if (StackSize || MFI->hasCalls()) {
+ assert((MBBI->getOpcode() == SystemZ::MOV64rmm ||
+ MBBI->getOpcode() == SystemZ::MOV64rm) &&
+ "Expected to see callee-save register restore code");
+ assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
+ "Invalid stack frame calculation!");
+
+ unsigned i = 0;
+ MachineInstr &MI = *MBBI;
+ while (!MI.getOperand(i).isImm()) {
+ ++i;
+ assert(i < MI.getNumOperands() && "Unexpected restore code!");
+ }
+
+ uint64_t Offset = NumBytes + MI.getOperand(i).getImm();
+ // If Offset does not fit into 20-bit signed displacement field we need to
+ // emit some additional code...
+ if (Offset > 524287) {
+ // Fold the displacement into load instruction as much as possible.
+ NumBytes = Offset - 524287;
+ Offset = 524287;
+ emitSPUpdate(MBB, MBBI, NumBytes, TII);
+ }
+
+ MI.getOperand(i).ChangeToImmediate(Offset);
+ }
+}
+
+unsigned SystemZRegisterInfo::getRARegister() const {
+ assert(0 && "What is the return address register");
+ return 0;
+}
+
+unsigned
+SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
+ assert(0 && "What is the frame register");
+ return 0;
+}
+
+unsigned SystemZRegisterInfo::getEHExceptionRegister() const {
+ assert(0 && "What is the exception register");
+ return 0;
+}
+
+unsigned SystemZRegisterInfo::getEHHandlerRegister() const {
+ assert(0 && "What is the exception handler register");
+ return 0;
+}
+
+int SystemZRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
+ assert(0 && "What is the dwarf register number");
+ return -1;
+}
+
+#include "SystemZGenRegisterInfo.inc"
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h b/contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
new file mode 100644
index 0000000..42aa5dd
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
@@ -0,0 +1,73 @@
+//===-- SystemZRegisterInfo.h - SystemZ Register Information ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SystemZ implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SystemZREGISTERINFO_H
+#define SystemZREGISTERINFO_H
+
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "SystemZGenRegisterInfo.h.inc"
+
+namespace llvm {
+
+class SystemZSubtarget;
+class SystemZInstrInfo;
+class Type;
+
+struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
+ SystemZTargetMachine &TM;
+ const SystemZInstrInfo &TII;
+
+ SystemZRegisterInfo(SystemZTargetMachine &tm, const SystemZInstrInfo &tii);
+
+ /// Code Generation virtual methods...
+ const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const;
+
+ const TargetRegisterClass* const* getCalleeSavedRegClasses(
+ const MachineFunction *MF = 0) const;
+
+ BitVector getReservedRegs(const MachineFunction &MF) const;
+
+ bool hasReservedCallFrame(MachineFunction &MF) const { return true; }
+ bool hasFP(const MachineFunction &MF) const;
+
+ int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
+
+ void eliminateCallFramePseudoInstr(MachineFunction &MF,
+ MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const;
+
+ unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
+ int SPAdj, FrameIndexValue *Value = NULL,
+ RegScavenger *RS = NULL) const;
+
+
+ void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
+ RegScavenger *RS) const;
+
+ void emitPrologue(MachineFunction &MF) const;
+ void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
+
+ // Debug information queries.
+ unsigned getRARegister() const;
+ unsigned getFrameRegister(const MachineFunction &MF) const;
+
+ // Exception handling queries.
+ unsigned getEHExceptionRegister() const;
+ unsigned getEHHandlerRegister() const;
+
+ int getDwarfRegNum(unsigned RegNum, bool isEH) const;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td b/contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
new file mode 100644
index 0000000..b561744
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
@@ -0,0 +1,480 @@
+//===- SystemZRegisterInfo.td - The PowerPC Register File ------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+class SystemZReg<string n> : Register<n> {
+ let Namespace = "SystemZ";
+}
+
+class SystemZRegWithSubregs<string n, list<Register> subregs>
+ : RegisterWithSubRegs<n, subregs> {
+ let Namespace = "SystemZ";
+}
+
+// We identify all our registers with a 4-bit ID, for consistency's sake.
+
+// GPR32 - Lower 32 bits of one of the 16 64-bit general-purpose registers
+class GPR32<bits<4> num, string n> : SystemZReg<n> {
+ field bits<4> Num = num;
+}
+
+// GPR64 - One of the 16 64-bit general-purpose registers
+class GPR64<bits<4> num, string n, list<Register> subregs,
+ list<Register> aliases = []>
+ : SystemZRegWithSubregs<n, subregs> {
+ field bits<4> Num = num;
+ let Aliases = aliases;
+}
+
+// GPR128 - 8 even-odd register pairs
+class GPR128<bits<4> num, string n, list<Register> subregs,
+ list<Register> aliases = []>
+ : SystemZRegWithSubregs<n, subregs> {
+ field bits<4> Num = num;
+ let Aliases = aliases;
+}
+
+// FPRS - Lower 32 bits of one of the 16 64-bit floating-point registers
+class FPRS<bits<4> num, string n> : SystemZReg<n> {
+ field bits<4> Num = num;
+}
+
+// FPRL - One of the 16 64-bit floating-point registers
+class FPRL<bits<4> num, string n, list<Register> subregs>
+ : SystemZRegWithSubregs<n, subregs> {
+ field bits<4> Num = num;
+}
+
+let Namespace = "SystemZ" in {
+def subreg_32bit : SubRegIndex;
+def subreg_even32 : SubRegIndex;
+def subreg_odd32 : SubRegIndex;
+def subreg_even : SubRegIndex;
+def subreg_odd : SubRegIndex;
+}
+
+// General-purpose registers
+def R0W : GPR32< 0, "r0">, DwarfRegNum<[0]>;
+def R1W : GPR32< 1, "r1">, DwarfRegNum<[1]>;
+def R2W : GPR32< 2, "r2">, DwarfRegNum<[2]>;
+def R3W : GPR32< 3, "r3">, DwarfRegNum<[3]>;
+def R4W : GPR32< 4, "r4">, DwarfRegNum<[4]>;
+def R5W : GPR32< 5, "r5">, DwarfRegNum<[5]>;
+def R6W : GPR32< 6, "r6">, DwarfRegNum<[6]>;
+def R7W : GPR32< 7, "r7">, DwarfRegNum<[7]>;
+def R8W : GPR32< 8, "r8">, DwarfRegNum<[8]>;
+def R9W : GPR32< 9, "r9">, DwarfRegNum<[9]>;
+def R10W : GPR32<10, "r10">, DwarfRegNum<[10]>;
+def R11W : GPR32<11, "r11">, DwarfRegNum<[11]>;
+def R12W : GPR32<12, "r12">, DwarfRegNum<[12]>;
+def R13W : GPR32<13, "r13">, DwarfRegNum<[13]>;
+def R14W : GPR32<14, "r14">, DwarfRegNum<[14]>;
+def R15W : GPR32<15, "r15">, DwarfRegNum<[15]>;
+
+let SubRegIndices = [subreg_32bit] in {
+def R0D : GPR64< 0, "r0", [R0W]>, DwarfRegNum<[0]>;
+def R1D : GPR64< 1, "r1", [R1W]>, DwarfRegNum<[1]>;
+def R2D : GPR64< 2, "r2", [R2W]>, DwarfRegNum<[2]>;
+def R3D : GPR64< 3, "r3", [R3W]>, DwarfRegNum<[3]>;
+def R4D : GPR64< 4, "r4", [R4W]>, DwarfRegNum<[4]>;
+def R5D : GPR64< 5, "r5", [R5W]>, DwarfRegNum<[5]>;
+def R6D : GPR64< 6, "r6", [R6W]>, DwarfRegNum<[6]>;
+def R7D : GPR64< 7, "r7", [R7W]>, DwarfRegNum<[7]>;
+def R8D : GPR64< 8, "r8", [R8W]>, DwarfRegNum<[8]>;
+def R9D : GPR64< 9, "r9", [R9W]>, DwarfRegNum<[9]>;
+def R10D : GPR64<10, "r10", [R10W]>, DwarfRegNum<[10]>;
+def R11D : GPR64<11, "r11", [R11W]>, DwarfRegNum<[11]>;
+def R12D : GPR64<12, "r12", [R12W]>, DwarfRegNum<[12]>;
+def R13D : GPR64<13, "r13", [R13W]>, DwarfRegNum<[13]>;
+def R14D : GPR64<14, "r14", [R14W]>, DwarfRegNum<[14]>;
+def R15D : GPR64<15, "r15", [R15W]>, DwarfRegNum<[15]>;
+}
+
+// Register pairs
+let SubRegIndices = [subreg_even32, subreg_odd32] in {
+def R0P : GPR64< 0, "r0", [R0W, R1W], [R0D, R1D]>, DwarfRegNum<[0]>;
+def R2P : GPR64< 2, "r2", [R2W, R3W], [R2D, R3D]>, DwarfRegNum<[2]>;
+def R4P : GPR64< 4, "r4", [R4W, R5W], [R4D, R5D]>, DwarfRegNum<[4]>;
+def R6P : GPR64< 6, "r6", [R6W, R7W], [R6D, R7D]>, DwarfRegNum<[6]>;
+def R8P : GPR64< 8, "r8", [R8W, R9W], [R8D, R9D]>, DwarfRegNum<[8]>;
+def R10P : GPR64<10, "r10", [R10W, R11W], [R10D, R11D]>, DwarfRegNum<[10]>;
+def R12P : GPR64<12, "r12", [R12W, R13W], [R12D, R13D]>, DwarfRegNum<[12]>;
+def R14P : GPR64<14, "r14", [R14W, R15W], [R14D, R15D]>, DwarfRegNum<[14]>;
+}
+
+let SubRegIndices = [subreg_even, subreg_odd],
+ CompositeIndices = [(subreg_even32 subreg_even, subreg_32bit),
+ (subreg_odd32 subreg_odd, subreg_32bit)] in {
+def R0Q : GPR128< 0, "r0", [R0D, R1D], [R0P]>, DwarfRegNum<[0]>;
+def R2Q : GPR128< 2, "r2", [R2D, R3D], [R2P]>, DwarfRegNum<[2]>;
+def R4Q : GPR128< 4, "r4", [R4D, R5D], [R4P]>, DwarfRegNum<[4]>;
+def R6Q : GPR128< 6, "r6", [R6D, R7D], [R6P]>, DwarfRegNum<[6]>;
+def R8Q : GPR128< 8, "r8", [R8D, R9D], [R8P]>, DwarfRegNum<[8]>;
+def R10Q : GPR128<10, "r10", [R10D, R11D], [R10P]>, DwarfRegNum<[10]>;
+def R12Q : GPR128<12, "r12", [R12D, R13D], [R12P]>, DwarfRegNum<[12]>;
+def R14Q : GPR128<14, "r14", [R14D, R15D], [R14P]>, DwarfRegNum<[14]>;
+}
+
+// Floating-point registers
+def F0S : FPRS< 0, "f0">, DwarfRegNum<[16]>;
+def F1S : FPRS< 1, "f1">, DwarfRegNum<[17]>;
+def F2S : FPRS< 2, "f2">, DwarfRegNum<[18]>;
+def F3S : FPRS< 3, "f3">, DwarfRegNum<[19]>;
+def F4S : FPRS< 4, "f4">, DwarfRegNum<[20]>;
+def F5S : FPRS< 5, "f5">, DwarfRegNum<[21]>;
+def F6S : FPRS< 6, "f6">, DwarfRegNum<[22]>;
+def F7S : FPRS< 7, "f7">, DwarfRegNum<[23]>;
+def F8S : FPRS< 8, "f8">, DwarfRegNum<[24]>;
+def F9S : FPRS< 9, "f9">, DwarfRegNum<[25]>;
+def F10S : FPRS<10, "f10">, DwarfRegNum<[26]>;
+def F11S : FPRS<11, "f11">, DwarfRegNum<[27]>;
+def F12S : FPRS<12, "f12">, DwarfRegNum<[28]>;
+def F13S : FPRS<13, "f13">, DwarfRegNum<[29]>;
+def F14S : FPRS<14, "f14">, DwarfRegNum<[30]>;
+def F15S : FPRS<15, "f15">, DwarfRegNum<[31]>;
+
+let SubRegIndices = [subreg_32bit] in {
+def F0L : FPRL< 0, "f0", [F0S]>, DwarfRegNum<[16]>;
+def F1L : FPRL< 1, "f1", [F1S]>, DwarfRegNum<[17]>;
+def F2L : FPRL< 2, "f2", [F2S]>, DwarfRegNum<[18]>;
+def F3L : FPRL< 3, "f3", [F3S]>, DwarfRegNum<[19]>;
+def F4L : FPRL< 4, "f4", [F4S]>, DwarfRegNum<[20]>;
+def F5L : FPRL< 5, "f5", [F5S]>, DwarfRegNum<[21]>;
+def F6L : FPRL< 6, "f6", [F6S]>, DwarfRegNum<[22]>;
+def F7L : FPRL< 7, "f7", [F7S]>, DwarfRegNum<[23]>;
+def F8L : FPRL< 8, "f8", [F8S]>, DwarfRegNum<[24]>;
+def F9L : FPRL< 9, "f9", [F9S]>, DwarfRegNum<[25]>;
+def F10L : FPRL<10, "f10", [F10S]>, DwarfRegNum<[26]>;
+def F11L : FPRL<11, "f11", [F11S]>, DwarfRegNum<[27]>;
+def F12L : FPRL<12, "f12", [F12S]>, DwarfRegNum<[28]>;
+def F13L : FPRL<13, "f13", [F13S]>, DwarfRegNum<[29]>;
+def F14L : FPRL<14, "f14", [F14S]>, DwarfRegNum<[30]>;
+def F15L : FPRL<15, "f15", [F15S]>, DwarfRegNum<[31]>;
+}
+
+// Status register
+def PSW : SystemZReg<"psw">;
+
+/// Register classes
+def GR32 : RegisterClass<"SystemZ", [i32], 32,
+ // Volatile registers
+ [R0W, R1W, R2W, R3W, R4W, R5W, R6W, R7W, R8W, R9W, R10W, R12W, R13W,
+ // Frame pointer, sometimes allocable
+ R11W,
+ // Volatile, but not allocable
+ R14W, R15W]>
+{
+ let MethodProtos = [{
+ iterator allocation_order_begin(const MachineFunction &MF) const;
+ iterator allocation_order_end(const MachineFunction &MF) const;
+ }];
+ let MethodBodies = [{
+ static const unsigned SystemZ_REG32[] = {
+ SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, SystemZ::R4W,
+ SystemZ::R5W, SystemZ::R0W, SystemZ::R12W, SystemZ::R11W,
+ SystemZ::R10W, SystemZ::R9W, SystemZ::R8W, SystemZ::R7W,
+ SystemZ::R6W, SystemZ::R14W, SystemZ::R13W
+ };
+ static const unsigned SystemZ_REG32_nofp[] = {
+ SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, SystemZ::R4W,
+ SystemZ::R5W, SystemZ::R0W, SystemZ::R12W, /* No R11W */
+ SystemZ::R10W, SystemZ::R9W, SystemZ::R8W, SystemZ::R7W,
+ SystemZ::R6W, SystemZ::R14W, SystemZ::R13W
+ };
+ GR32Class::iterator
+ GR32Class::allocation_order_begin(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_REG32_nofp;
+ else
+ return SystemZ_REG32;
+ }
+ GR32Class::iterator
+ GR32Class::allocation_order_end(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_REG32_nofp + (sizeof(SystemZ_REG32_nofp) / sizeof(unsigned));
+ else
+ return SystemZ_REG32 + (sizeof(SystemZ_REG32) / sizeof(unsigned));
+ }
+ }];
+}
+
+/// Registers used to generate address. Everything except R0.
+def ADDR32 : RegisterClass<"SystemZ", [i32], 32,
+ // Volatile registers
+ [R1W, R2W, R3W, R4W, R5W, R6W, R7W, R8W, R9W, R10W, R12W, R13W,
+ // Frame pointer, sometimes allocable
+ R11W,
+ // Volatile, but not allocable
+ R14W, R15W]>
+{
+ let MethodProtos = [{
+ iterator allocation_order_begin(const MachineFunction &MF) const;
+ iterator allocation_order_end(const MachineFunction &MF) const;
+ }];
+ let MethodBodies = [{
+ static const unsigned SystemZ_ADDR32[] = {
+ SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, SystemZ::R4W,
+ SystemZ::R5W, /* No R0W */ SystemZ::R12W, SystemZ::R11W,
+ SystemZ::R10W, SystemZ::R9W, SystemZ::R8W, SystemZ::R7W,
+ SystemZ::R6W, SystemZ::R14W, SystemZ::R13W
+ };
+ static const unsigned SystemZ_ADDR32_nofp[] = {
+ SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, SystemZ::R4W,
+ SystemZ::R5W, /* No R0W */ SystemZ::R12W, /* No R11W */
+ SystemZ::R10W, SystemZ::R9W, SystemZ::R8W, SystemZ::R7W,
+ SystemZ::R6W, SystemZ::R14W, SystemZ::R13W
+ };
+ ADDR32Class::iterator
+ ADDR32Class::allocation_order_begin(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_ADDR32_nofp;
+ else
+ return SystemZ_ADDR32;
+ }
+ ADDR32Class::iterator
+ ADDR32Class::allocation_order_end(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_ADDR32_nofp + (sizeof(SystemZ_ADDR32_nofp) / sizeof(unsigned));
+ else
+ return SystemZ_ADDR32 + (sizeof(SystemZ_ADDR32) / sizeof(unsigned));
+ }
+ }];
+}
+
+def GR64 : RegisterClass<"SystemZ", [i64], 64,
+ // Volatile registers
+ [R0D, R1D, R2D, R3D, R4D, R5D, R6D, R7D, R8D, R9D, R10D, R12D, R13D,
+ // Frame pointer, sometimes allocable
+ R11D,
+ // Volatile, but not allocable
+ R14D, R15D]>
+{
+ let SubRegClasses = [(GR32 subreg_32bit)];
+ let MethodProtos = [{
+ iterator allocation_order_begin(const MachineFunction &MF) const;
+ iterator allocation_order_end(const MachineFunction &MF) const;
+ }];
+ let MethodBodies = [{
+ static const unsigned SystemZ_REG64[] = {
+ SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, SystemZ::R4D,
+ SystemZ::R5D, SystemZ::R0D, SystemZ::R12D, SystemZ::R11D,
+ SystemZ::R10D, SystemZ::R9D, SystemZ::R8D, SystemZ::R7D,
+ SystemZ::R6D, SystemZ::R14D, SystemZ::R13D
+ };
+ static const unsigned SystemZ_REG64_nofp[] = {
+ SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, SystemZ::R4D,
+ SystemZ::R5D, SystemZ::R0D, SystemZ::R12D, /* No R11D */
+ SystemZ::R10D, SystemZ::R9D, SystemZ::R8D, SystemZ::R7D,
+ SystemZ::R6D, SystemZ::R14D, SystemZ::R13D
+ };
+ GR64Class::iterator
+ GR64Class::allocation_order_begin(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_REG64_nofp;
+ else
+ return SystemZ_REG64;
+ }
+ GR64Class::iterator
+ GR64Class::allocation_order_end(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_REG64_nofp + (sizeof(SystemZ_REG64_nofp) / sizeof(unsigned));
+ else
+ return SystemZ_REG64 + (sizeof(SystemZ_REG64) / sizeof(unsigned));
+ }
+ }];
+}
+
+def ADDR64 : RegisterClass<"SystemZ", [i64], 64,
+ // Volatile registers
+ [R1D, R2D, R3D, R4D, R5D, R6D, R7D, R8D, R9D, R10D, R12D, R13D,
+ // Frame pointer, sometimes allocable
+ R11D,
+ // Volatile, but not allocable
+ R14D, R15D]>
+{
+ let SubRegClasses = [(ADDR32 subreg_32bit)];
+ let MethodProtos = [{
+ iterator allocation_order_begin(const MachineFunction &MF) const;
+ iterator allocation_order_end(const MachineFunction &MF) const;
+ }];
+ let MethodBodies = [{
+ static const unsigned SystemZ_ADDR64[] = {
+ SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, SystemZ::R4D,
+ SystemZ::R5D, /* No R0D */ SystemZ::R12D, SystemZ::R11D,
+ SystemZ::R10D, SystemZ::R9D, SystemZ::R8D, SystemZ::R7D,
+ SystemZ::R6D, SystemZ::R14D, SystemZ::R13D
+ };
+ static const unsigned SystemZ_ADDR64_nofp[] = {
+ SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, SystemZ::R4D,
+ SystemZ::R5D, /* No R0D */ SystemZ::R12D, /* No R11D */
+ SystemZ::R10D, SystemZ::R9D, SystemZ::R8D, SystemZ::R7D,
+ SystemZ::R6D, SystemZ::R14D, SystemZ::R13D
+ };
+ ADDR64Class::iterator
+ ADDR64Class::allocation_order_begin(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_ADDR64_nofp;
+ else
+ return SystemZ_ADDR64;
+ }
+ ADDR64Class::iterator
+ ADDR64Class::allocation_order_end(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_ADDR64_nofp + (sizeof(SystemZ_ADDR64_nofp) / sizeof(unsigned));
+ else
+ return SystemZ_ADDR64 + (sizeof(SystemZ_ADDR64) / sizeof(unsigned));
+ }
+ }];
+}
+
+// Even-odd register pairs
+def GR64P : RegisterClass<"SystemZ", [v2i32], 64,
+ [R0P, R2P, R4P, R6P, R8P, R10P, R12P, R14P]>
+{
+ let SubRegClasses = [(GR32 subreg_even32, subreg_odd32)];
+ let MethodProtos = [{
+ iterator allocation_order_begin(const MachineFunction &MF) const;
+ iterator allocation_order_end(const MachineFunction &MF) const;
+ }];
+ let MethodBodies = [{
+ static const unsigned SystemZ_REG64P[] = {
+ SystemZ::R0P, SystemZ::R2P, SystemZ::R4P, SystemZ::R10P,
+ SystemZ::R8P, SystemZ::R6P };
+ static const unsigned SystemZ_REG64P_nofp[] = {
+ SystemZ::R0P, SystemZ::R2P, SystemZ::R4P, /* NO R10P */
+ SystemZ::R8P, SystemZ::R6P };
+ GR64PClass::iterator
+ GR64PClass::allocation_order_begin(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_REG64P_nofp;
+ else
+ return SystemZ_REG64P;
+ }
+ GR64PClass::iterator
+ GR64PClass::allocation_order_end(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_REG64P_nofp + (sizeof(SystemZ_REG64P_nofp) / sizeof(unsigned));
+ else
+ return SystemZ_REG64P + (sizeof(SystemZ_REG64P) / sizeof(unsigned));
+ }
+ }];
+}
+
+def GR128 : RegisterClass<"SystemZ", [v2i64], 128,
+ [R0Q, R2Q, R4Q, R6Q, R8Q, R10Q, R12Q, R14Q]>
+{
+ let SubRegClasses = [(GR32 subreg_even32, subreg_odd32),
+ (GR64 subreg_even, subreg_odd)];
+ let MethodProtos = [{
+ iterator allocation_order_begin(const MachineFunction &MF) const;
+ iterator allocation_order_end(const MachineFunction &MF) const;
+ }];
+ let MethodBodies = [{
+ static const unsigned SystemZ_REG128[] = {
+ SystemZ::R0Q, SystemZ::R2Q, SystemZ::R4Q, SystemZ::R10Q,
+ SystemZ::R8Q, SystemZ::R6Q };
+ static const unsigned SystemZ_REG128_nofp[] = {
+ SystemZ::R0Q, SystemZ::R2Q, SystemZ::R4Q, /* NO R10Q */
+ SystemZ::R8Q, SystemZ::R6Q };
+ GR128Class::iterator
+ GR128Class::allocation_order_begin(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_REG128_nofp;
+ else
+ return SystemZ_REG128;
+ }
+ GR128Class::iterator
+ GR128Class::allocation_order_end(const MachineFunction &MF) const {
+ const TargetMachine &TM = MF.getTarget();
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ if (RI->hasFP(MF))
+ return SystemZ_REG128_nofp + (sizeof(SystemZ_REG128_nofp) / sizeof(unsigned));
+ else
+ return SystemZ_REG128 + (sizeof(SystemZ_REG128) / sizeof(unsigned));
+ }
+ }];
+}
+
+def FP32 : RegisterClass<"SystemZ", [f32], 32,
+ [F0S, F1S, F2S, F3S, F4S, F5S, F6S, F7S,
+ F8S, F9S, F10S, F11S, F12S, F13S, F14S, F15S]> {
+ let MethodProtos = [{
+ iterator allocation_order_begin(const MachineFunction &MF) const;
+ iterator allocation_order_end(const MachineFunction &MF) const;
+ }];
+ let MethodBodies = [{
+ static const unsigned SystemZ_REGFP32[] = {
+ SystemZ::F0S, SystemZ::F2S, SystemZ::F4S, SystemZ::F6S,
+ SystemZ::F1S, SystemZ::F3S, SystemZ::F5S, SystemZ::F7S,
+ SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S,
+ SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S };
+ FP32Class::iterator
+ FP32Class::allocation_order_begin(const MachineFunction &MF) const {
+ return SystemZ_REGFP32;
+ }
+ FP32Class::iterator
+ FP32Class::allocation_order_end(const MachineFunction &MF) const {
+ return SystemZ_REGFP32 + (sizeof(SystemZ_REGFP32) / sizeof(unsigned));
+ }
+ }];
+}
+
+def FP64 : RegisterClass<"SystemZ", [f64], 64,
+ [F0L, F1L, F2L, F3L, F4L, F5L, F6L, F7L,
+ F8L, F9L, F10L, F11L, F12L, F13L, F14L, F15L]> {
+ let SubRegClasses = [(FP32 subreg_32bit)];
+ let MethodProtos = [{
+ iterator allocation_order_begin(const MachineFunction &MF) const;
+ iterator allocation_order_end(const MachineFunction &MF) const;
+ }];
+ let MethodBodies = [{
+ static const unsigned SystemZ_REGFP64[] = {
+ SystemZ::F0L, SystemZ::F2L, SystemZ::F4L, SystemZ::F6L,
+ SystemZ::F1L, SystemZ::F3L, SystemZ::F5L, SystemZ::F7L,
+ SystemZ::F8L, SystemZ::F9L, SystemZ::F10L, SystemZ::F11L,
+ SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L };
+ FP64Class::iterator
+ FP64Class::allocation_order_begin(const MachineFunction &MF) const {
+ return SystemZ_REGFP64;
+ }
+ FP64Class::iterator
+ FP64Class::allocation_order_end(const MachineFunction &MF) const {
+ return SystemZ_REGFP64 + (sizeof(SystemZ_REGFP64) / sizeof(unsigned));
+ }
+ }];
+}
+
+// Status flags registers.
+def CCR : RegisterClass<"SystemZ", [i64], 64, [PSW]> {
+ let CopyCost = -1; // Don't allow copying of status registers.
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp
new file mode 100644
index 0000000..3eabcd2
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp
@@ -0,0 +1,23 @@
+//===-- SystemZSelectionDAGInfo.cpp - SystemZ SelectionDAG Info -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SystemZSelectionDAGInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "systemz-selectiondag-info"
+#include "SystemZTargetMachine.h"
+using namespace llvm;
+
+SystemZSelectionDAGInfo::SystemZSelectionDAGInfo(const SystemZTargetMachine &TM)
+ : TargetSelectionDAGInfo(TM) {
+}
+
+SystemZSelectionDAGInfo::~SystemZSelectionDAGInfo() {
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h b/contrib/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h
new file mode 100644
index 0000000..1450401
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h
@@ -0,0 +1,31 @@
+//===-- SystemZSelectionDAGInfo.h - SystemZ SelectionDAG Info ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SystemZ subclass for TargetSelectionDAGInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SYSTEMZSELECTIONDAGINFO_H
+#define SYSTEMZSELECTIONDAGINFO_H
+
+#include "llvm/Target/TargetSelectionDAGInfo.h"
+
+namespace llvm {
+
+class SystemZTargetMachine;
+
+class SystemZSelectionDAGInfo : public TargetSelectionDAGInfo {
+public:
+ explicit SystemZSelectionDAGInfo(const SystemZTargetMachine &TM);
+ ~SystemZSelectionDAGInfo();
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp
new file mode 100644
index 0000000..a8b5e1f
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp
@@ -0,0 +1,47 @@
+//===- SystemZSubtarget.cpp - SystemZ Subtarget Information -------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SystemZ specific subclass of TargetSubtarget.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZSubtarget.h"
+#include "SystemZ.h"
+#include "SystemZGenSubtarget.inc"
+#include "llvm/GlobalValue.h"
+#include "llvm/Target/TargetMachine.h"
+
+using namespace llvm;
+
+SystemZSubtarget::SystemZSubtarget(const std::string &TT,
+ const std::string &FS):
+ HasZ10Insts(false) {
+ std::string CPU = "z9";
+
+ // Parse features string.
+ ParseSubtargetFeatures(FS, CPU);
+}
+
+/// True if accessing the GV requires an extra load.
+bool SystemZSubtarget::GVRequiresExtraLoad(const GlobalValue* GV,
+ const TargetMachine& TM,
+ bool isDirectCall) const {
+ if (TM.getRelocationModel() == Reloc::PIC_) {
+ // Extra load is needed for all externally visible.
+ if (isDirectCall)
+ return false;
+
+ if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.h b/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.h
new file mode 100644
index 0000000..405d6e9
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.h
@@ -0,0 +1,45 @@
+//==-- SystemZSubtarget.h - Define Subtarget for the SystemZ ---*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SystemZ specific subclass of TargetSubtarget.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_SystemZ_SUBTARGET_H
+#define LLVM_TARGET_SystemZ_SUBTARGET_H
+
+#include "llvm/Target/TargetSubtarget.h"
+
+#include <string>
+
+namespace llvm {
+class GlobalValue;
+class TargetMachine;
+
+class SystemZSubtarget : public TargetSubtarget {
+ bool HasZ10Insts;
+public:
+ /// This constructor initializes the data members to match that
+ /// of the specified triple.
+ ///
+ SystemZSubtarget(const std::string &TT, const std::string &FS);
+
+ /// ParseSubtargetFeatures - Parses features string setting specified
+ /// subtarget options. Definition of function is auto generated by tblgen.
+ std::string ParseSubtargetFeatures(const std::string &FS,
+ const std::string &CPU);
+
+ bool isZ10() const { return HasZ10Insts; }
+
+ bool GVRequiresExtraLoad(const GlobalValue* GV, const TargetMachine& TM,
+ bool isDirectCall) const;
+};
+} // End llvm namespace
+
+#endif // LLVM_TARGET_SystemZ_SUBTARGET_H
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
new file mode 100644
index 0000000..f45827b
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
@@ -0,0 +1,44 @@
+//===-- SystemZTargetMachine.cpp - Define TargetMachine for SystemZ -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZMCAsmInfo.h"
+#include "SystemZTargetMachine.h"
+#include "SystemZ.h"
+#include "llvm/PassManager.h"
+#include "llvm/Target/TargetRegistry.h"
+using namespace llvm;
+
+extern "C" void LLVMInitializeSystemZTarget() {
+ // Register the target.
+ RegisterTargetMachine<SystemZTargetMachine> X(TheSystemZTarget);
+ RegisterAsmInfo<SystemZMCAsmInfo> Y(TheSystemZTarget);
+}
+
+/// SystemZTargetMachine ctor - Create an ILP64 architecture model
+///
+SystemZTargetMachine::SystemZTargetMachine(const Target &T,
+ const std::string &TT,
+ const std::string &FS)
+ : LLVMTargetMachine(T, TT),
+ Subtarget(TT, FS),
+ DataLayout("E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32"
+ "-f64:64:64-f128:128:128-a0:16:16-n32:64"),
+ InstrInfo(*this), TLInfo(*this), TSInfo(*this),
+ FrameInfo(TargetFrameInfo::StackGrowsDown, 8, -160) {
+
+ if (getRelocationModel() == Reloc::Default)
+ setRelocationModel(Reloc::Static);
+}
+
+bool SystemZTargetMachine::addInstSelector(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
+ // Install an instruction selector.
+ PM.add(createSystemZISelDag(*this, OptLevel));
+ return false;
+}
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZTargetMachine.h b/contrib/llvm/lib/Target/SystemZ/SystemZTargetMachine.h
new file mode 100644
index 0000000..6af829b
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/SystemZTargetMachine.h
@@ -0,0 +1,67 @@
+//==- SystemZTargetMachine.h - Define TargetMachine for SystemZ ---*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SystemZ specific subclass of TargetMachine.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_TARGET_SYSTEMZ_TARGETMACHINE_H
+#define LLVM_TARGET_SYSTEMZ_TARGETMACHINE_H
+
+#include "SystemZInstrInfo.h"
+#include "SystemZISelLowering.h"
+#include "SystemZSelectionDAGInfo.h"
+#include "SystemZRegisterInfo.h"
+#include "SystemZSubtarget.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+
+/// SystemZTargetMachine
+///
+class SystemZTargetMachine : public LLVMTargetMachine {
+ SystemZSubtarget Subtarget;
+ const TargetData DataLayout; // Calculates type size & alignment
+ SystemZInstrInfo InstrInfo;
+ SystemZTargetLowering TLInfo;
+ SystemZSelectionDAGInfo TSInfo;
+
+ // SystemZ does not have any call stack frame, therefore not having
+ // any SystemZ specific FrameInfo class.
+ TargetFrameInfo FrameInfo;
+public:
+ SystemZTargetMachine(const Target &T, const std::string &TT,
+ const std::string &FS);
+
+ virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
+ virtual const SystemZInstrInfo *getInstrInfo() const { return &InstrInfo; }
+ virtual const TargetData *getTargetData() const { return &DataLayout;}
+ virtual const SystemZSubtarget *getSubtargetImpl() const { return &Subtarget; }
+
+ virtual const SystemZRegisterInfo *getRegisterInfo() const {
+ return &InstrInfo.getRegisterInfo();
+ }
+
+ virtual const SystemZTargetLowering *getTargetLowering() const {
+ return &TLInfo;
+ }
+
+ virtual const SystemZSelectionDAGInfo* getSelectionDAGInfo() const {
+ return &TSInfo;
+ }
+
+ virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
+}; // SystemZTargetMachine.
+
+} // end namespace llvm
+
+#endif // LLVM_TARGET_SystemZ_TARGETMACHINE_H
diff --git a/contrib/llvm/lib/Target/SystemZ/TargetInfo/CMakeLists.txt b/contrib/llvm/lib/Target/SystemZ/TargetInfo/CMakeLists.txt
new file mode 100644
index 0000000..743d8d3
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/TargetInfo/CMakeLists.txt
@@ -0,0 +1,7 @@
+include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
+
+add_llvm_library(LLVMSystemZInfo
+ SystemZTargetInfo.cpp
+ )
+
+add_dependencies(LLVMSystemZInfo SystemZCodeGenTable_gen)
diff --git a/contrib/llvm/lib/Target/SystemZ/TargetInfo/Makefile b/contrib/llvm/lib/Target/SystemZ/TargetInfo/Makefile
new file mode 100644
index 0000000..0be80eb
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/TargetInfo/Makefile
@@ -0,0 +1,15 @@
+##===- lib/Target/SystemZ/TargetInfo/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../../../..
+LIBRARYNAME = LLVMSystemZInfo
+
+# Hack: we need to include 'main' target directory to grab private headers
+CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
+
+include $(LEVEL)/Makefile.common
diff --git a/contrib/llvm/lib/Target/SystemZ/TargetInfo/SystemZTargetInfo.cpp b/contrib/llvm/lib/Target/SystemZ/TargetInfo/SystemZTargetInfo.cpp
new file mode 100644
index 0000000..8272b11
--- /dev/null
+++ b/contrib/llvm/lib/Target/SystemZ/TargetInfo/SystemZTargetInfo.cpp
@@ -0,0 +1,19 @@
+//===-- SystemZTargetInfo.cpp - SystemZ Target Implementation -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZ.h"
+#include "llvm/Module.h"
+#include "llvm/Target/TargetRegistry.h"
+using namespace llvm;
+
+Target llvm::TheSystemZTarget;
+
+extern "C" void LLVMInitializeSystemZTargetInfo() {
+ RegisterTarget<Triple::systemz> X(TheSystemZTarget, "systemz", "SystemZ");
+}
OpenPOWER on IntegriCloud