From 19cb35b4bc76a04c882ccb6f507c2485e504406f Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Fri, 14 Nov 2014 14:08:00 +0000 Subject: [PATCH] R600/SI: Start implementing an assembler This was done using the Sparc and PowerPC AsmParsers as guides. So far it is very simple and only supports sopp instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221994 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/R600Usage.rst | 43 +++ docs/index.rst | 4 + lib/Target/R600/AMDGPU.td | 7 + lib/Target/R600/AMDGPUInstructions.td | 2 + lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp | 320 ++++++++++++++++++ lib/Target/R600/AsmParser/CMakeLists.txt | 3 + lib/Target/R600/AsmParser/LLVMBuild.txt | 23 ++ lib/Target/R600/AsmParser/Makefile | 15 + lib/Target/R600/CMakeLists.txt | 2 + lib/Target/R600/LLVMBuild.txt | 5 +- lib/Target/R600/Makefile | 4 +- lib/Target/R600/R600InstrFormats.td | 3 + lib/Target/R600/R600Instructions.td | 1 + lib/Target/R600/SIInstrFormats.td | 3 +- lib/Target/R600/SIInstructions.td | 55 +-- test/MC/R600/lit.local.cfg | 2 + test/MC/R600/sopp.s | 52 +++ 17 files changed, 514 insertions(+), 30 deletions(-) create mode 100644 docs/R600Usage.rst create mode 100644 lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp create mode 100644 lib/Target/R600/AsmParser/CMakeLists.txt create mode 100644 lib/Target/R600/AsmParser/LLVMBuild.txt create mode 100644 lib/Target/R600/AsmParser/Makefile create mode 100644 test/MC/R600/lit.local.cfg create mode 100644 test/MC/R600/sopp.s diff --git a/docs/R600Usage.rst b/docs/R600Usage.rst new file mode 100644 index 00000000000..48a30c8a8dd --- /dev/null +++ b/docs/R600Usage.rst @@ -0,0 +1,43 @@ +============================ +User Guide for R600 Back-end +============================ + +Introduction +============ + +The R600 back-end provides ISA code generation for AMD GPUs, starting with +the R600 family up until the current Sea Islands (GCN Gen 2). + + +Assembler +========= + +The assembler is currently a work in progress and not yet complete. Below +are the currently supported features. + +SOPP Instructions +----------------- + +Unless otherwise mentioned, all SOPP instructions that with an operand +accept a integer operand(s) only. No verification is performed on the +operands, so it is up to the programmer to be familiar with the range +or acceptable values. + +s_waitcnt +^^^^^^^^^ + +s_waitcnt accepts named arguments to specify which memory counter(s) to +wait for. + +.. code-block:: nasm + + // Wait for all counters to be 0 + s_waitcnt 0 + + // Equivalent to s_waitcnt 0. Counter names can also be delimited by + // '&' or ','. + s_waitcnt vmcnt(0) expcnt(0) lgkcmt(0) + + // Wait for vmcnt counter to be 1. + s_waitcnt vmcnt(1) + diff --git a/docs/index.rst b/docs/index.rst index 403c17aafae..5ac54432fd0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -235,6 +235,7 @@ For API clients and LLVM developers. WritingAnLLVMPass HowToUseAttributes NVPTXUsage + R600Usage StackMaps InAlloca BigEndianNEON @@ -317,6 +318,9 @@ For API clients and LLVM developers. :doc:`NVPTXUsage` This document describes using the NVPTX back-end to compile GPU kernels. +:doc:`R600Usage` + This document describes how to use the R600 back-end. + :doc:`StackMaps` LLVM support for mapping instruction addresses to the location of values and allowing code to be patched. diff --git a/lib/Target/R600/AMDGPU.td b/lib/Target/R600/AMDGPU.td index f5930f5e485..4cf12430d9d 100644 --- a/lib/Target/R600/AMDGPU.td +++ b/lib/Target/R600/AMDGPU.td @@ -153,9 +153,16 @@ def AMDGPUInstrInfo : InstrInfo { let guessInstructionProperties = 1; } +def AMDGPUAsmParser : AsmParser { + // Some of the R600 registers have the same name, so this crashes. + // For example T0_XYZW and T0_XY both have the asm name T0. + let ShouldEmitMatchRegisterName = 0; +} + def AMDGPU : Target { // Pull in Instruction Info: let InstructionSet = AMDGPUInstrInfo; + let AssemblyParsers = [AMDGPUAsmParser]; } // Dummy Instruction itineraries for pseudo instructions diff --git a/lib/Target/R600/AMDGPUInstructions.td b/lib/Target/R600/AMDGPUInstructions.td index ba5630e7478..c2158654f5e 100644 --- a/lib/Target/R600/AMDGPUInstructions.td +++ b/lib/Target/R600/AMDGPUInstructions.td @@ -23,6 +23,8 @@ class AMDGPUInst pattern> : Instructio let Pattern = pattern; let Itinerary = NullALU; + let isCodeGenOnly = 1; + let TSFlags{63} = isRegisterLoad; let TSFlags{62} = isRegisterStore; } diff --git a/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp new file mode 100644 index 00000000000..7ad815dbcac --- /dev/null +++ b/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp @@ -0,0 +1,320 @@ +//===-- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/AMDGPUMCTargetDesc.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { + +class AMDGPUAsmParser : public MCTargetAsmParser { + MCSubtargetInfo &STI; + MCAsmParser &Parser; + + + /// @name Auto-generated Match Functions + /// { + +#define GET_ASSEMBLER_HEADER +#include "AMDGPUGenAsmMatcher.inc" + + /// } + +public: + AMDGPUAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser, + const MCInstrInfo &_MII, + const MCTargetOptions &Options) + : MCTargetAsmParser(), STI(_STI), Parser(_Parser) { + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + } + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + OperandVector &Operands, MCStreamer &Out, + uint64_t &ErrorInfo, + bool MatchingInlineAsm) override; + bool ParseDirective(AsmToken DirectiveID) override; + OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic); + bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, OperandVector &Operands) override; + + bool parseCnt(int64_t &IntVal); + OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands); +}; + +class AMDGPUOperand : public MCParsedAsmOperand { + enum KindTy { + Token, + Immediate + } Kind; + +public: + AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {} + + struct TokOp { + const char *Data; + unsigned Length; + }; + + struct ImmOp { + int64_t Val; + }; + + union { + TokOp Tok; + ImmOp Imm; + }; + + void addImmOperands(MCInst &Inst, unsigned N) const { + Inst.addOperand(MCOperand::CreateImm(getImm())); + } + void addRegOperands(MCInst &Inst, unsigned N) const { + llvm_unreachable("addRegOperands"); + } + StringRef getToken() const { + return StringRef(Tok.Data, Tok.Length); + } + bool isToken() const override { + return Kind == Token; + } + + bool isImm() const override { + return Kind == Immediate; + } + + int64_t getImm() const { + return Imm.Val; + } + + bool isReg() const override { + return false; + } + + unsigned getReg() const override { + return 0; + } + + bool isMem() const override { + return false; + } + + SMLoc getStartLoc() const override { + return SMLoc(); + } + + SMLoc getEndLoc() const override { + return SMLoc(); + } + + void print(raw_ostream &OS) const override { } + + static std::unique_ptr CreateImm(int64_t Val) { + auto Op = llvm::make_unique(Immediate); + Op->Imm.Val = Val; + return Op; + } + + static std::unique_ptr CreateToken(StringRef Str, SMLoc Loc) { + auto Res = llvm::make_unique(Token); + Res->Tok.Data = Str.data(); + Res->Tok.Length = Str.size(); + return Res; + } + + bool isSWaitCnt() const; +}; + +} + +bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + return true; +} + + +bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + OperandVector &Operands, + MCStreamer &Out, + uint64_t &ErrorInfo, + bool MatchingInlineAsm) { + MCInst Inst; + + switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { + default: break; + case Match_Success: + Inst.setLoc(IDLoc); + Out.EmitInstruction(Inst, STI); + return false; + case Match_MissingFeature: + return Error(IDLoc, "instruction use requires an option to be enabled"); + case Match_MnemonicFail: + return Error(IDLoc, "unrecognized instruction mnemonic"); + case Match_InvalidOperand: { + if (ErrorInfo != ~0ULL) { + if (ErrorInfo >= Operands.size()) + return Error(IDLoc, "too few operands for instruction"); + + } + return Error(IDLoc, "invalid operand for instruction"); + } + } + llvm_unreachable("Implement any new match types added!"); +} + +bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) { + return true; +} + +AMDGPUAsmParser::OperandMatchResultTy +AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { + + // Try to parse with a custom parser + OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); + + // If we successfully parsed the operand or if there as an error parsing, + // we are done. + if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail) + return ResTy; + + switch(getLexer().getKind()) { + case AsmToken::Integer: { + int64_t IntVal; + if (getParser().parseAbsoluteExpression(IntVal)) + return MatchOperand_ParseFail; + Operands.push_back(AMDGPUOperand::CreateImm(IntVal)); + return MatchOperand_Success; + } + default: + return MatchOperand_NoMatch; + } +} + +bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info, + StringRef Name, + SMLoc NameLoc, OperandVector &Operands) { + // Add the instruction mnemonic + Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc)); + + if (getLexer().is(AsmToken::EndOfStatement)) + return false; + + AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name); + switch (Res) { + case MatchOperand_Success: return false; + case MatchOperand_ParseFail: return Error(NameLoc, + "Failed parsing operand"); + case MatchOperand_NoMatch: return Error(NameLoc, "Not a valid operand"); + } + return true; +} + +//===----------------------------------------------------------------------===// +// s_waitcnt +//===----------------------------------------------------------------------===// + +bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { + StringRef CntName = Parser.getTok().getString(); + int64_t CntVal; + + Parser.Lex(); + if (getLexer().isNot(AsmToken::LParen)) + return true; + + Parser.Lex(); + if (getLexer().isNot(AsmToken::Integer)) + return true; + + if (getParser().parseAbsoluteExpression(CntVal)) + return true; + + if (getLexer().isNot(AsmToken::RParen)) + return true; + + Parser.Lex(); + if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) + Parser.Lex(); + + int CntShift; + int CntMask; + + if (CntName == "vmcnt") { + CntMask = 0xf; + CntShift = 0; + } else if (CntName == "expcnt") { + CntMask = 0x7; + CntShift = 4; + } else if (CntName == "lgkmcnt") { + CntMask = 0x7; + CntShift = 8; + } else { + return true; + } + + IntVal &= ~(CntMask << CntShift); + IntVal |= (CntVal << CntShift); + return false; +} + +AMDGPUAsmParser::OperandMatchResultTy +AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) { + // Disable all counters by default. + // vmcnt [3:0] + // expcnt [6:4] + // lgkmcnt [10:8] + int64_t CntVal = 0x77f; + + switch(getLexer().getKind()) { + default: return MatchOperand_ParseFail; + case AsmToken::Integer: + // The operand can be an integer value. + if (getParser().parseAbsoluteExpression(CntVal)) + return MatchOperand_ParseFail; + break; + + case AsmToken::Identifier: + do { + if (parseCnt(CntVal)) + return MatchOperand_ParseFail; + } while(getLexer().isNot(AsmToken::EndOfStatement)); + break; + } + Operands.push_back(AMDGPUOperand::CreateImm(CntVal)); + return MatchOperand_Success; +} + +bool AMDGPUOperand::isSWaitCnt() const { + return isImm(); +} + +/// Force static initialization. +extern "C" void LLVMInitializeR600AsmParser() { + RegisterMCAsmParser A(TheAMDGPUTarget); +} + +#define GET_REGISTER_MATCHER +#define GET_MATCHER_IMPLEMENTATION +#include "AMDGPUGenAsmMatcher.inc" + diff --git a/lib/Target/R600/AsmParser/CMakeLists.txt b/lib/Target/R600/AsmParser/CMakeLists.txt new file mode 100644 index 00000000000..1b42af73740 --- /dev/null +++ b/lib/Target/R600/AsmParser/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMR600AsmParser + AMDGPUAsmParser.cpp + ) diff --git a/lib/Target/R600/AsmParser/LLVMBuild.txt b/lib/Target/R600/AsmParser/LLVMBuild.txt new file mode 100644 index 00000000000..940e4cee6df --- /dev/null +++ b/lib/Target/R600/AsmParser/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/R600/AsmParser/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 = R600AsmParser +parent = R600 +required_libraries = MC MCParser R600Desc R600Info Support +add_to_library_groups = R600 diff --git a/lib/Target/R600/AsmParser/Makefile b/lib/Target/R600/AsmParser/Makefile new file mode 100644 index 00000000000..e6689b54b6b --- /dev/null +++ b/lib/Target/R600/AsmParser/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/R600/AsmParser/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 = LLVMR600AsmParser + +# Hack: we need to include 'main' R600 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/R600/CMakeLists.txt b/lib/Target/R600/CMakeLists.txt index 7dbff55753e..ed0a21684dc 100644 --- a/lib/Target/R600/CMakeLists.txt +++ b/lib/Target/R600/CMakeLists.txt @@ -9,6 +9,7 @@ tablegen(LLVM AMDGPUGenIntrinsics.inc -gen-tgt-intrinsic) tablegen(LLVM AMDGPUGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM AMDGPUGenDFAPacketizer.inc -gen-dfa-packetizer) tablegen(LLVM AMDGPUGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM AMDGPUGenAsmMatcher.inc -gen-asm-matcher) add_public_tablegen_target(AMDGPUCommonTableGen) add_llvm_target(R600CodeGen @@ -54,6 +55,7 @@ add_llvm_target(R600CodeGen SITypeRewriter.cpp ) +add_subdirectory(AsmParser) add_subdirectory(InstPrinter) add_subdirectory(TargetInfo) add_subdirectory(MCTargetDesc) diff --git a/lib/Target/R600/LLVMBuild.txt b/lib/Target/R600/LLVMBuild.txt index 1b0472a133a..f3f254fdcba 100644 --- a/lib/Target/R600/LLVMBuild.txt +++ b/lib/Target/R600/LLVMBuild.txt @@ -16,17 +16,18 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = InstPrinter MCTargetDesc TargetInfo +subdirectories = AsmParser InstPrinter MCTargetDesc TargetInfo [component_0] type = TargetGroup name = R600 parent = Target +has_asmparser = 1 has_asmprinter = 1 [component_1] type = Library name = R600CodeGen parent = R600 -required_libraries = Analysis AsmPrinter CodeGen Core IPO MC R600AsmPrinter R600Desc R600Info Scalar SelectionDAG Support Target TransformUtils +required_libraries = Analysis AsmPrinter CodeGen Core IPO MC R600AsmParser R600AsmPrinter R600Desc R600Info Scalar SelectionDAG Support Target TransformUtils add_to_library_groups = R600 diff --git a/lib/Target/R600/Makefile b/lib/Target/R600/Makefile index 1b3ebbe8c8f..64a7c8c045c 100644 --- a/lib/Target/R600/Makefile +++ b/lib/Target/R600/Makefile @@ -16,8 +16,8 @@ BUILT_SOURCES = AMDGPUGenRegisterInfo.inc AMDGPUGenInstrInfo.inc \ AMDGPUGenDAGISel.inc AMDGPUGenSubtargetInfo.inc \ AMDGPUGenMCCodeEmitter.inc AMDGPUGenCallingConv.inc \ AMDGPUGenIntrinsics.inc AMDGPUGenDFAPacketizer.inc \ - AMDGPUGenAsmWriter.inc + AMDGPUGenAsmWriter.inc AMDGPUGenAsmMatcher.inc -DIRS = InstPrinter TargetInfo MCTargetDesc +DIRS = AsmParser InstPrinter TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/R600/R600InstrFormats.td b/lib/Target/R600/R600InstrFormats.td index 9428babcbef..0ffd485476e 100644 --- a/lib/Target/R600/R600InstrFormats.td +++ b/lib/Target/R600/R600InstrFormats.td @@ -38,6 +38,9 @@ class InstR600 pattern, let Pattern = pattern; let Itinerary = itin; + // No AsmMatcher support. + let isCodeGenOnly = 1; + let TSFlags{4} = Trig; let TSFlags{5} = Op3; diff --git a/lib/Target/R600/R600Instructions.td b/lib/Target/R600/R600Instructions.td index 69695a3bce3..b6c00f89d5c 100644 --- a/lib/Target/R600/R600Instructions.td +++ b/lib/Target/R600/R600Instructions.td @@ -1496,6 +1496,7 @@ class ILFormat pattern> let mayLoad = 0; let mayStore = 0; let hasSideEffects = 0; + let isCodeGenOnly = 1; } multiclass BranchConditional { diff --git a/lib/Target/R600/SIInstrFormats.td b/lib/Target/R600/SIInstrFormats.td index 18c1345ec51..bc8c0110471 100644 --- a/lib/Target/R600/SIInstrFormats.td +++ b/lib/Target/R600/SIInstrFormats.td @@ -204,12 +204,13 @@ class SOPK op, dag outs, dag ins, string asm, list pattern> : let UseNamedOperandTable = 1; } -class SOPP op, dag ins, string asm, list pattern> : +class SOPP op, dag ins, string asm, list pattern = []> : InstSI <(outs), ins, asm, pattern >, SOPPe { let mayLoad = 0; let mayStore = 0; let hasSideEffects = 0; + let isCodeGenOnly = 0; let SALU = 1; let UseNamedOperandTable = 1; diff --git a/lib/Target/R600/SIInstructions.td b/lib/Target/R600/SIInstructions.td index 9d4b8bb200e..193a083085a 100644 --- a/lib/Target/R600/SIInstructions.td +++ b/lib/Target/R600/SIInstructions.td @@ -33,7 +33,15 @@ def isCI : Predicate<"Subtarget.getGeneration() " ">= AMDGPUSubtarget::SEA_ISLANDS">; def HasFlatAddressSpace : Predicate<"Subtarget.hasFlatAddressSpace()">; -def WAIT_FLAG : InstFlag<"printWaitFlag">; +def SWaitMatchClass : AsmOperandClass { + let Name = "SWaitCnt"; + let RenderMethod = "addImmOperands"; + let ParserMethod = "parseSWaitCntOps"; +} + +def WAIT_FLAG : InstFlag<"printWaitFlag"> { + let ParserMatchClass = SWaitMatchClass; +} let SubtargetPredicate = isSI in { @@ -371,7 +379,7 @@ def S_GETREG_REGRD_B32 : SOPK_32 <0x00000014, "s_getreg_regrd_b32", []>; // SOPP Instructions //===----------------------------------------------------------------------===// -def S_NOP : SOPP <0x00000000, (ins i16imm:$simm16), "s_nop $simm16", []>; +def S_NOP : SOPP <0x00000000, (ins i16imm:$simm16), "s_nop $simm16">; let isTerminator = 1 in { @@ -392,36 +400,31 @@ def S_BRANCH : SOPP < let DisableEncoding = "$scc" in { def S_CBRANCH_SCC0 : SOPP < 0x00000004, (ins sopp_brtarget:$simm16, SCCReg:$scc), - "s_cbranch_scc0 $simm16", [] + "s_cbranch_scc0 $simm16" >; def S_CBRANCH_SCC1 : SOPP < 0x00000005, (ins sopp_brtarget:$simm16, SCCReg:$scc), - "s_cbranch_scc1 $simm16", - [] + "s_cbranch_scc1 $simm16" >; } // End DisableEncoding = "$scc" def S_CBRANCH_VCCZ : SOPP < 0x00000006, (ins sopp_brtarget:$simm16, VCCReg:$vcc), - "s_cbranch_vccz $simm16", - [] + "s_cbranch_vccz $simm16" >; def S_CBRANCH_VCCNZ : SOPP < 0x00000007, (ins sopp_brtarget:$simm16, VCCReg:$vcc), - "s_cbranch_vccnz $simm16", - [] + "s_cbranch_vccnz $simm16" >; let DisableEncoding = "$exec" in { def S_CBRANCH_EXECZ : SOPP < 0x00000008, (ins sopp_brtarget:$simm16, EXECReg:$exec), - "s_cbranch_execz $simm16", - [] + "s_cbranch_execz $simm16" >; def S_CBRANCH_EXECNZ : SOPP < 0x00000009, (ins sopp_brtarget:$simm16, EXECReg:$exec), - "s_cbranch_execnz $simm16", - [] + "s_cbranch_execnz $simm16" >; } // End DisableEncoding = "$exec" @@ -440,12 +443,10 @@ def S_BARRIER : SOPP <0x0000000a, (ins), "s_barrier", let mayStore = 1; } -def S_WAITCNT : SOPP <0x0000000c, (ins WAIT_FLAG:$simm16), "s_waitcnt $simm16", - [] ->; -//def S_SETHALT : SOPP_ <0x0000000d, "s_sethalt", []>; -//def S_SLEEP : SOPP_ <0x0000000e, "s_sleep", []>; -//def S_SETPRIO : SOPP_ <0x0000000f, "s_setprio", []>; +def S_WAITCNT : SOPP <0x0000000c, (ins WAIT_FLAG:$simm16), "s_waitcnt $simm16">; +def S_SETHALT : SOPP <0x0000000d, (ins i16imm:$simm16), "s_sethalt $simm16">; +def S_SLEEP : SOPP <0x0000000e, (ins i16imm:$simm16), "s_sleep $simm16">; +def S_SETPRIO : SOPP <0x0000000f, (ins i16imm:$sim16), "s_setprio $sim16">; let Uses = [EXEC] in { def S_SENDMSG : SOPP <0x00000010, (ins SendMsgImm:$simm16, M0Reg:$m0), "s_sendmsg $simm16", @@ -455,12 +456,16 @@ let Uses = [EXEC] in { } } // End Uses = [EXEC] -//def S_SENDMSGHALT : SOPP_ <0x00000011, "s_sendmsghalt", []>; -//def S_TRAP : SOPP_ <0x00000012, "s_trap", []>; -//def S_ICACHE_INV : SOPP_ <0x00000013, "s_icache_inv", []>; -//def S_INCPERFLEVEL : SOPP_ <0x00000014, "s_incperflevel", []>; -//def S_DECPERFLEVEL : SOPP_ <0x00000015, "s_decperflevel", []>; -//def S_TTRACEDATA : SOPP_ <0x00000016, "s_ttracedata", []>; +def S_SENDMSGHALT : SOPP <0x00000011, (ins i16imm:$simm16), "s_sendmsghalt $simm16">; +def S_TRAP : SOPP <0x00000012, (ins i16imm:$simm16), "s_trap $simm16">; +def S_ICACHE_INV : SOPP <0x00000013, (ins), "s_icache_inv"> { + let simm16 = 0; +} +def S_INCPERFLEVEL : SOPP <0x00000014, (ins i16imm:$simm16), "s_incperflevel $simm16">; +def S_DECPERFLEVEL : SOPP <0x00000015, (ins i16imm:$simm16), "s_decperflevel $simm16">; +def S_TTRACEDATA : SOPP <0x00000016, (ins), "s_ttracedata"> { + let simm16 = 0; +} } // End hasSideEffects //===----------------------------------------------------------------------===// diff --git a/test/MC/R600/lit.local.cfg b/test/MC/R600/lit.local.cfg new file mode 100644 index 00000000000..ad9ce2541ef --- /dev/null +++ b/test/MC/R600/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'R600' in config.root.targets: + config.unsupported = True diff --git a/test/MC/R600/sopp.s b/test/MC/R600/sopp.s new file mode 100644 index 00000000000..65fc97be42d --- /dev/null +++ b/test/MC/R600/sopp.s @@ -0,0 +1,52 @@ +// RUN: llvm-mc -arch=r600 -mcpu=SI -show-encoding %s | FileCheck %s + + s_nop 1 // CHECK: s_nop 1 ; encoding: [0x01,0x00,0x80,0xbf] + s_endpgm // CHECK: s_endpgm ; encoding: [0x00,0x00,0x81,0xbf] + s_branch 2 // CHECK: s_branch 2 ; encoding: [0x02,0x00,0x82,0xbf] + s_cbranch_scc0 3 // CHECK: s_cbranch_scc0 3 ; encoding: [0x03,0x00,0x84,0xbf] + s_cbranch_scc1 4 // CHECK: s_cbranch_scc1 4 ; encoding: [0x04,0x00,0x85,0xbf] + s_cbranch_vccz 5 // CHECK: s_cbranch_vccz 5 ; encoding: [0x05,0x00,0x86,0xbf] + s_cbranch_vccnz 6 // CHECK: s_cbranch_vccnz 6 ; encoding: [0x06,0x00,0x87,0xbf] + s_cbranch_execz 7 // CHECK: s_cbranch_execz 7 ; encoding: [0x07,0x00,0x88,0xbf] + s_cbranch_execnz 8 // CHECK: s_cbranch_execnz 8 ; encoding: [0x08,0x00,0x89,0xbf] + s_barrier // CHECK: s_barrier ; encoding: [0x00,0x00,0x8a,0xbf] + +//===----------------------------------------------------------------------===// +// s_waitcnt +//===----------------------------------------------------------------------===// + + s_waitcnt 0 + // CHECK: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; encoding: [0x00,0x00,0x8c,0xbf] + + s_waitcnt vmcnt(0) & expcnt(0) & lgkmcnt(0) + // CHECK: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; encoding: [0x00,0x00,0x8c,0xbf] + + s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) + // CHECK: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; encoding: [0x00,0x00,0x8c,0xbf] + + s_waitcnt vmcnt(0), expcnt(0), lgkmcnt(0) + // CHECK: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; encoding: [0x00,0x00,0x8c,0xbf] + + s_waitcnt vmcnt(1) + // CHECK: s_waitcnt vmcnt(1) ; encoding: [0x71,0x07,0x8c,0xbf] + + s_waitcnt expcnt(2) + // CHECK: s_waitcnt expcnt(2) ; encoding: [0x2f,0x07,0x8c,0xbf] + + s_waitcnt lgkmcnt(3) + // CHECK: s_waitcnt lgkmcnt(3) ; encoding: [0x7f,0x03,0x8c,0xbf] + + s_waitcnt vmcnt(0), expcnt(0) + // CHECK: s_waitcnt vmcnt(0) expcnt(0) ; encoding: [0x00,0x07,0x8c,0xbf] + + + s_sethalt 9 // CHECK: s_sethalt 9 ; encoding: [0x09,0x00,0x8d,0xbf] + s_sleep 10 // CHECK: s_sleep 10 ; encoding: [0x0a,0x00,0x8e,0xbf] + s_setprio 1 // CHECK: s_setprio 1 ; encoding: [0x01,0x00,0x8f,0xbf] + s_sendmsg 2 // CHECK: s_sendmsg Gs(nop), [m0] ; encoding: [0x02,0x00,0x90,0xbf] + s_sendmsghalt 3 // CHECK: s_sendmsghalt 3 ; encoding: [0x03,0x00,0x91,0xbf] + s_trap 4 // CHECK: s_trap 4 ; encoding: [0x04,0x00,0x92,0xbf] + s_icache_inv // CHECK: s_icache_inv ; encoding: [0x00,0x00,0x93,0xbf] + s_incperflevel 5 // CHECK: s_incperflevel 5 ; encoding: [0x05,0x00,0x94,0xbf] + s_decperflevel 6 // CHECK: s_decperflevel 6 ; encoding: [0x06,0x00,0x95,0xbf] + s_ttracedata // CHECK: s_ttracedata ; encoding: [0x00,0x00,0x96,0xbf] -- 2.34.1