diff options
Diffstat (limited to 'lib/Target/SystemZ')
19 files changed, 996 insertions, 424 deletions
diff --git a/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp index c7725a1459..7f2159f79e 100644 --- a/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "MCTargetDesc/SystemZMCTargetDesc.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" @@ -250,46 +251,6 @@ public: bool isS32Imm() const { return isImm(-(1LL << 31), (1LL << 31) - 1); } }; -// Maps of asm register numbers to LLVM register numbers, with 0 indicating -// an invalid register. We don't use register class directly because that -// specifies the allocation order. -static const unsigned GR32Regs[] = { - SystemZ::R0W, SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, - SystemZ::R4W, SystemZ::R5W, SystemZ::R6W, SystemZ::R7W, - SystemZ::R8W, SystemZ::R9W, SystemZ::R10W, SystemZ::R11W, - SystemZ::R12W, SystemZ::R13W, SystemZ::R14W, SystemZ::R15W -}; -static const unsigned GR64Regs[] = { - SystemZ::R0D, SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, - SystemZ::R4D, SystemZ::R5D, SystemZ::R6D, SystemZ::R7D, - SystemZ::R8D, SystemZ::R9D, SystemZ::R10D, SystemZ::R11D, - SystemZ::R12D, SystemZ::R13D, SystemZ::R14D, SystemZ::R15D -}; -static const unsigned GR128Regs[] = { - SystemZ::R0Q, 0, SystemZ::R2Q, 0, - SystemZ::R4Q, 0, SystemZ::R6Q, 0, - SystemZ::R8Q, 0, SystemZ::R10Q, 0, - SystemZ::R12Q, 0, SystemZ::R14Q, 0 -}; -static const unsigned FP32Regs[] = { - SystemZ::F0S, SystemZ::F1S, SystemZ::F2S, SystemZ::F3S, - SystemZ::F4S, SystemZ::F5S, SystemZ::F6S, SystemZ::F7S, - SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S, - SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S -}; -static const unsigned FP64Regs[] = { - SystemZ::F0D, SystemZ::F1D, SystemZ::F2D, SystemZ::F3D, - SystemZ::F4D, SystemZ::F5D, SystemZ::F6D, SystemZ::F7D, - SystemZ::F8D, SystemZ::F9D, SystemZ::F10D, SystemZ::F11D, - SystemZ::F12D, SystemZ::F13D, SystemZ::F14D, SystemZ::F15D -}; -static const unsigned FP128Regs[] = { - SystemZ::F0Q, SystemZ::F1Q, 0, 0, - SystemZ::F4Q, SystemZ::F5Q, 0, 0, - SystemZ::F8Q, SystemZ::F9Q, 0, 0, - SystemZ::F12Q, SystemZ::F13Q, 0, 0 -}; - class SystemZAsmParser : public MCTargetAsmParser { #define GET_ASSEMBLER_HEADER #include "SystemZGenAsmMatcher.inc" @@ -349,25 +310,28 @@ public: // Used by the TableGen code to parse particular operand types. OperandMatchResultTy parseGR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseRegister(Operands, 'r', GR32Regs, SystemZOperand::GR32Reg); + return parseRegister(Operands, 'r', SystemZMC::GR32Regs, + SystemZOperand::GR32Reg); } OperandMatchResultTy parseGR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseRegister(Operands, 'r', GR64Regs, SystemZOperand::GR64Reg); + return parseRegister(Operands, 'r', SystemZMC::GR64Regs, + SystemZOperand::GR64Reg); } OperandMatchResultTy parseGR128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseRegister(Operands, 'r', GR128Regs, SystemZOperand::GR128Reg); + return parseRegister(Operands, 'r', SystemZMC::GR128Regs, + SystemZOperand::GR128Reg); } OperandMatchResultTy parseADDR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseRegister(Operands, 'r', GR32Regs, SystemZOperand::ADDR32Reg, - true); + return parseRegister(Operands, 'r', SystemZMC::GR32Regs, + SystemZOperand::ADDR32Reg, true); } OperandMatchResultTy parseADDR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseRegister(Operands, 'r', GR64Regs, SystemZOperand::ADDR64Reg, - true); + return parseRegister(Operands, 'r', SystemZMC::GR64Regs, + SystemZOperand::ADDR64Reg, true); } OperandMatchResultTy parseADDR128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { @@ -375,30 +339,47 @@ public: } OperandMatchResultTy parseFP32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseRegister(Operands, 'f', FP32Regs, SystemZOperand::FP32Reg); + return parseRegister(Operands, 'f', SystemZMC::FP32Regs, + SystemZOperand::FP32Reg); } OperandMatchResultTy parseFP64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseRegister(Operands, 'f', FP64Regs, SystemZOperand::FP64Reg); + return parseRegister(Operands, 'f', SystemZMC::FP64Regs, + SystemZOperand::FP64Reg); } OperandMatchResultTy parseFP128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseRegister(Operands, 'f', FP128Regs, SystemZOperand::FP128Reg); + return parseRegister(Operands, 'f', SystemZMC::FP128Regs, + SystemZOperand::FP128Reg); } OperandMatchResultTy parseBDAddr32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseAddress(Operands, GR32Regs, SystemZOperand::ADDR32Reg, false); + return parseAddress(Operands, SystemZMC::GR32Regs, + SystemZOperand::ADDR32Reg, false); } OperandMatchResultTy parseBDAddr64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseAddress(Operands, GR64Regs, SystemZOperand::ADDR64Reg, false); + return parseAddress(Operands, SystemZMC::GR64Regs, + SystemZOperand::ADDR64Reg, false); } OperandMatchResultTy parseBDXAddr64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseAddress(Operands, GR64Regs, SystemZOperand::ADDR64Reg, true); + return parseAddress(Operands, SystemZMC::GR64Regs, + SystemZOperand::ADDR64Reg, true); } OperandMatchResultTy parseAccessReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + OperandMatchResultTy + parsePCRel(SmallVectorImpl<MCParsedAsmOperand*> &Operands, + int64_t MinVal, int64_t MaxVal); + OperandMatchResultTy + parsePCRel16(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1); + } + OperandMatchResultTy + parsePCRel32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1); + } }; } @@ -502,7 +483,8 @@ SystemZAsmParser::parseAddress(SmallVectorImpl<MCParsedAsmOperand*> &Operands, // Parse the first register. Register Reg; - OperandMatchResultTy Result = parseRegister(Reg, 'r', GR64Regs, true); + OperandMatchResultTy Result = parseRegister(Reg, 'r', SystemZMC::GR64Regs, + true); if (Result != MatchOperand_Success) return Result; @@ -517,7 +499,7 @@ SystemZAsmParser::parseAddress(SmallVectorImpl<MCParsedAsmOperand*> &Operands, } Index = Reg.Number; - Result = parseRegister(Reg, 'r', GR64Regs, true); + Result = parseRegister(Reg, 'r', SystemZMC::GR64Regs, true); if (Result != MatchOperand_Success) return Result; } @@ -546,9 +528,9 @@ bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, if (parseRegister(Reg)) return Error(Reg.StartLoc, "register expected"); if (Reg.Prefix == 'r' && Reg.Number < 16) - RegNo = GR64Regs[Reg.Number]; + RegNo = SystemZMC::GR64Regs[Reg.Number]; else if (Reg.Prefix == 'f' && Reg.Number < 16) - RegNo = FP64Regs[Reg.Number]; + RegNo = SystemZMC::FP64Regs[Reg.Number]; else return Error(Reg.StartLoc, "invalid register"); StartLoc = Reg.StartLoc; @@ -683,6 +665,37 @@ parseAccessReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return MatchOperand_Success; } +SystemZAsmParser::OperandMatchResultTy SystemZAsmParser:: +parsePCRel(SmallVectorImpl<MCParsedAsmOperand*> &Operands, + int64_t MinVal, int64_t MaxVal) { + MCContext &Ctx = getContext(); + MCStreamer &Out = getStreamer(); + const MCExpr *Expr; + SMLoc StartLoc = Parser.getTok().getLoc(); + if (getParser().parseExpression(Expr)) + return MatchOperand_NoMatch; + + // For consistency with the GNU assembler, treat immediates as offsets + // from ".". + if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) { + int64_t Value = CE->getValue(); + if ((Value & 1) || Value < MinVal || Value > MaxVal) { + Error(StartLoc, "offset out of range"); + return MatchOperand_ParseFail; + } + MCSymbol *Sym = Ctx.CreateTempSymbol(); + Out.EmitLabel(Sym); + const MCExpr *Base = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, + Ctx); + Expr = Value == 0 ? Base : MCBinaryExpr::CreateAdd(Base, Expr, Ctx); + } + + SMLoc EndLoc = + SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc)); + return MatchOperand_Success; +} + // Force static initialization. extern "C" void LLVMInitializeSystemZAsmParser() { RegisterMCAsmParser<SystemZAsmParser> X(TheSystemZTarget); diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt index 67b17fcc59..757d5a8898 100644 --- a/lib/Target/SystemZ/CMakeLists.txt +++ b/lib/Target/SystemZ/CMakeLists.txt @@ -4,6 +4,7 @@ tablegen(LLVM SystemZGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM SystemZGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM SystemZGenCallingConv.inc -gen-callingconv) tablegen(LLVM SystemZGenDAGISel.inc -gen-dag-isel) +tablegen(LLVM SystemZGenDisassemblerTables.inc -gen-disassembler) tablegen(LLVM SystemZGenMCCodeEmitter.inc -gen-emitter -mc-emitter) tablegen(LLVM SystemZGenInstrInfo.inc -gen-instr-info) tablegen(LLVM SystemZGenRegisterInfo.inc -gen-register-info) @@ -27,6 +28,7 @@ add_llvm_target(SystemZCodeGen add_dependencies(LLVMSystemZCodeGen intrinsics_gen) add_subdirectory(AsmParser) +add_subdirectory(Disassembler) add_subdirectory(InstPrinter) add_subdirectory(TargetInfo) add_subdirectory(MCTargetDesc) diff --git a/lib/Target/SystemZ/Disassembler/CMakeLists.txt b/lib/Target/SystemZ/Disassembler/CMakeLists.txt new file mode 100644 index 0000000000..5bc1859816 --- /dev/null +++ b/lib/Target/SystemZ/Disassembler/CMakeLists.txt @@ -0,0 +1,7 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMSystemZDisassembler + SystemZDisassembler.cpp + ) + +add_dependencies(LLVMSystemZDisassembler SystemZCommonTableGen) diff --git a/lib/Target/SystemZ/Disassembler/LLVMBuild.txt b/lib/Target/SystemZ/Disassembler/LLVMBuild.txt new file mode 100644 index 0000000000..c3081f5447 --- /dev/null +++ b/lib/Target/SystemZ/Disassembler/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===-- ./lib/Target/SystemZ/Disassembler/LLVMBuild.txt ---------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = SystemZDisassembler +parent = SystemZ +required_libraries = MC Support SystemZDesc SystemZInfo +add_to_library_groups = SystemZ diff --git a/lib/Target/SystemZ/Disassembler/Makefile b/lib/Target/SystemZ/Disassembler/Makefile new file mode 100644 index 0000000000..efc4cc8e9c --- /dev/null +++ b/lib/Target/SystemZ/Disassembler/Makefile @@ -0,0 +1,16 @@ +##===-- lib/Target/SystemZ/Disassembler/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 = LLVMSystemZDisassembler + +# Hack: we need to include 'main' x86 target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp b/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp new file mode 100644 index 0000000000..9a9de78224 --- /dev/null +++ b/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp @@ -0,0 +1,301 @@ +//===-- SystemZDisassembler.cpp - Disassembler for SystemZ ------*- C++ -*-===// +// +// 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/MC/MCDisassembler.h" +#include "llvm/MC/MCFixedLenDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +typedef MCDisassembler::DecodeStatus DecodeStatus; + +namespace { +class SystemZDisassembler : public MCDisassembler { +public: + SystemZDisassembler(const MCSubtargetInfo &STI) + : MCDisassembler(STI) {} + virtual ~SystemZDisassembler() {} + + // Override MCDisassembler. + virtual DecodeStatus getInstruction(MCInst &instr, + uint64_t &size, + const MemoryObject ®ion, + uint64_t address, + raw_ostream &vStream, + raw_ostream &cStream) const LLVM_OVERRIDE; +}; +} // end anonymous namespace + +static MCDisassembler *createSystemZDisassembler(const Target &T, + const MCSubtargetInfo &STI) { + return new SystemZDisassembler(STI); +} + +extern "C" void LLVMInitializeSystemZDisassembler() { + // Register the disassembler. + TargetRegistry::RegisterMCDisassembler(TheSystemZTarget, + createSystemZDisassembler); +} + +static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo, + const unsigned *Regs, + bool isAddress = false) { + assert(RegNo < 16 && "Invalid register"); + if (!isAddress || RegNo) { + RegNo = Regs[RegNo]; + if (RegNo == 0) + return MCDisassembler::Fail; + } + Inst.addOperand(MCOperand::CreateReg(RegNo)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs); +} + +static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs); +} + +static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs); +} + +static DecodeStatus DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, true); +} + +static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs); +} + +static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs); +} + +static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs); +} + +template<unsigned N> +static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) { + assert(isUInt<N>(Imm) && "Invalid immediate"); + Inst.addOperand(MCOperand::CreateImm(Imm)); + return MCDisassembler::Success; +} + +template<unsigned N> +static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) { + assert(isUInt<N>(Imm) && "Invalid immediate"); + Inst.addOperand(MCOperand::CreateImm(SignExtend64<N>(Imm))); + return MCDisassembler::Success; +} + +static DecodeStatus decodeAccessRegOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, + const void *Decoder) { + return decodeUImmOperand<4>(Inst, Imm); +} + +static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, const void *Decoder) { + return decodeUImmOperand<4>(Inst, Imm); +} + +static DecodeStatus decodeU6ImmOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, const void *Decoder) { + return decodeUImmOperand<6>(Inst, Imm); +} + +static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, const void *Decoder) { + return decodeUImmOperand<8>(Inst, Imm); +} + +static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, const void *Decoder) { + return decodeUImmOperand<16>(Inst, Imm); +} + +static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, const void *Decoder) { + return decodeUImmOperand<32>(Inst, Imm); +} + +static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, const void *Decoder) { + return decodeSImmOperand<8>(Inst, Imm); +} + +static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, const void *Decoder) { + return decodeSImmOperand<16>(Inst, Imm); +} + +static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, const void *Decoder) { + return decodeSImmOperand<32>(Inst, Imm); +} + +template<unsigned N> +static DecodeStatus decodePCDBLOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address) { + assert(isUInt<N>(Imm) && "Invalid PC-relative offset"); + Inst.addOperand(MCOperand::CreateImm(SignExtend64<N>(Imm) * 2 + Address)); + return MCDisassembler::Success; +} + +static DecodeStatus decodePC16DBLOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, + const void *Decoder) { + return decodePCDBLOperand<16>(Inst, Imm, Address); +} + +static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm, + uint64_t Address, + const void *Decoder) { + return decodePCDBLOperand<32>(Inst, Imm, Address); +} + +static DecodeStatus decodeBDAddr12Operand(MCInst &Inst, uint64_t Field, + const unsigned *Regs) { + uint64_t Base = Field >> 12; + uint64_t Disp = Field & 0xfff; + assert(Base < 16 && "Invalid BDAddr12"); + Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base])); + Inst.addOperand(MCOperand::CreateImm(Disp)); + return MCDisassembler::Success; +} + +static DecodeStatus decodeBDAddr20Operand(MCInst &Inst, uint64_t Field, + const unsigned *Regs) { + uint64_t Base = Field >> 20; + uint64_t Disp = ((Field << 12) & 0xff000) | ((Field >> 8) & 0xfff); + assert(Base < 16 && "Invalid BDAddr20"); + Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base])); + Inst.addOperand(MCOperand::CreateImm(SignExtend64<20>(Disp))); + return MCDisassembler::Success; +} + +static DecodeStatus decodeBDXAddr12Operand(MCInst &Inst, uint64_t Field, + const unsigned *Regs) { + uint64_t Index = Field >> 16; + uint64_t Base = (Field >> 12) & 0xf; + uint64_t Disp = Field & 0xfff; + assert(Index < 16 && "Invalid BDXAddr12"); + Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base])); + Inst.addOperand(MCOperand::CreateImm(Disp)); + Inst.addOperand(MCOperand::CreateReg(Index == 0 ? 0 : Regs[Index])); + return MCDisassembler::Success; +} + +static DecodeStatus decodeBDXAddr20Operand(MCInst &Inst, uint64_t Field, + const unsigned *Regs) { + uint64_t Index = Field >> 24; + uint64_t Base = (Field >> 20) & 0xf; + uint64_t Disp = ((Field & 0xfff00) >> 8) | ((Field & 0xff) << 12); + assert(Index < 16 && "Invalid BDXAddr20"); + Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base])); + Inst.addOperand(MCOperand::CreateImm(SignExtend64<20>(Disp))); + Inst.addOperand(MCOperand::CreateReg(Index == 0 ? 0 : Regs[Index])); + return MCDisassembler::Success; +} + +static DecodeStatus decodeBDAddr32Disp12Operand(MCInst &Inst, uint64_t Field, + uint64_t Address, + const void *Decoder) { + return decodeBDAddr12Operand(Inst, Field, SystemZMC::GR32Regs); +} + +static DecodeStatus decodeBDAddr32Disp20Operand(MCInst &Inst, uint64_t Field, + uint64_t Address, + const void *Decoder) { + return decodeBDAddr20Operand(Inst, Field, SystemZMC::GR32Regs); +} + +static DecodeStatus decodeBDAddr64Disp12Operand(MCInst &Inst, uint64_t Field, + uint64_t Address, + const void *Decoder) { + return decodeBDAddr12Operand(Inst, Field, SystemZMC::GR64Regs); +} + +static DecodeStatus decodeBDAddr64Disp20Operand(MCInst &Inst, uint64_t Field, + uint64_t Address, + const void *Decoder) { + return decodeBDAddr20Operand(Inst, Field, SystemZMC::GR64Regs); +} + +static DecodeStatus decodeBDXAddr64Disp12Operand(MCInst &Inst, uint64_t Field, + uint64_t Address, + const void *Decoder) { + return decodeBDXAddr12Operand(Inst, Field, SystemZMC::GR64Regs); +} + +static DecodeStatus decodeBDXAddr64Disp20Operand(MCInst &Inst, uint64_t Field, + uint64_t Address, + const void *Decoder) { + return decodeBDXAddr20Operand(Inst, Field, SystemZMC::GR64Regs); +} + +#include "SystemZGenDisassemblerTables.inc" + +DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size, + const MemoryObject &Region, + uint64_t Address, + raw_ostream &os, + raw_ostream &cs) const { + // Get the first two bytes of the instruction. + uint8_t Bytes[6]; + Size = 0; + if (Region.readBytes(Address, 2, Bytes, 0) == -1) + return MCDisassembler::Fail; + + // The top 2 bits of the first byte specify the size. + const uint8_t *Table; + if (Bytes[0] < 0x40) { + Size = 2; + Table = DecoderTable16; + } else if (Bytes[0] < 0xc0) { + Size = 4; + Table = DecoderTable32; + } else { + Size = 6; + Table = DecoderTable48; + } + + // Read any remaining bytes. + if (Size > 2 && Region.readBytes(Address + 2, Size - 2, Bytes + 2, 0) == -1) + return MCDisassembler::Fail; + + // Construct the instruction. + uint64_t Inst = 0; + for (uint64_t I = 0; I < Size; ++I) + Inst = (Inst << 8) | Bytes[I]; + + return decodeInstruction(Table, MI, Inst, Address, this, STI); +} diff --git a/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.cpp b/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.cpp index d73cf49808..369802b2b8 100644 --- a/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.cpp +++ b/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.cpp @@ -114,10 +114,26 @@ void SystemZInstPrinter::printAccessRegOperand(const MCInst *MI, int OpNum, O << "%a" << (unsigned int)Value; } +void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum, + raw_ostream &O) { + const MCOperand &MO = MI->getOperand(OpNum); + if (MO.isImm()) { + O << "0x"; + O.write_hex(MO.getImm()); + } else + O << *MO.getExpr(); +} + void SystemZInstPrinter::printCallOperand(const MCInst *MI, int OpNum, raw_ostream &O) { - printOperand(MI, OpNum, O); - O << "@PLT"; + const MCOperand &MO = MI->getOperand(OpNum); + if (MO.isImm()) { + O << "0x"; + O.write_hex(MO.getImm()); + } else { + O << *MO.getExpr(); + O << "@PLT"; + } } void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum, diff --git a/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.h b/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.h index b82e79d93c..f77282efcb 100644 --- a/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.h +++ b/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.h @@ -56,6 +56,7 @@ private: void printU16ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printS32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printU32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O); + void printPCRelOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printCallOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printAccessRegOperand(const MCInst *MI, int OpNum, raw_ostream &O); diff --git a/lib/Target/SystemZ/LLVMBuild.txt b/lib/Target/SystemZ/LLVMBuild.txt index aba0de27ac..95e657f7bd 100644 --- a/lib/Target/SystemZ/LLVMBuild.txt +++ b/lib/Target/SystemZ/LLVMBuild.txt @@ -16,7 +16,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = AsmParser InstPrinter MCTargetDesc TargetInfo +subdirectories = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo [component_0] type = TargetGroup @@ -24,6 +24,7 @@ name = SystemZ parent = Target has_asmparser = 1 has_asmprinter = 1 +has_disassembler = 1 has_jit = 1 [component_1] diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp index ea2250f546..7721b1ffab 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp @@ -45,30 +45,43 @@ private: // Called by the TableGen code to get the binary encoding of operand // MO in MI. Fixups is the list of fixups against MI. - unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, + uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl<MCFixup> &Fixups) const; + // Called by the TableGen code to get the binary encoding of an address. + // The index, if any, is encoded first, followed by the base, + // followed by the displacement. In a 20-bit displacement, + // the low 12 bits are encoded before the high 8 bits. + uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, + SmallVectorImpl<MCFixup> &Fixups) const; + uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, + SmallVectorImpl<MCFixup> &Fixups) const; + uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, + SmallVectorImpl<MCFixup> &Fixups) const; + uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, + SmallVectorImpl<MCFixup> &Fixups) const; + // Operand OpNum of MI needs a PC-relative fixup of kind Kind at // Offset bytes from the start of MI. Add the fixup to Fixups // and return the in-place addend, which since we're a RELA target // is always 0. - unsigned getPCRelEncoding(const MCInst &MI, unsigned int OpNum, + uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum, SmallVectorImpl<MCFixup> &Fixups, unsigned Kind, int64_t Offset) const; - unsigned getPC16DBLEncoding(const MCInst &MI, unsigned int OpNum, + uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum, SmallVectorImpl<MCFixup> &Fixups) const { return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC16DBL, 2); } - unsigned getPC32DBLEncoding(const MCInst &MI, unsigned int OpNum, + uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum, SmallVectorImpl<MCFixup> &Fixups) const { return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2); } - unsigned getPLT16DBLEncoding(const MCInst &MI, unsigned int OpNum, + uint64_t getPLT16DBLEncoding(const MCInst &MI, unsigned OpNum, SmallVectorImpl<MCFixup> &Fixups) const { return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PLT16DBL, 2); } - unsigned getPLT32DBLEncoding(const MCInst &MI, unsigned int OpNum, + uint64_t getPLT32DBLEncoding(const MCInst &MI, unsigned OpNum, SmallVectorImpl<MCFixup> &Fixups) const { return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PLT32DBL, 2); } @@ -95,34 +108,73 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, } } -unsigned SystemZMCCodeEmitter:: +uint64_t SystemZMCCodeEmitter:: getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl<MCFixup> &Fixups) const { if (MO.isReg()) return Ctx.getRegisterInfo().getEncodingValue(MO.getReg()); if (MO.isImm()) - return static_cast<unsigned>(MO.getImm()); + return static_cast<uint64_t>(MO.getImm()); llvm_unreachable("Unexpected operand type!"); } -unsigned -SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned int OpNum, +uint64_t SystemZMCCodeEmitter:: +getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, + SmallVectorImpl<MCFixup> &Fixups) const { + uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); + uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); + assert(isUInt<4>(Base) && isUInt<12>(Disp)); + return (Base << 12) | Disp; +} + +uint64_t SystemZMCCodeEmitter:: +getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, + SmallVectorImpl<MCFixup> &Fixups) const { + uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); + uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); + assert(isUInt<4>(Base) && isInt<20>(Disp)); + return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12); +} + +uint64_t SystemZMCCodeEmitter:: +getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, + SmallVectorImpl<MCFixup> &Fixups) const { + uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); + uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); + uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups); + assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index)); + return (Index << 16) | (Base << 12) | Disp; +} + +uint64_t SystemZMCCodeEmitter:: +getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, + SmallVectorImpl<MCFixup> &Fixups) const { + uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); + uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); + uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups); + assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index)); + return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8) + | ((Disp & 0xff000) >> 12); +} + +uint64_t +SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum, SmallVectorImpl<MCFixup> &Fixups, unsigned Kind, int64_t Offset) const { const MCOperand &MO = MI.getOperand(OpNum); - // For compatibility with the GNU assembler, treat constant operands as - // unadjusted PC-relative offsets. + const MCExpr *Expr; if (MO.isImm()) - return MO.getImm() / 2; - - const MCExpr *Expr = MO.getExpr(); - if (Offset) { - // The operand value is relative to the start of MI, but the fixup - // is relative to the operand field itself, which is Offset bytes - // into MI. Add Offset to the relocation value to cancel out - // this difference. - const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); - Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx); + Expr = MCConstantExpr::Create(MO.getImm() + Offset, Ctx); + else { + Expr = MO.getExpr(); + if (Offset) { + // The operand value is relative to the start of MI, but the fixup + // is relative to the operand field itself, which is Offset bytes + // into MI. Add Offset to the relocation value to cancel out + // this difference. + const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); + Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx); + } } Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind)); return 0; diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp index 6844f92ec9..3653192d85 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp @@ -27,11 +27,55 @@ using namespace llvm; -static MCAsmInfo *createSystemZMCAsmInfo(StringRef TT) { +const unsigned SystemZMC::GR32Regs[16] = { + SystemZ::R0W, SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, + SystemZ::R4W, SystemZ::R5W, SystemZ::R6W, SystemZ::R7W, + SystemZ::R8W, SystemZ::R9W, SystemZ::R10W, SystemZ::R11W, + SystemZ::R12W, SystemZ::R13W, SystemZ::R14W, SystemZ::R15W +}; + +const unsigned SystemZMC::GR64Regs[16] = { + SystemZ::R0D, SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, + SystemZ::R4D, SystemZ::R5D, SystemZ::R6D, SystemZ::R7D, + SystemZ::R8D, SystemZ::R9D, SystemZ::R10D, SystemZ::R11D, + SystemZ::R12D, SystemZ::R13D, SystemZ::R14D, SystemZ::R15D +}; + +const unsigned SystemZMC::GR128Regs[16] = { + SystemZ::R0Q, 0, SystemZ::R2Q, 0, + SystemZ::R4Q, 0, SystemZ::R6Q, 0, + SystemZ::R8Q, 0, SystemZ::R10Q, 0, + SystemZ::R12Q, 0, SystemZ::R14Q, 0 +}; + +const unsigned SystemZMC::FP32Regs[16] = { + SystemZ::F0S, SystemZ::F1S, SystemZ::F2S, SystemZ::F3S, + SystemZ::F4S, SystemZ::F5S, SystemZ::F6S, SystemZ::F7S, + SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S, + SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S +}; + +const unsigned SystemZMC::FP64Regs[16] = { + SystemZ::F0D, SystemZ::F1D, SystemZ::F2D, SystemZ::F3D, + SystemZ::F4D, SystemZ::F5D, SystemZ::F6D, SystemZ::F7D, + SystemZ::F8D, SystemZ::F9D, SystemZ::F10D, SystemZ::F11D, + SystemZ::F12D, SystemZ::F13D, SystemZ::F14D, SystemZ::F15D +}; + +const unsigned SystemZMC::FP128Regs[16] = { + SystemZ::F0Q, SystemZ::F1Q, 0, 0, + SystemZ::F4Q, SystemZ::F5Q, 0, 0, + SystemZ::F8Q, SystemZ::F9Q, 0, 0, + SystemZ::F12Q, SystemZ::F13Q, 0, 0 +}; + +static MCAsmInfo *createSystemZMCAsmInfo(const MCRegisterInfo &MRI, + StringRef TT) { MCAsmInfo *MAI = new SystemZMCAsmInfo(TT); - MachineLocation FPDst(MachineLocation::VirtualFP); - MachineLocation FPSrc(SystemZ::R15D, -SystemZMC::CFAOffsetFromInitialSP); - MAI->addInitialFrameState(0, FPDst, FPSrc); + MCCFIInstruction Inst = + MCCFIInstruction::createDefCfa(0, MRI.getDwarfRegNum(SystemZ::R15D, true), + SystemZMC::CFAOffsetFromInitialSP); + MAI->addInitialFrameState(Inst); return MAI; } diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h index 229912f161..1f70047db6 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h @@ -34,6 +34,16 @@ namespace SystemZMC { // The offset of the DWARF CFA from the incoming stack pointer. const int64_t CFAOffsetFromInitialSP = CallFrameSize; + + // Maps of asm register numbers to LLVM register numbers, with 0 indicating + // an invalid register. We don't use the register classes directly because + // they specify the allocation order. + extern const unsigned GR32Regs[16]; + extern const unsigned GR64Regs[16]; + extern const unsigned GR128Regs[16]; + extern const unsigned FP32Regs[16]; + extern const unsigned FP64Regs[16]; + extern const unsigned FP128Regs[16]; } MCCodeEmitter *createSystemZMCCodeEmitter(const MCInstrInfo &MCII, diff --git a/lib/Target/SystemZ/Makefile b/lib/Target/SystemZ/Makefile index c992584af9..445725bd1e 100644 --- a/lib/Target/SystemZ/Makefile +++ b/lib/Target/SystemZ/Makefile @@ -16,13 +16,14 @@ BUILT_SOURCES = SystemZGenRegisterInfo.inc \ SystemZGenAsmWriter.inc \ SystemZGenAsmMatcher.inc \ SystemZGenCodeEmitter.inc \ + SystemZGenDisassemblerTables.inc \ SystemZGenInstrInfo.inc \ SystemZGenDAGISel.inc \ SystemZGenSubtargetInfo.inc \ SystemZGenCallingConv.inc \ SystemZGenMCCodeEmitter.inc -DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc +DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/SystemZ/README.txt b/lib/Target/SystemZ/README.txt index d1f56a4916..8f5a5476b4 100644 --- a/lib/Target/SystemZ/README.txt +++ b/lib/Target/SystemZ/README.txt @@ -29,17 +29,44 @@ to load 103. This seems to be a general target-independent problem. -- -The tuning of the choice between Load Address (LA) and addition in +The tuning of the choice between LOAD ADDRESS (LA) and addition in SystemZISelDAGToDAG.cpp is suspect. It should be tweaked based on performance measurements. -- +We don't support tail calls at present. + +-- + +We don't support prefetching yet. + +-- + There is no scheduling support. -- -We don't use the Branch on Count or Branch on Index families of instruction. +We don't use the BRANCH ON COUNT or BRANCH ON INDEX families of instruction. + +-- + +We might want to use BRANCH ON CONDITION for conditional indirect calls +and conditional returns. + +-- + +We don't use the combined COMPARE AND BRANCH instructions. Using them +would require a change to the way we handle out-of-range branches. +At the moment, we start with 32-bit forms like BRCL and shorten them +to forms like BRC where possible, but COMPARE AND BRANCH does not have +a 32-bit form. + +-- + +We should probably model just CC, not the PSW as a whole. Strictly +speaking, every instruction changes the PSW since the PSW contains the +current instruction address. -- @@ -54,7 +81,30 @@ equality after an integer comparison, etc. -- -We don't optimize string and block memory operations. +We don't use the LOAD AND TEST or TEST DATA CLASS instructions. + +-- + +We could use the generic floating-point forms of LOAD COMPLEMENT, +LOAD NEGATIVE and LOAD POSITIVE in cases where we don't need the +condition codes. For example, we could use LCDFR instead of LCDBR. + +-- + +We don't optimize block memory operations. + +It's definitely worth using things like MVC, CLC, NC, XC and OC with +constant lengths. MVCIN may be worthwhile too. + +We should probably implement things like memcpy using MVC with EXECUTE. +Likewise memcmp and CLC. MVCLE and CLCLE could be useful too. + +-- + +We don't optimize string operations. + +MVST, CLST, SRST and CUSE could be useful here. Some of the TRANSLATE +family might be too, although they are probably more difficult to exploit. -- @@ -63,9 +113,33 @@ conventions require f128s to be returned by invisible reference. -- +ADD LOGICAL WITH SIGNED IMMEDIATE could be useful when we need to +produce a carry. SUBTRACT LOGICAL IMMEDIATE could be useful when we +need to produce a borrow. (Note that there are no memory forms of +ADD LOGICAL WITH CARRY and SUBTRACT LOGICAL WITH BORROW, so the high +part of 128-bit memory operations would probably need to be done +via a register.) + +-- + +We don't use the halfword forms of LOAD REVERSED and STORE REVERSED +(LRVH and STRVH). + +-- + +We could take advantage of the various ... UNDER MASK instructions, +such as ICM and STCM. + +-- + +We could make more use of the ROTATE AND ... SELECTED BITS instructions. +At the moment we only use RISBG, and only then for subword atomic operations. + +-- + DAGCombiner can detect integer absolute, but there's not yet an associated -ISD opcode. We could add one and implement it using Load Positive. -Negated absolutes could use Load Negative. +ISD opcode. We could add one and implement it using LOAD POSITIVE. +Negated absolutes could use LOAD NEGATIVE. -- @@ -142,5 +216,15 @@ See CodeGen/SystemZ/alloca-01.ll for an example. -- Atomic loads and stores use the default compare-and-swap based implementation. -This is probably much too conservative in practice, and the overhead is -especially bad for 8- and 16-bit accesses. +This is much too conservative in practice, since the architecture guarantees +that 1-, 2-, 4- and 8-byte loads and stores to aligned addresses are +inherently atomic. + +-- + +If needed, we can support 16-byte atomics using LPQ, STPQ and CSDG. + +-- + +We might want to model all access registers and use them to spill +32-bit values. diff --git a/lib/Target/SystemZ/SystemZInstrFP.td b/lib/Target/SystemZ/SystemZInstrFP.td index 7c9f0e668b..104af6e99d 100644 --- a/lib/Target/SystemZ/SystemZInstrFP.td +++ b/lib/Target/SystemZ/SystemZInstrFP.td @@ -40,24 +40,22 @@ def LDGR : UnaryRRE<"ldgr", 0xB3C1, bitconvert, FP64, GR64>; // fcopysign with an FP32 result. let isCodeGenOnly = 1 in { - def CPSDRss : BinaryRevRRF<"cpsdr", 0xB372, fcopysign, FP32, FP32>; - def CPSDRsd : BinaryRevRRF<"cpsdr", 0xB372, fcopysign, FP32, FP64>; + def CPSDRss : BinaryRRF<"cpsdr", 0xB372, fcopysign, FP32, FP32>; + def CPSDRsd : BinaryRRF<"cpsdr", 0xB372, fcopysign, FP32, FP64>; } -// The sign of an FP128 is in the high register. Give the CPSDRsd -// operands in R1, R2, R3 order. +// The sign of an FP128 is in the high register. def : Pat<(fcopysign FP32:$src1, FP128:$src2), - (CPSDRsd (EXTRACT_SUBREG FP128:$src2, subreg_high), FP32:$src1)>; + (CPSDRsd FP32:$src1, (EXTRACT_SUBREG FP128:$src2, subreg_high))>; // fcopysign with an FP64 result. let isCodeGenOnly = 1 in - def CPSDRds : BinaryRevRRF<"cpsdr", 0xB372, fcopysign, FP64, FP32>; -def CPSDRdd : BinaryRevRRF<"cpsdr", 0xB372, fcopysign, FP64, FP64>; + def CPSDRds : BinaryRRF<"cpsdr", 0xB372, fcopysign, FP64, FP32>; +def CPSDRdd : BinaryRRF<"cpsdr", 0xB372, fcopysign, FP64, FP64>; -// The sign of an FP128 is in the high register. Give the CPSDRdd -// operands in R1, R2, R3 order. +// The sign of an FP128 is in the high register. def : Pat<(fcopysign FP64:$src1, FP128:$src2), - (CPSDRdd (EXTRACT_SUBREG FP128:$src2, subreg_high), FP64:$src1)>; + (CPSDRdd FP64:$src1, (EXTRACT_SUBREG FP128:$src2, subreg_high))>; // fcopysign with an FP128 result. Use "upper" as the high half and leave // the low half as-is. @@ -65,13 +63,12 @@ class CopySign128<RegisterOperand cls, dag upper> : Pat<(fcopysign FP128:$src1, cls:$src2), (INSERT_SUBREG FP128:$src1, upper, subreg_high)>; -// Give the CPSDR* operands in R1, R2, R3 order. -def : CopySign128<FP32, (CPSDRds FP32:$src2, - (EXTRACT_SUBREG FP128:$src1, subreg_high))>; -def : CopySign128<FP64, (CPSDRdd FP64:$src2, - (EXTRACT_SUBREG FP128:$src1, subreg_high))>; -def : CopySign128<FP128, (CPSDRdd (EXTRACT_SUBREG FP128:$src2, subreg_high), - (EXTRACT_SUBREG FP128:$src1, subreg_high))>; +def : CopySign128<FP32, (CPSDRds (EXTRACT_SUBREG FP128:$src1, subreg_high), + FP32:$src2)>; +def : CopySign128<FP64, (CPSDRdd (EXTRACT_SUBREG FP128:$src1, subreg_high), + FP64:$src2)>; +def : CopySign128<FP128, (CPSDRdd (EXTRACT_SUBREG FP128:$src1, subreg_high), + (EXTRACT_SUBREG FP128:$src2, subreg_high))>; //===----------------------------------------------------------------------===// // Load instructions @@ -155,13 +152,13 @@ let Defs = [PSW] in { } // fp_to_sint always rounds towards zero, which is modifier value 5. -def : Pat<(i32 (fp_to_sint FP32:$src)), (CFEBR FP32:$src, 5)>; -def : Pat<(i32 (fp_to_sint FP64:$src)), (CFDBR FP64:$src, 5)>; -def : Pat<(i32 (fp_to_sint FP128:$src)), (CFXBR FP128:$src, 5)>; +def : Pat<(i32 (fp_to_sint FP32:$src)), (CFEBR 5, FP32:$src)>; +def : Pat<(i32 (fp_to_sint FP64:$src)), (CFDBR 5, FP64:$src)>; +def : Pat<(i32 (fp_to_sint FP128:$src)), (CFXBR 5, FP128:$src)>; -def : Pat<(i64 (fp_to_sint FP32:$src)), (CGEBR FP32:$src, 5)>; -def : Pat<(i64 (fp_to_sint FP64:$src)), (CGDBR FP64:$src, 5)>; -def : Pat<(i64 (fp_to_sint FP128:$src)), (CGXBR FP128:$src, 5)>; +def : Pat<(i64 (fp_to_sint FP32:$src)), (CGEBR 5, FP32:$src)>; +def : Pat<(i64 (fp_to_sint FP64:$src)), (CGDBR 5, FP64:$src)>; +def : Pat<(i64 (fp_to_sint FP128:$src)), (CGXBR 5, FP128:$src)>; //===----------------------------------------------------------------------===// // Unary arithmetic @@ -210,9 +207,9 @@ let Defs = [PSW] in { // frint rounds according to the current mode (modifier 0) and detects // inexact conditions. -def : Pat<(frint FP32:$src), (FIEBR FP32:$src, 0)>; -def : Pat<(frint FP64:$src), (FIDBR FP64:$src, 0)>; -def : Pat<(frint FP128:$src), (FIXBR FP128:$src, 0)>; +def : Pat<(frint FP32:$src), (FIEBR 0, FP32:$src)>; +def : Pat<(frint FP64:$src), (FIDBR 0, FP64:$src)>; +def : Pat<(frint FP128:$src), (FIXBR 0, FP128:$src)>; //===----------------------------------------------------------------------===// // Binary arithmetic diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td index b32b7eb0fc..bf5aa8dbeb 100644 --- a/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/lib/Target/SystemZ/SystemZInstrFormats.td @@ -82,25 +82,24 @@ def getDisp20Opcode : InstrMapping { // // Formats are specified using operand field declarations of the form: // -// bits<4> Rn : register input or output for operand n -// bits<m> In : immediate value of width m for operand n -// bits<4> Bn : base register for address operand n -// bits<m> Dn : displacement value of width m for address operand n -// bits<4> Xn : index register for address operand n -// bits<4> Mn : mode value for operand n +// bits<4> Rn : register input or output for operand n +// bits<m> In : immediate value of width m for operand n +// bits<4> BDn : address operand n, which has a base and a displacement +// bits<m> XBDn : address operand n, which has an index, a base and a +// displacement +// bits<4> Xn : index register for address operand n +// bits<4> Mn : mode value for operand n // -// The operand numbers ("n" in the list above) follow the architecture manual, -// but the fields are always declared in assembly order, so there are some -// cases where operand "2" comes after operand "3". For address operands, -// the base register field is declared first, followed by the displacement, -// followed by the index (if any). This matches the bdaddr* and bdxaddr* -// orders. +// The operand numbers ("n" in the list above) follow the architecture manual. +// Assembly operands sometimes have a different order; in particular, R3 often +// is often written between operands 1 and 2. // //===----------------------------------------------------------------------===// class InstRI<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<4, outs, ins, asmstr, pattern> { field bits<32> Inst; + field bits<32> SoftFail = 0; bits<4> R1; bits<16> I2; @@ -114,6 +113,7 @@ class InstRI<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRIEf<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<6, outs, ins, asmstr, pattern> { field bits<48> Inst; + field bits<48> SoftFail = 0; bits<4> R1; bits<4> R2; @@ -133,6 +133,7 @@ class InstRIEf<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRIL<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<6, outs, ins, asmstr, pattern> { field bits<48> Inst; + field bits<48> SoftFail = 0; bits<4> R1; bits<32> I2; @@ -146,6 +147,7 @@ class InstRIL<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRR<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<2, outs, ins, asmstr, pattern> { field bits<16> Inst; + field bits<16> SoftFail = 0; bits<4> R1; bits<4> R2; @@ -158,6 +160,7 @@ class InstRR<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRRD<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<4, outs, ins, asmstr, pattern> { field bits<32> Inst; + field bits<32> SoftFail = 0; bits<4> R1; bits<4> R3; @@ -173,6 +176,7 @@ class InstRRD<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRRE<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<4, outs, ins, asmstr, pattern> { field bits<32> Inst; + field bits<32> SoftFail = 0; bits<4> R1; bits<4> R2; @@ -186,6 +190,7 @@ class InstRRE<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRRF<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<4, outs, ins, asmstr, pattern> { field bits<32> Inst; + field bits<32> SoftFail = 0; bits<4> R1; bits<4> R2; @@ -201,17 +206,14 @@ class InstRRF<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRX<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<4, outs, ins, asmstr, pattern> { field bits<32> Inst; + field bits<32> SoftFail = 0; bits<4> R1; - bits<4> B2; - bits<12> D2; - bits<4> X2; + bits<20> XBD2; let Inst{31-24} = op; let Inst{23-20} = R1; - let Inst{19-16} = X2; - let Inst{15-12} = B2; - let Inst{11-0} = D2; + let Inst{19-0} = XBD2; let HasIndex = 1; } @@ -219,17 +221,14 @@ class InstRX<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRXE<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<6, outs, ins, asmstr, pattern> { field bits<48> Inst; + field bits<48> SoftFail = 0; bits<4> R1; - bits<4> B2; - bits<12> D2; - bits<4> X2; + bits<20> XBD2; let Inst{47-40} = op{15-8}; let Inst{39-36} = R1; - let Inst{35-32} = X2; - let Inst{31-28} = B2; - let Inst{27-16} = D2; + let Inst{35-16} = XBD2; let Inst{15-8} = 0; let Inst{7-0} = op{7-0}; @@ -239,18 +238,15 @@ class InstRXE<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRXF<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<6, outs, ins, asmstr, pattern> { field bits<48> Inst; + field bits<48> SoftFail = 0; bits<4> R1; bits<4> R3; - bits<4> B2; - bits<12> D2; - bits<4> X2; + bits<20> XBD2; let Inst{47-40} = op{15-8}; let Inst{39-36} = R3; - let Inst{35-32} = X2; - let Inst{31-28} = B2; - let Inst{27-16} = D2; + let Inst{35-16} = XBD2; let Inst{15-12} = R1; let Inst{11-8} = 0; let Inst{7-0} = op{7-0}; @@ -261,18 +257,14 @@ class InstRXF<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRXY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<6, outs, ins, asmstr, pattern> { field bits<48> Inst; + field bits<48> SoftFail = 0; bits<4> R1; - bits<4> B2; - bits<20> D2; - bits<4> X2; + bits<28> XBD2; let Inst{47-40} = op{15-8}; let Inst{39-36} = R1; - let Inst{35-32} = X2; - let Inst{31-28} = B2; - let Inst{27-16} = D2{11-0}; - let Inst{15-8} = D2{19-12}; + let Inst{35-8} = XBD2; let Inst{7-0} = op{7-0}; let Has20BitOffset = 1; @@ -282,34 +274,31 @@ class InstRXY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstRS<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<4, outs, ins, asmstr, pattern> { field bits<32> Inst; + field bits<32> SoftFail = 0; bits<4> R1; bits<4> R3; - bits<4> B2; - bits<12> D2; + bits<16> BD2; let Inst{31-24} = op; let Inst{23-20} = R1; let Inst{19-16} = R3; - let Inst{15-12} = B2; - let Inst{11-0} = D2; + let Inst{15-0} = BD2; } class InstRSY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<6, outs, ins, asmstr, pattern> { field bits<48> Inst; + field bits<48> SoftFail = 0; bits<4> R1; bits<4> R3; - bits<4> B2; - bits<20> D2; + bits<24> BD2; let Inst{47-40} = op{15-8}; let Inst{39-36} = R1; let Inst{35-32} = R3; - let Inst{31-28} = B2; - let Inst{27-16} = D2{11-0}; - let Inst{15-8} = D2{19-12}; + let Inst{31-8} = BD2; let Inst{7-0} = op{7-0}; let Has20BitOffset = 1; @@ -318,44 +307,40 @@ class InstRSY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InstSI<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<4, outs, ins, asmstr, pattern> { field bits<32> Inst; + field bits<32> SoftFail = 0; - bits<4> B1; - bits<12> D1; + bits<16> BD1; bits<8> I2; let Inst{31-24} = op; let Inst{23-16} = I2; - let Inst{15-12} = B1; - let Inst{11-0} = D1; + let Inst{15-0} = BD1; } class InstSIL<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<6, outs, ins, asmstr, pattern> { field bits<48> Inst; + field bits<48> SoftFail = 0; - bits<4> B1; - bits<12> D1; + bits<16> BD1; bits<16> I2; let Inst{47-32} = op; - let Inst{31-28} = B1; - let Inst{27-16} = D1; + let Inst{31-16} = BD1; let Inst{15-0} = I2; } class InstSIY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> : InstSystemZ<6, outs, ins, asmstr, pattern> { field bits<48> Inst; + field bits<48> SoftFail = 0; - bits<4> B1; - bits<20> D1; + bits<24> BD1; bits<8> I2; let Inst{47-40} = op{15-8}; let Inst{39-32} = I2; - let Inst{31-28} = B1; - let Inst{27-16} = D1{11-0}; - let Inst{15-8} = D1{19-12}; + let Inst{31-8} = BD1; let Inst{7-0} = op{7-0}; let Has20BitOffset = 1; @@ -432,23 +417,23 @@ class InstSIY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> class InherentRRE<string mnemonic, bits<16> opcode, RegisterOperand cls, dag src> - : InstRRE<opcode, (outs cls:$dst), (ins), - mnemonic#"\t$dst", - [(set cls:$dst, src)]> { + : InstRRE<opcode, (outs cls:$R1), (ins), + mnemonic#"\t$R1", + [(set cls:$R1, src)]> { let R2 = 0; } class LoadMultipleRSY<string mnemonic, bits<16> opcode, RegisterOperand cls> - : InstRSY<opcode, (outs cls:$dst1, cls:$dst2), (ins bdaddr20only:$addr), - mnemonic#"\t$dst1, $dst2, $addr", []> { + : InstRSY<opcode, (outs cls:$R1, cls:$R3), (ins bdaddr20only:$BD2), + mnemonic#"\t$R1, $R3, $BD2", []> { let mayLoad = 1; } class StoreRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, RegisterOperand cls> - : InstRIL<opcode, (outs), (ins cls:$src, pcrel32:$addr), - mnemonic#"\t$src, $addr", - [(operator cls:$src, pcrel32:$addr)]> { + : InstRIL<opcode, (outs), (ins cls:$R1, pcrel32:$I2), + mnemonic#"\t$R1, $I2", + [(operator cls:$R1, pcrel32:$I2)]> { let mayStore = 1; // We want PC-relative addresses to be tried ahead of BD and BDX addresses. // However, BDXs have two extra operands and are therefore 6 units more @@ -458,17 +443,17 @@ class StoreRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, class StoreRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, RegisterOperand cls, AddressingMode mode = bdxaddr12only> - : InstRX<opcode, (outs), (ins cls:$src, mode:$addr), - mnemonic#"\t$src, $addr", - [(operator cls:$src, mode:$addr)]> { + : InstRX<opcode, (outs), (ins cls:$R1, mode:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(operator cls:$R1, mode:$XBD2)]> { let mayStore = 1; } class StoreRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls, AddressingMode mode = bdxaddr20only> - : InstRXY<opcode, (outs), (ins cls:$src, mode:$addr), - mnemonic#"\t$src, $addr", - [(operator cls:$src, mode:$addr)]> { + : InstRXY<opcode, (outs), (ins cls:$R1, mode:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(operator cls:$R1, mode:$XBD2)]> { let mayStore = 1; } @@ -483,32 +468,32 @@ multiclass StoreRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, } class StoreMultipleRSY<string mnemonic, bits<16> opcode, RegisterOperand cls> - : InstRSY<opcode, (outs), (ins cls:$from, cls:$to, bdaddr20only:$addr), - mnemonic#"\t$from, $to, $addr", []> { + : InstRSY<opcode, (outs), (ins cls:$R1, cls:$R3, bdaddr20only:$BD2), + mnemonic#"\t$R1, $R3, $BD2", []> { let mayStore = 1; } class StoreSI<string mnemonic, bits<8> opcode, SDPatternOperator operator, Immediate imm, AddressingMode mode = bdaddr12only> - : InstSI<opcode, (outs), (ins mode:$addr, imm:$src), - mnemonic#"\t$addr, $src", - [(operator imm:$src, mode:$addr)]> { + : InstSI<opcode, (outs), (ins mode:$BD1, imm:$I2), + mnemonic#"\t$BD1, $I2", + [(operator imm:$I2, mode:$BD1)]> { let mayStore = 1; } class StoreSIY<string mnemonic, bits<16> opcode, SDPatternOperator operator, Immediate imm, AddressingMode mode = bdaddr20only> - : InstSIY<opcode, (outs), (ins mode:$addr, imm:$src), - mnemonic#"\t$addr, $src", - [(operator imm:$src, mode:$addr)]> { + : InstSIY<opcode, (outs), (ins mode:$BD1, imm:$I2), + mnemonic#"\t$BD1, $I2", + [(operator imm:$I2, mode:$BD1)]> { let mayStore = 1; } class StoreSIL<string mnemonic, bits<16> opcode, SDPatternOperator operator, Immediate imm> - : InstSIL<opcode, (outs), (ins bdaddr12only:$addr, imm:$src), - mnemonic#"\t$addr, $src", - [(operator imm:$src, bdaddr12only:$addr)]> { + : InstSIL<opcode, (outs), (ins bdaddr12only:$BD1, imm:$I2), + mnemonic#"\t$BD1, $I2", + [(operator imm:$I2, bdaddr12only:$BD1)]> { let mayStore = 1; } @@ -524,38 +509,38 @@ multiclass StoreSIPair<string mnemonic, bits<8> siOpcode, bits<16> siyOpcode, class UnaryRR<string mnemonic, bits<8> opcode, SDPatternOperator operator, RegisterOperand cls1, RegisterOperand cls2> - : InstRR<opcode, (outs cls1:$dst), (ins cls2:$src), - mnemonic#"\t$dst, $src", - [(set cls1:$dst, (operator cls2:$src))]>; + : InstRR<opcode, (outs cls1:$R1), (ins cls2:$R2), + mnemonic#"\t$R1, $R2", + [(set cls1:$R1, (operator cls2:$R2))]>; class UnaryRRE<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls1, RegisterOperand cls2> - : InstRRE<opcode, (outs cls1:$dst), (ins cls2:$src), - mnemonic#"\t$dst, $src", - [(set cls1:$dst, (operator cls2:$src))]>; + : InstRRE<opcode, (outs cls1:$R1), (ins cls2:$R2), + mnemonic#"\t$R1, $R2", + [(set cls1:$R1, (operator cls2:$R2))]>; class UnaryRRF<string mnemonic, bits<16> opcode, RegisterOperand cls1, RegisterOperand cls2> - : InstRRF<opcode, (outs cls1:$dst), (ins cls2:$src, uimm8zx4:$mode), - mnemonic#"\t$dst, $mode, $src", []>; + : InstRRF<opcode, (outs cls1:$R1), (ins uimm8zx4:$R3, cls2:$R2), + mnemonic#"\t$R1, $R3, $R2", []>; class UnaryRI<string mnemonic, bits<12> opcode, SDPatternOperator operator, RegisterOperand cls, Immediate imm> - : InstRI<opcode, (outs cls:$dst), (ins imm:$src), - mnemonic#"\t$dst, $src", - [(set cls:$dst, (operator imm:$src))]>; + : InstRI<opcode, (outs cls:$R1), (ins imm:$I2), + mnemonic#"\t$R1, $I2", + [(set cls:$R1, (operator imm:$I2))]>; class UnaryRIL<string mnemonic, bits<12> opcode, SDPatternOperator operator, RegisterOperand cls, Immediate imm> - : InstRIL<opcode, (outs cls:$dst), (ins imm:$src), - mnemonic#"\t$dst, $src", - [(set cls:$dst, (operator imm:$src))]>; + : InstRIL<opcode, (outs cls:$R1), (ins imm:$I2), + mnemonic#"\t$R1, $I2", + [(set cls:$R1, (operator imm:$I2))]>; class UnaryRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, RegisterOperand cls> - : InstRIL<opcode, (outs cls:$dst), (ins pcrel32:$addr), - mnemonic#"\t$dst, $addr", - [(set cls:$dst, (operator pcrel32:$addr))]> { + : InstRIL<opcode, (outs cls:$R1), (ins pcrel32:$I2), + mnemonic#"\t$R1, $I2", + [(set cls:$R1, (operator pcrel32:$I2))]> { let mayLoad = 1; // We want PC-relative addresses to be tried ahead of BD and BDX addresses. // However, BDXs have two extra operands and are therefore 6 units more @@ -565,25 +550,25 @@ class UnaryRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, class UnaryRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, RegisterOperand cls, AddressingMode mode = bdxaddr12only> - : InstRX<opcode, (outs cls:$dst), (ins mode:$addr), - mnemonic#"\t$dst, $addr", - [(set cls:$dst, (operator mode:$addr))]> { + : InstRX<opcode, (outs cls:$R1), (ins mode:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(set cls:$R1, (operator mode:$XBD2))]> { let mayLoad = 1; } class UnaryRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls> - : InstRXE<opcode, (outs cls:$dst), (ins bdxaddr12only:$addr), - mnemonic#"\t$dst, $addr", - [(set cls:$dst, (operator bdxaddr12only:$addr))]> { + : InstRXE<opcode, (outs cls:$R1), (ins bdxaddr12only:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(set cls:$R1, (operator bdxaddr12only:$XBD2))]> { let mayLoad = 1; } class UnaryRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls, AddressingMode mode = bdxaddr20only> - : InstRXY<opcode, (outs cls:$dst), (ins mode:$addr), - mnemonic#"\t$dst, $addr", - [(set cls:$dst, (operator mode:$addr))]> { + : InstRXY<opcode, (outs cls:$R1), (ins mode:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(set cls:$R1, (operator mode:$XBD2))]> { let mayLoad = 1; } @@ -599,83 +584,76 @@ multiclass UnaryRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, class BinaryRR<string mnemonic, bits<8> opcode, SDPatternOperator operator, RegisterOperand cls1, RegisterOperand cls2> - : InstRR<opcode, (outs cls1:$dst), (ins cls1:$src1, cls2:$src2), - mnemonic#"\t$dst, $src2", - [(set cls1:$dst, (operator cls1:$src1, cls2:$src2))]> { - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + : InstRR<opcode, (outs cls1:$R1), (ins cls1:$R1src, cls2:$R2), + mnemonic#"\t$R1, $R2", + [(set cls1:$R1, (operator cls1:$R1src, cls2:$R2))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; } class BinaryRRE<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls1, RegisterOperand cls2> - : InstRRE<opcode, (outs cls1:$dst), (ins cls1:$src1, cls2:$src2), - mnemonic#"\t$dst, $src2", - [(set cls1:$dst, (operator cls1:$src1, cls2:$src2))]> { - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + : InstRRE<opcode, (outs cls1:$R1), (ins cls1:$R1src, cls2:$R2), + mnemonic#"\t$R1, $R2", + [(set cls1:$R1, (operator cls1:$R1src, cls2:$R2))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; } -// Here the assembly and dag operands are in natural order, -// but the first input operand maps to R3 and the second to R2. -// This is used for "CPSDR R1, R3, R2", which is equivalent to -// R1 = copysign (R3, R2). -// -// Direct uses of the instruction must pass operands in encoding order -- -// R1, R2, R3 -- so they must pass the source operands in reverse order. -class BinaryRevRRF<string mnemonic, bits<16> opcode, SDPatternOperator operator, - RegisterOperand cls1, RegisterOperand cls2> - : InstRRF<opcode, (outs cls1:$dst), (ins cls2:$src2, cls1:$src1), - mnemonic#"\t$dst, $src1, $src2", - [(set cls1:$dst, (operator cls1:$src1, cls2:$src2))]>; +class BinaryRRF<string mnemonic, bits<16> opcode, SDPatternOperator operator, + RegisterOperand cls1, RegisterOperand cls2> + : InstRRF<opcode, (outs cls1:$R1), (ins cls1:$R3, cls2:$R2), + mnemonic#"\t$R1, $R3, $R2", + [(set cls1:$R1, (operator cls1:$R3, cls2:$R2))]>; class BinaryRI<string mnemonic, bits<12> opcode, SDPatternOperator operator, RegisterOperand cls, Immediate imm> - : InstRI<opcode, (outs cls:$dst), (ins cls:$src1, imm:$src2), - mnemonic#"\t$dst, $src2", - [(set cls:$dst, (operator cls:$src1, imm:$src2))]> { - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + : InstRI<opcode, (outs cls:$R1), (ins cls:$R1src, imm:$I2), + mnemonic#"\t$R1, $I2", + [(set cls:$R1, (operator cls:$R1src, imm:$I2))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; } class BinaryRIL<string mnemonic, bits<12> opcode, SDPatternOperator operator, RegisterOperand cls, Immediate imm> - : InstRIL<opcode, (outs cls:$dst), (ins cls:$src1, imm:$src2), - mnemonic#"\t$dst, $src2", - [(set cls:$dst, (operator cls:$src1, imm:$src2))]> { - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + : InstRIL<opcode, (outs cls:$R1), (ins cls:$R1src, imm:$I2), + mnemonic#"\t$R1, $I2", + [(set cls:$R1, (operator cls:$R1src, imm:$I2))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; } class BinaryRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, RegisterOperand cls, SDPatternOperator load, AddressingMode mode = bdxaddr12only> - : InstRX<opcode, (outs cls:$dst), (ins cls:$src1, mode:$src2), - mnemonic#"\t$dst, $src2", - [(set cls:$dst, (operator cls:$src1, (load mode:$src2)))]> { - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + : InstRX<opcode, (outs cls:$R1), (ins cls:$R1src, mode:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(set cls:$R1, (operator cls:$R1src, (load mode:$XBD2)))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; let mayLoad = 1; } class BinaryRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls, SDPatternOperator load> - : InstRXE<opcode, (outs cls:$dst), (ins cls:$src1, bdxaddr12only:$src2), - mnemonic#"\t$dst, $src2", - [(set cls:$dst, (operator cls:$src1, - (load bdxaddr12only:$src2)))]> { - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + : InstRXE<opcode, (outs cls:$R1), (ins cls:$R1src, bdxaddr12only:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(set cls:$R1, (operator cls:$R1src, + (load bdxaddr12only:$XBD2)))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; let mayLoad = 1; } class BinaryRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls, SDPatternOperator load, AddressingMode mode = bdxaddr20only> - : InstRXY<opcode, (outs cls:$dst), (ins cls:$src1, mode:$src2), - mnemonic#"\t$dst, $src2", - [(set cls:$dst, (operator cls:$src1, (load mode:$src2)))]> { - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + : InstRXY<opcode, (outs cls:$R1), (ins cls:$R1src, mode:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(set cls:$R1, (operator cls:$R1src, (load mode:$XBD2)))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; let mayLoad = 1; } @@ -693,18 +671,18 @@ multiclass BinaryRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, class BinarySI<string mnemonic, bits<8> opcode, SDPatternOperator operator, Operand imm, AddressingMode mode = bdaddr12only> - : InstSI<opcode, (outs), (ins mode:$addr, imm:$src), - mnemonic#"\t$addr, $src", - [(store (operator (load mode:$addr), imm:$src), mode:$addr)]> { + : InstSI<opcode, (outs), (ins mode:$BD1, imm:$I2), + mnemonic#"\t$BD1, $I2", + [(store (operator (load mode:$BD1), imm:$I2), mode:$BD1)]> { let mayLoad = 1; let mayStore = 1; } class BinarySIY<string mnemonic, bits<16> opcode, SDPatternOperator operator, Operand imm, AddressingMode mode = bdaddr20only> - : InstSIY<opcode, (outs), (ins mode:$addr, imm:$src), - mnemonic#"\t$addr, $src", - [(store (operator (load mode:$addr), imm:$src), mode:$addr)]> { + : InstSIY<opcode, (outs), (ins mode:$BD1, imm:$I2), + mnemonic#"\t$BD1, $I2", + [(store (operator (load mode:$BD1), imm:$I2), mode:$BD1)]> { let mayLoad = 1; let mayStore = 1; } @@ -722,49 +700,49 @@ multiclass BinarySIPair<string mnemonic, bits<8> siOpcode, class ShiftRS<string mnemonic, bits<8> opcode, SDPatternOperator operator, RegisterOperand cls, AddressingMode mode> - : InstRS<opcode, (outs cls:$dst), (ins cls:$src1, mode:$src2), - mnemonic#"\t$dst, $src2", - [(set cls:$dst, (operator cls:$src1, mode:$src2))]> { + : InstRS<opcode, (outs cls:$R1), (ins cls:$R1src, mode:$BD2), + mnemonic#"\t$R1, $BD2", + [(set cls:$R1, (operator cls:$R1src, mode:$BD2))]> { let R3 = 0; - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; } class ShiftRSY<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls, AddressingMode mode> - : InstRSY<opcode, (outs cls:$dst), (ins cls:$src1, mode:$src2), - mnemonic#"\t$dst, $src1, $src2", - [(set cls:$dst, (operator cls:$src1, mode:$src2))]>; + : InstRSY<opcode, (outs cls:$R1), (ins cls:$R3, mode:$BD2), + mnemonic#"\t$R1, $R3, $BD2", + [(set cls:$R1, (operator cls:$R3, mode:$BD2))]>; class CompareRR<string mnemonic, bits<8> opcode, SDPatternOperator operator, RegisterOperand cls1, RegisterOperand cls2> - : InstRR<opcode, (outs), (ins cls1:$src1, cls2:$src2), - mnemonic#"\t$src1, $src2", - [(operator cls1:$src1, cls2:$src2)]>; + : InstRR<opcode, (outs), (ins cls1:$R1, cls2:$R2), + mnemonic#"\t$R1, $R2", + [(operator cls1:$R1, cls2:$R2)]>; class CompareRRE<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls1, RegisterOperand cls2> - : InstRRE<opcode, (outs), (ins cls1:$src1, cls2:$src2), - mnemonic#"\t$src1, $src2", - [(operator cls1:$src1, cls2:$src2)]>; + : InstRRE<opcode, (outs), (ins cls1:$R1, cls2:$R2), + mnemonic#"\t$R1, $R2", + [(operator cls1:$R1, cls2:$R2)]>; class CompareRI<string mnemonic, bits<12> opcode, SDPatternOperator operator, RegisterOperand cls, Immediate imm> - : InstRI<opcode, (outs), (ins cls:$src1, imm:$src2), - mnemonic#"\t$src1, $src2", - [(operator cls:$src1, imm:$src2)]>; + : InstRI<opcode, (outs), (ins cls:$R1, imm:$I2), + mnemonic#"\t$R1, $I2", + [(operator cls:$R1, imm:$I2)]>; class CompareRIL<string mnemonic, bits<12> opcode, SDPatternOperator operator, RegisterOperand cls, Immediate imm> - : InstRIL<opcode, (outs), (ins cls:$src1, imm:$src2), - mnemonic#"\t$src1, $src2", - [(operator cls:$src1, imm:$src2)]>; + : InstRIL<opcode, (outs), (ins cls:$R1, imm:$I2), + mnemonic#"\t$R1, $I2", + [(operator cls:$R1, imm:$I2)]>; class CompareRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, RegisterOperand cls, SDPatternOperator load> - : InstRIL<opcode, (outs), (ins cls:$src1, pcrel32:$src2), - mnemonic#"\t$src1, $src2", - [(operator cls:$src1, (load pcrel32:$src2))]> { + : InstRIL<opcode, (outs), (ins cls:$R1, pcrel32:$I2), + mnemonic#"\t$R1, $I2", + [(operator cls:$R1, (load pcrel32:$I2))]> { let mayLoad = 1; // We want PC-relative addresses to be tried ahead of BD and BDX addresses. // However, BDXs have two extra operands and are therefore 6 units more @@ -775,26 +753,26 @@ class CompareRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, class CompareRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, RegisterOperand cls, SDPatternOperator load, AddressingMode mode = bdxaddr12only> - : InstRX<opcode, (outs), (ins cls:$src1, mode:$src2), - mnemonic#"\t$src1, $src2", - [(operator cls:$src1, (load mode:$src2))]> { + : InstRX<opcode, (outs), (ins cls:$R1, mode:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(operator cls:$R1, (load mode:$XBD2))]> { let mayLoad = 1; } class CompareRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls, SDPatternOperator load> - : InstRXE<opcode, (outs), (ins cls:$src1, bdxaddr12only:$src2), - mnemonic#"\t$src1, $src2", - [(operator cls:$src1, (load bdxaddr12only:$src2))]> { + : InstRXE<opcode, (outs), (ins cls:$R1, bdxaddr12only:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(operator cls:$R1, (load bdxaddr12only:$XBD2))]> { let mayLoad = 1; } class CompareRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls, SDPatternOperator load, AddressingMode mode = bdxaddr20only> - : InstRXY<opcode, (outs), (ins cls:$src1, mode:$src2), - mnemonic#"\t$src1, $src2", - [(operator cls:$src1, (load mode:$src2))]> { + : InstRXY<opcode, (outs), (ins cls:$R1, mode:$XBD2), + mnemonic#"\t$R1, $XBD2", + [(operator cls:$R1, (load mode:$XBD2))]> { let mayLoad = 1; } @@ -814,26 +792,26 @@ multiclass CompareRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, class CompareSI<string mnemonic, bits<8> opcode, SDPatternOperator operator, SDPatternOperator load, Immediate imm, AddressingMode mode = bdaddr12only> - : InstSI<opcode, (outs), (ins mode:$addr, imm:$src), - mnemonic#"\t$addr, $src", - [(operator (load mode:$addr), imm:$src)]> { + : InstSI<opcode, (outs), (ins mode:$BD1, imm:$I2), + mnemonic#"\t$BD1, $I2", + [(operator (load mode:$BD1), imm:$I2)]> { let mayLoad = 1; } class CompareSIL<string mnemonic, bits<16> opcode, SDPatternOperator operator, SDPatternOperator load, Immediate imm> - : InstSIL<opcode, (outs), (ins bdaddr12only:$addr, imm:$src), - mnemonic#"\t$addr, $src", - [(operator (load bdaddr12only:$addr), imm:$src)]> { + : InstSIL<opcode, (outs), (ins bdaddr12only:$BD1, imm:$I2), + mnemonic#"\t$BD1, $I2", + [(operator (load bdaddr12only:$BD1), imm:$I2)]> { let mayLoad = 1; } class CompareSIY<string mnemonic, bits<16> opcode, SDPatternOperator operator, SDPatternOperator load, Immediate imm, AddressingMode mode = bdaddr20only> - : InstSIY<opcode, (outs), (ins mode:$addr, imm:$src), - mnemonic#"\t$addr, $src", - [(operator (load mode:$addr), imm:$src)]> { + : InstSIY<opcode, (outs), (ins mode:$BD1, imm:$I2), + mnemonic#"\t$BD1, $I2", + [(operator (load mode:$BD1), imm:$I2)]> { let mayLoad = 1; } @@ -851,43 +829,43 @@ multiclass CompareSIPair<string mnemonic, bits<8> siOpcode, bits<16> siyOpcode, class TernaryRRD<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls> - : InstRRD<opcode, (outs cls:$dst), (ins cls:$src1, cls:$src2, cls:$src3), - mnemonic#"\t$dst, $src2, $src3", - [(set cls:$dst, (operator cls:$src1, cls:$src2, cls:$src3))]> { - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + : InstRRD<opcode, (outs cls:$R1), (ins cls:$R1src, cls:$R3, cls:$R2), + mnemonic#"\t$R1, $R3, $R2", + [(set cls:$R1, (operator cls:$R1src, cls:$R3, cls:$R2))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; } class TernaryRXF<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls, SDPatternOperator load> - : InstRXF<opcode, (outs cls:$dst), - (ins cls:$src1, cls:$src2, bdxaddr12only:$src3), - mnemonic#"\t$dst, $src2, $src3", - [(set cls:$dst, (operator cls:$src1, cls:$src2, - (load bdxaddr12only:$src3)))]> { - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + : InstRXF<opcode, (outs cls:$R1), + (ins cls:$R1src, cls:$R3, bdxaddr12only:$XBD2), + mnemonic#"\t$R1, $R3, $XBD2", + [(set cls:$R1, (operator cls:$R1src, cls:$R3, + (load bdxaddr12only:$XBD2)))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; let mayLoad = 1; } class CmpSwapRS<string mnemonic, bits<8> opcode, SDPatternOperator operator, RegisterOperand cls, AddressingMode mode = bdaddr12only> - : InstRS<opcode, (outs cls:$dst), (ins cls:$old, cls:$new, mode:$ptr), - mnemonic#"\t$dst, $new, $ptr", - [(set cls:$dst, (operator mode:$ptr, cls:$old, cls:$new))]> { - let Constraints = "$old = $dst"; - let DisableEncoding = "$old"; + : InstRS<opcode, (outs cls:$R1), (ins cls:$R1src, cls:$R3, mode:$BD2), + mnemonic#"\t$R1, $R3, $BD2", + [(set cls:$R1, (operator mode:$BD2, cls:$R1src, cls:$R3))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; let mayLoad = 1; let mayStore = 1; } class CmpSwapRSY<string mnemonic, bits<16> opcode, SDPatternOperator operator, RegisterOperand cls, AddressingMode mode = bdaddr20only> - : InstRSY<opcode, (outs cls:$dst), (ins cls:$old, cls:$new, mode:$ptr), - mnemonic#"\t$dst, $new, $ptr", - [(set cls:$dst, (operator mode:$ptr, cls:$old, cls:$new))]> { - let Constraints = "$old = $dst"; - let DisableEncoding = "$old"; + : InstRSY<opcode, (outs cls:$R1), (ins cls:$R1src, cls:$R3, mode:$BD2), + mnemonic#"\t$R1, $R3, $BD2", + [(set cls:$R1, (operator mode:$BD2, cls:$R1src, cls:$R3))]> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; let mayLoad = 1; let mayStore = 1; } @@ -904,12 +882,12 @@ multiclass CmpSwapRSPair<string mnemonic, bits<8> rsOpcode, bits<16> rsyOpcode, class RotateSelectRIEf<string mnemonic, bits<16> opcode, RegisterOperand cls1, RegisterOperand cls2> - : InstRIEf<opcode, (outs cls1:$dst), - (ins cls1:$src1, cls2:$src2, - uimm8zx6:$imm1, uimm8zx6:$imm2, uimm8zx6:$imm3), - mnemonic#"\t$dst, $src2, $imm1, $imm2, $imm3", []> { - let Constraints = "$src1 = $dst"; - let DisableEncoding = "$src1"; + : InstRIEf<opcode, (outs cls1:$R1), + (ins cls1:$R1src, cls2:$R2, + uimm8zx6:$I3, uimm8zx6:$I4, uimm8zx6:$I5), + mnemonic#"\t$R1, $R2, $I3, $I4, $I5", []> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index 7ffa382d36..903fb740a4 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -42,20 +42,19 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1, hasCtrlDep = 1, // Unconditional branches. R1 is the condition-code mask (all 1s). let isBranch = 1, isTerminator = 1, isBarrier = 1, R1 = 15 in { let isIndirectBranch = 1 in - def BR : InstRR<0x07, (outs), (ins ADDR64:$dst), - "br\t$dst", [(brind ADDR64:$dst)]>; + def BR : InstRR<0x07, (outs), (ins ADDR64:$R2), + "br\t$R2", [(brind ADDR64:$R2)]>; // An assembler extended mnemonic for BRC. Use a separate instruction for // the asm parser, so that we don't relax Js to external symbols into JGs. let isCodeGenOnly = 1 in - def J : InstRI<0xA74, (outs), (ins brtarget16:$dst), "j\t$dst", []>; - let isAsmParserOnly = 1 in - def AsmJ : InstRI<0xA74, (outs), (ins brtarget16:$dst), "j\t$dst", []>; + def J : InstRI<0xA74, (outs), (ins brtarget16:$I2), "j\t$I2", []>; + def AsmJ : InstRI<0xA74, (outs), (ins brtarget16:$I2), "j\t$I2", []>; // An assembler extended mnemonic for BRCL. (The extension is "G" // rather than "L" because "JL" is "Jump if Less".) - def JG : InstRIL<0xC04, (outs), (ins brtarget32:$dst), - "jg\t$dst", [(br bb:$dst)]>; + def JG : InstRIL<0xC04, (outs), (ins brtarget32:$I2), + "jg\t$I2", [(br bb:$I2)]>; } // Conditional branches. It's easier for LLVM to handle these branches @@ -64,42 +63,39 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, R1 = 15 in { // JE and JLH when writing out the assembly though. multiclass CondBranches<Operand imm, string short, string long> { let isBranch = 1, isTerminator = 1, Uses = [PSW] in { - def "" : InstRI<0xA74, (outs), (ins imm:$cond, brtarget16:$dst), short, []>; - def L : InstRIL<0xC04, (outs), (ins imm:$cond, brtarget32:$dst), long, []>; + def "" : InstRI<0xA74, (outs), (ins imm:$R1, brtarget16:$I2), short, []>; + def L : InstRIL<0xC04, (outs), (ins imm:$R1, brtarget32:$I2), long, []>; } } let isCodeGenOnly = 1 in - defm BRC : CondBranches<cond4, "j$cond\t$dst", "jg$cond\t$dst">; -let isAsmParserOnly = 1 in - defm AsmBRC : CondBranches<uimm8zx4, "brc\t$cond, $dst", "brcl\t$cond, $dst">; + defm BRC : CondBranches<cond4, "j$R1\t$I2", "jg$R1\t$I2">; +defm AsmBRC : CondBranches<uimm8zx4, "brc\t$R1, $I2", "brcl\t$R1, $I2">; def : Pat<(z_br_ccmask cond4:$cond, bb:$dst), (BRCL cond4:$cond, bb:$dst)>; // Define AsmParser mnemonics for each condition code. multiclass CondExtendedMnemonic<bits<4> Cond, string name> { let R1 = Cond in { - def "" : InstRI<0xA74, (outs), (ins brtarget16:$dst), - "j"##name##"\t$dst", []>; - def L : InstRIL<0xC04, (outs), (ins brtarget32:$dst), - "jg"##name##"\t$dst", []>; + def "" : InstRI<0xA74, (outs), (ins brtarget16:$I2), + "j"##name##"\t$I2", []>; + def L : InstRIL<0xC04, (outs), (ins brtarget32:$I2), + "jg"##name##"\t$I2", []>; } } -let isAsmParserOnly = 1 in { - defm AsmJO : CondExtendedMnemonic<1, "o">; - defm AsmJH : CondExtendedMnemonic<2, "h">; - defm AsmJNLE : CondExtendedMnemonic<3, "nle">; - defm AsmJL : CondExtendedMnemonic<4, "l">; - defm AsmJNHE : CondExtendedMnemonic<5, "nhe">; - defm AsmJLH : CondExtendedMnemonic<6, "lh">; - defm AsmJNE : CondExtendedMnemonic<7, "ne">; - defm AsmJE : CondExtendedMnemonic<8, "e">; - defm AsmJNLH : CondExtendedMnemonic<9, "nlh">; - defm AsmJHE : CondExtendedMnemonic<10, "he">; - defm AsmJNL : CondExtendedMnemonic<11, "nl">; - defm AsmJLE : CondExtendedMnemonic<12, "le">; - defm AsmJNH : CondExtendedMnemonic<13, "nh">; - defm AsmJNO : CondExtendedMnemonic<14, "no">; -} +defm AsmJO : CondExtendedMnemonic<1, "o">; +defm AsmJH : CondExtendedMnemonic<2, "h">; +defm AsmJNLE : CondExtendedMnemonic<3, "nle">; +defm AsmJL : CondExtendedMnemonic<4, "l">; +defm AsmJNHE : CondExtendedMnemonic<5, "nhe">; +defm AsmJLH : CondExtendedMnemonic<6, "lh">; +defm AsmJNE : CondExtendedMnemonic<7, "ne">; +defm AsmJE : CondExtendedMnemonic<8, "e">; +defm AsmJNLH : CondExtendedMnemonic<9, "nlh">; +defm AsmJHE : CondExtendedMnemonic<10, "he">; +defm AsmJNL : CondExtendedMnemonic<11, "nl">; +defm AsmJLE : CondExtendedMnemonic<12, "le">; +defm AsmJNH : CondExtendedMnemonic<13, "nh">; +defm AsmJNO : CondExtendedMnemonic<14, "no">; def Select32 : SelectWrapper<GR32>; def Select64 : SelectWrapper<GR64>; @@ -112,24 +108,22 @@ def Select64 : SelectWrapper<GR64>; let isCall = 1, Defs = [R0D, R1D, R2D, R3D, R4D, R5D, R14D, F0D, F1D, F2D, F3D, F4D, F5D, F6D, F7D], R1 = 14, isCodeGenOnly = 1 in { - def BRAS : InstRI<0xA75, (outs), (ins pcrel16call:$dst, variable_ops), - "bras\t%r14, $dst", []>; - def BRASL : InstRIL<0xC05, (outs), (ins pcrel32call:$dst, variable_ops), - "brasl\t%r14, $dst", [(z_call pcrel32call:$dst)]>; - def BASR : InstRR<0x0D, (outs), (ins ADDR64:$dst, variable_ops), - "basr\t%r14, $dst", [(z_call ADDR64:$dst)]>; + def BRAS : InstRI<0xA75, (outs), (ins pcrel16call:$I2, variable_ops), + "bras\t%r14, $I2", []>; + def BRASL : InstRIL<0xC05, (outs), (ins pcrel32call:$I2, variable_ops), + "brasl\t%r14, $I2", [(z_call pcrel32call:$I2)]>; + def BASR : InstRR<0x0D, (outs), (ins ADDR64:$R2, variable_ops), + "basr\t%r14, $R2", [(z_call ADDR64:$R2)]>; } // Define the general form of the call instructions for the asm parser. // These instructions don't hard-code %r14 as the return address register. -let isAsmParserOnly = 1 in { - def AsmBRAS : InstRI<0xA75, (outs), (ins GR64:$save, brtarget16:$dst), - "bras\t$save, $dst", []>; - def AsmBRASL : InstRIL<0xC05, (outs), (ins GR64:$save, brtarget32:$dst), - "brasl\t$save, $dst", []>; - def AsmBASR : InstRR<0x0D, (outs), (ins GR64:$save, ADDR64:$dst), - "basr\t$save, $dst", []>; -} +def AsmBRAS : InstRI<0xA75, (outs), (ins GR64:$R1, brtarget16:$I2), + "bras\t$R1, $I2", []>; +def AsmBRASL : InstRIL<0xC05, (outs), (ins GR64:$R1, brtarget32:$I2), + "brasl\t$R1, $I2", []>; +def AsmBASR : InstRR<0x0D, (outs), (ins GR64:$R1, ADDR64:$R2), + "basr\t$R1, $R2", []>; //===----------------------------------------------------------------------===// // Move instructions @@ -337,21 +331,21 @@ def STRVG : StoreRXY<"strvg", 0xE32F, storeu<bswap>, GR64>; // Load BDX-style addresses. let neverHasSideEffects = 1, Function = "la" in { let PairType = "12" in - def LA : InstRX<0x41, (outs GR64:$dst), (ins laaddr12pair:$src), - "la\t$dst, $src", - [(set GR64:$dst, laaddr12pair:$src)]>; + def LA : InstRX<0x41, (outs GR64:$R1), (ins laaddr12pair:$XBD2), + "la\t$R1, $XBD2", + [(set GR64:$R1, laaddr12pair:$XBD2)]>; let PairType = "20" in - def LAY : InstRXY<0xE371, (outs GR64:$dst), (ins laaddr20pair:$src), - "lay\t$dst, $src", - [(set GR64:$dst, laaddr20pair:$src)]>; + def LAY : InstRXY<0xE371, (outs GR64:$R1), (ins laaddr20pair:$XBD2), + "lay\t$R1, $XBD2", + [(set GR64:$R1, laaddr20pair:$XBD2)]>; } // Load a PC-relative address. There's no version of this instruction // with a 16-bit offset, so there's no relaxation. let neverHasSideEffects = 1 in { - def LARL : InstRIL<0xC00, (outs GR64:$dst), (ins pcrel32:$src), - "larl\t$dst, $src", - [(set GR64:$dst, pcrel32:$src)]>; + def LARL : InstRIL<0xC00, (outs GR64:$R1), (ins pcrel32:$I2), + "larl\t$R1, $I2", + [(set GR64:$R1, pcrel32:$I2)]>; } //===----------------------------------------------------------------------===// @@ -484,6 +478,7 @@ let Defs = [PSW] in { def SGR : BinaryRRE<"sgr", 0xB909, sub, GR64, GR64>; // Subtraction of memory. + defm SH : BinaryRXPair<"sh", 0x4B, 0xE37B, sub, GR32, sextloadi16>; defm S : BinaryRXPair<"s", 0x5B, 0xE35B, sub, GR32, load>; def SGF : BinaryRXY<"sgf", 0xE319, sub, GR64, sextloadi32>; def SG : BinaryRXY<"sg", 0xE309, sub, GR64, load>; @@ -903,9 +898,9 @@ let Defs = [PSW] in { // Read a 32-bit access register into a GR32. As with all GR32 operations, // the upper 32 bits of the enclosing GR64 remain unchanged, which is useful // when a 64-bit address is stored in a pair of access registers. -def EAR : InstRRE<0xB24F, (outs GR32:$dst), (ins access_reg:$src), - "ear\t$dst, $src", - [(set GR32:$dst, (z_extract_access access_reg:$src))]>; +def EAR : InstRRE<0xB24F, (outs GR32:$R1), (ins access_reg:$R2), + "ear\t$R1, $R2", + [(set GR32:$R1, (z_extract_access access_reg:$R2))]>; // Find leftmost one, AKA count leading zeros. The instruction actually // returns a pair of GR64s, the first giving the number of leading zeros diff --git a/lib/Target/SystemZ/SystemZOperands.td b/lib/Target/SystemZ/SystemZOperands.td index 0abc3f7517..66d9c5fceb 100644 --- a/lib/Target/SystemZ/SystemZOperands.td +++ b/lib/Target/SystemZ/SystemZOperands.td @@ -24,14 +24,30 @@ class ImmediateAsmOperand<string name> class Immediate<ValueType vt, code pred, SDNodeXForm xform, string asmop> : PatLeaf<(vt imm), pred, xform>, Operand<vt> { let PrintMethod = "print"##asmop##"Operand"; + let DecoderMethod = "decode"##asmop##"Operand"; let ParserMatchClass = !cast<AsmOperandClass>(asmop); } +// Constructs an asm operand for a PC-relative address. SIZE says how +// many bits there are. +class PCRelAsmOperand<string size> : ImmediateAsmOperand<"PCRel"##size> { + let PredicateMethod = "isImm"; + let ParserMethod = "parsePCRel"##size; +} + +// Constructs an operand for a PC-relative address with address type VT. +// ASMOP is the associated asm operand. +class PCRelOperand<ValueType vt, AsmOperandClass asmop> : Operand<vt> { + let PrintMethod = "printPCRelOperand"; + let ParserMatchClass = asmop; +} + // Constructs both a DAG pattern and instruction operand for a PC-relative -// address with address size VT. SELF is the name of the operand. -class PCRelAddress<ValueType vt, string self> +// address with address size VT. SELF is the name of the operand and +// ASMOP is the associated asm operand. +class PCRelAddress<ValueType vt, string self, AsmOperandClass asmop> : ComplexPattern<vt, 1, "selectPCRelAddress", [z_pcrel_wrapper]>, - Operand<vt> { + PCRelOperand<vt, asmop> { let MIOperandInfo = (ops !cast<Operand>(self)); } @@ -45,11 +61,14 @@ class AddressAsmOperand<string format, string bitsize, string dispsize> } // Constructs both a DAG pattern and instruction operand for an addressing mode. -// The mode is selected by custom code in selectTYPE...SUFFIX(). The address -// registers have BITSIZE bits and displacements have DISPSIZE bits. NUMOPS is -// the number of operands that make up an address and OPERANDS lists the types -// of those operands using (ops ...). FORMAT is the type of addressing mode, -// which needs to match the names used in AddressAsmOperand. +// The mode is selected by custom code in select<TYPE><DISPSIZE><SUFFIX>(), +// encoded by custom code in get<FORMAT><DISPSIZE>Encoding() and decoded +// by custom code in decode<TYPE><BITSIZE>Disp<DISPSIZE>Operand(). +// The address registers have BITSIZE bits and displacements have +// DISPSIZE bits. NUMOPS is the number of operands that make up an +// address and OPERANDS lists the types of those operands using (ops ...). +// FORMAT is the type of addressing mode, which needs to match the names +// used in AddressAsmOperand. class AddressingMode<string type, string bitsize, string dispsize, string suffix, int numops, string format, dag operands> : ComplexPattern<!cast<ValueType>("i"##bitsize), numops, @@ -57,6 +76,8 @@ class AddressingMode<string type, string bitsize, string dispsize, [add, sub, or, frameindex, z_adjdynalloc]>, Operand<!cast<ValueType>("i"##bitsize)> { let PrintMethod = "print"##format##"Operand"; + let EncoderMethod = "get"##format##dispsize##"Encoding"; + let DecoderMethod = "decode"##format##bitsize##"Disp"##dispsize##"Operand"; let MIOperandInfo = operands; let ParserMatchClass = !cast<AddressAsmOperand>(format##bitsize##"Disp"##dispsize); @@ -334,30 +355,39 @@ def fpimmneg0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(-0.0); }]>; // Symbolic address operands //===----------------------------------------------------------------------===// +// PC-relative asm operands. +def PCRel16 : PCRelAsmOperand<"16">; +def PCRel32 : PCRelAsmOperand<"32">; + // PC-relative offsets of a basic block. The offset is sign-extended // and multiplied by 2. -def brtarget16 : Operand<OtherVT> { +def brtarget16 : PCRelOperand<OtherVT, PCRel16> { let EncoderMethod = "getPC16DBLEncoding"; + let DecoderMethod = "decodePC16DBLOperand"; } -def brtarget32 : Operand<OtherVT> { +def brtarget32 : PCRelOperand<OtherVT, PCRel32> { let EncoderMethod = "getPC32DBLEncoding"; + let DecoderMethod = "decodePC32DBLOperand"; } // A PC-relative offset of a global value. The offset is sign-extended // and multiplied by 2. -def pcrel32 : PCRelAddress<i64, "pcrel32"> { +def pcrel32 : PCRelAddress<i64, "pcrel32", PCRel32> { let EncoderMethod = "getPC32DBLEncoding"; + let DecoderMethod = "decodePC32DBLOperand"; } // A PC-relative offset of a global value when the value is used as a // call target. The offset is sign-extended and multiplied by 2. -def pcrel16call : PCRelAddress<i64, "pcrel16call"> { +def pcrel16call : PCRelAddress<i64, "pcrel16call", PCRel16> { let PrintMethod = "printCallOperand"; let EncoderMethod = "getPLT16DBLEncoding"; + let DecoderMethod = "decodePC16DBLOperand"; } -def pcrel32call : PCRelAddress<i64, "pcrel32call"> { +def pcrel32call : PCRelAddress<i64, "pcrel32call", PCRel32> { let PrintMethod = "printCallOperand"; let EncoderMethod = "getPLT32DBLEncoding"; + let DecoderMethod = "decodePC32DBLOperand"; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/SystemZ/SystemZTargetMachine.cpp b/lib/Target/SystemZ/SystemZTargetMachine.cpp index 8c4c456ef5..17450ee53e 100644 --- a/lib/Target/SystemZ/SystemZTargetMachine.cpp +++ b/lib/Target/SystemZ/SystemZTargetMachine.cpp @@ -33,6 +33,7 @@ SystemZTargetMachine::SystemZTargetMachine(const Target &T, StringRef TT, "-f32:32-f64:64-f128:64-a0:8:16-n32:64"), InstrInfo(*this), TLInfo(*this), TSInfo(*this), FrameLowering(*this, Subtarget) { + initAsmInfo(); } namespace { |