<html>
<head>
<meta content="text/html; charset=windows-1252"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">On 11/12/2014 11:18 AM, Tom Stellard
wrote:<br>
</div>
<blockquote cite="mid:20141112191842.GB21893@yyz" type="cite">
<div class="moz-text-plain" wrap="true" graphical-quote="true"
style="font-family: -moz-fixed; font-size: 12px;"
lang="x-western">
<pre wrap="">On Thu, Nov 06, 2014 at 11:28:48AM -0800, Matt Arsenault wrote:
</pre>
<blockquote type="cite" style="color: #000000;">
<pre wrap=""><span class="moz-txt-citetags">> </span>
</pre>
<blockquote type="cite" style="color: #000000;">
<pre wrap=""><span class="moz-txt-citetags">> > </span>On Nov 5, 2014, at 8:05 PM, Tom Stellard <a moz-do-not-send="true" class="moz-txt-link-rfc2396E" href="mailto:thomas.stellard@amd.com"><thomas.stellard@amd.com></a> wrote:
<span class="moz-txt-citetags">> > </span>
<span class="moz-txt-citetags">> > </span>This was done using PowerPCAsmParser as a guide. So far it is very
<span class="moz-txt-citetags">> > </span>simple and only supports a few sopp instructions.
<span class="moz-txt-citetags">> > </span>---
<span class="moz-txt-citetags">> > </span>lib/Target/R600/AMDGPU.td | 7 +
<span class="moz-txt-citetags">> > </span>lib/Target/R600/AMDGPUInstructions.td | 2 +
<span class="moz-txt-citetags">> > </span>lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp | 224 ++++++++++++++++++++++++++
<span class="moz-txt-citetags">> > </span>lib/Target/R600/AsmParser/CMakeLists.txt | 3 +
<span class="moz-txt-citetags">> > </span>lib/Target/R600/AsmParser/LLVMBuild.txt | 23 +++
<span class="moz-txt-citetags">> > </span>lib/Target/R600/AsmParser/Makefile | 15 ++
<span class="moz-txt-citetags">> > </span>lib/Target/R600/CMakeLists.txt | 2 +
<span class="moz-txt-citetags">> > </span>lib/Target/R600/LLVMBuild.txt | 5 +-
<span class="moz-txt-citetags">> > </span>lib/Target/R600/Makefile | 4 +-
<span class="moz-txt-citetags">> > </span>lib/Target/R600/R600InstrFormats.td | 3 +
<span class="moz-txt-citetags">> > </span>lib/Target/R600/R600Instructions.td | 1 +
<span class="moz-txt-citetags">> > </span>lib/Target/R600/SIInstrFormats.td | 3 +-
<span class="moz-txt-citetags">> > </span>lib/Target/R600/SIInstructions.td | 40 ++---
<span class="moz-txt-citetags">> > </span>test/MC/R600/lit.local.cfg | 2 +
<span class="moz-txt-citetags">> > </span>test/MC/R600/sopp.s | 23 +++
<span class="moz-txt-citetags">> > </span>15 files changed, 332 insertions(+), 25 deletions(-)
<span class="moz-txt-citetags">> > </span>create mode 100644 lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
<span class="moz-txt-citetags">> > </span>create mode 100644 lib/Target/R600/AsmParser/CMakeLists.txt
<span class="moz-txt-citetags">> > </span>create mode 100644 lib/Target/R600/AsmParser/LLVMBuild.txt
<span class="moz-txt-citetags">> > </span>create mode 100644 lib/Target/R600/AsmParser/Makefile
<span class="moz-txt-citetags">> > </span>create mode 100644 test/MC/R600/lit.local.cfg
<span class="moz-txt-citetags">> > </span>create mode 100644 test/MC/R600/sopp.s
<span class="moz-txt-citetags">> > </span>
<span class="moz-txt-citetags">> > </span>diff --git a/lib/Target/R600/AMDGPU.td b/lib/Target/R600/AMDGPU.td
<span class="moz-txt-citetags">> > </span>index f5930f5..4cf1243 100644
<span class="moz-txt-citetags">> > </span>--- a/lib/Target/R600/AMDGPU.td
<span class="moz-txt-citetags">> > </span>+++ b/lib/Target/R600/AMDGPU.td
<span class="moz-txt-citetags">> > </span>@@ -153,9 +153,16 @@ def AMDGPUInstrInfo : InstrInfo {
<span class="moz-txt-citetags">> > </span> let guessInstructionProperties = 1;
<span class="moz-txt-citetags">> > </span>}
<span class="moz-txt-citetags">> > </span>
<span class="moz-txt-citetags">> > </span>+def AMDGPUAsmParser : AsmParser {
<span class="moz-txt-citetags">> > </span>+ // Some of the R600 registers have the same name, so this crashes.
<span class="moz-txt-citetags">> > </span>+ // For example T0_XYZW and T0_XY both have the asm name T0.
<span class="moz-txt-citetags">> > </span>+ let ShouldEmitMatchRegisterName = 0;
<span class="moz-txt-citetags">> > </span>+}
<span class="moz-txt-citetags">> > </span>+
<span class="moz-txt-citetags">> > </span>def AMDGPU : Target {
<span class="moz-txt-citetags">> > </span> // Pull in Instruction Info:
<span class="moz-txt-citetags">> > </span> let InstructionSet = AMDGPUInstrInfo;
<span class="moz-txt-citetags">> > </span>+ let AssemblyParsers = [AMDGPUAsmParser];
<span class="moz-txt-citetags">> > </span>}
<span class="moz-txt-citetags">> > </span>
<span class="moz-txt-citetags">> > </span>// Dummy Instruction itineraries for pseudo instructions
<span class="moz-txt-citetags">> > </span>diff --git a/lib/Target/R600/AMDGPUInstructions.td b/lib/Target/R600/AMDGPUInstructions.td
<span class="moz-txt-citetags">> > </span>index ba5630e..c215865 100644
<span class="moz-txt-citetags">> > </span>--- a/lib/Target/R600/AMDGPUInstructions.td
<span class="moz-txt-citetags">> > </span>+++ b/lib/Target/R600/AMDGPUInstructions.td
<span class="moz-txt-citetags">> > </span>@@ -23,6 +23,8 @@ class AMDGPUInst <dag outs, dag ins, string asm, list<dag> pattern> : Instructio
<span class="moz-txt-citetags">> > </span> let Pattern = pattern;
<span class="moz-txt-citetags">> > </span> let Itinerary = NullALU;
<span class="moz-txt-citetags">> > </span>
<span class="moz-txt-citetags">> > </span>+ let isCodeGenOnly = 1;
<span class="moz-txt-citetags">> > </span>+
<span class="moz-txt-citetags">> > </span> let TSFlags{63} = isRegisterLoad;
<span class="moz-txt-citetags">> > </span> let TSFlags{62} = isRegisterStore;
<span class="moz-txt-citetags">> > </span>}
<span class="moz-txt-citetags">> > </span>diff --git a/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
<span class="moz-txt-citetags">> > </span>new file mode 100644
<span class="moz-txt-citetags">> > </span>index 0000000..7331e7e
<span class="moz-txt-citetags">> > </span>--- /dev/null
<span class="moz-txt-citetags">> > </span>+++ b/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
<span class="moz-txt-citetags">> > </span>@@ -0,0 +1,224 @@
<span class="moz-txt-citetags">> > </span>+//===-- AMDGPUAsmParser.cpp - Parse R600 asm to MCInst instructions ---------===//
</pre>
</blockquote>
<pre wrap=""><span class="moz-txt-citetags">> </span>Should this really be SIAsmParser?
<span class="moz-txt-citetags">> </span>
</pre>
</blockquote>
<pre wrap="">TableGen expects the class to be called AMDGPUAsmParser.cpp, but I changed the
comment from R600 asm to SI asm.
The attached patches addresses your other concerns and implements the
parser for all sopp instructions including the special syntax for
s_waitcnt.
-Tom</pre>
</div>
</blockquote>
<br>
LGTM<br>
<br>
<blockquote cite="mid:20141112191842.GB21893@yyz" type="cite">
<div class="moz-text-plain" wrap="true" graphical-quote="true"
style="font-family: -moz-fixed; font-size: 12px;"
lang="x-western">
<pre wrap="">
</pre>
</div>
<br>
<fieldset class="mimeAttachmentHeader"><legend
class="mimeAttachmentHeaderName">0001-R600-SI-Start-implementing-an-assembler.patch</legend></fieldset>
<br>
<div class="moz-text-plain" wrap="true" graphical-quote="true"
style="font-family: -moz-fixed; font-size: 12px;"
lang="x-western">
<pre wrap="">From 3b94fbc540c32a42a340b39f6ae3725056e335a1 Mon Sep 17 00:00:00 2001
From: Tom Stellard <a moz-do-not-send="true" class="moz-txt-link-rfc2396E" href="mailto:thomas.stellard@amd.com"><thomas.stellard@amd.com></a>
Date: Wed, 5 Nov 2014 21:32:56 -0500
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.
---
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 | 319 ++++++++++++++++++++++++++
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, 513 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 0000000..48a30c8
--- /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 403c17a..5ac5443 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 f5930f5..4cf1243 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 ba5630e..c215865 100644
--- a/lib/Target/R600/AMDGPUInstructions.td
+++ b/lib/Target/R600/AMDGPUInstructions.td
@@ -23,6 +23,8 @@ class AMDGPUInst <dag outs, dag ins, string asm, list<dag> 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 0000000..205de5f
--- /dev/null
+++ b/lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
@@ -0,0 +1,319 @@
+//===-- 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/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"</pre>
</div>
</blockquote>
STLExtras comes after these<br>
<blockquote cite="mid:20141112191842.GB21893@yyz" type="cite">
<div class="moz-text-plain" wrap="true" graphical-quote="true"
style="font-family: -moz-fixed; font-size: 12px;"
lang="x-western">
<pre wrap="">
+#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<AMDGPUOperand> CreateImm(int64_t Val) {
+ auto Op = llvm::make_unique<AMDGPUOperand>(Immediate);
+ Op->Imm.Val = Val;
+ return Op;
+ }
+
+ static std::unique_ptr<AMDGPUOperand> CreateToken(StringRef Str, SMLoc Loc) {
+ auto Res = llvm::make_unique<AMDGPUOperand>(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");
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// 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<AMDGPUAsmParser> 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 0000000..1b42af7
--- /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 0000000..940e4ce
--- /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:
+;
+; <a moz-do-not-send="true" class="moz-txt-link-freetext" href="http://llvm.org/docs/LLVMBuild.html">http://llvm.org/docs/LLVMBuild.html</a>
+;
+;===------------------------------------------------------------------------===;
+
+[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 0000000..e6689b5
--- /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 7dbff55..ed0a216 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 1b0472a..f3f254f 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 1b3ebbe..64a7c8c 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 9428bab..0ffd485 100644
--- a/lib/Target/R600/R600InstrFormats.td
+++ b/lib/Target/R600/R600InstrFormats.td
@@ -38,6 +38,9 @@ class InstR600 <dag outs, dag ins, string asm, list<dag> 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 7ce05a2..fbcca54 100644
--- a/lib/Target/R600/R600Instructions.td
+++ b/lib/Target/R600/R600Instructions.td
@@ -1495,6 +1495,7 @@ class ILFormat<dag outs, dag ins, string asmstr, list<dag> pattern>
let mayLoad = 0;
let mayStore = 0;
let hasSideEffects = 0;
+ let isCodeGenOnly = 1;
}
multiclass BranchConditional<SDNode Op, RegisterClass rci, RegisterClass rcf> {
diff --git a/lib/Target/R600/SIInstrFormats.td b/lib/Target/R600/SIInstrFormats.td
index 18c1345..bc8c011 100644
--- a/lib/Target/R600/SIInstrFormats.td
+++ b/lib/Target/R600/SIInstrFormats.td
@@ -204,12 +204,13 @@ class SOPK <bits<5> op, dag outs, dag ins, string asm, list<dag> pattern> :
let UseNamedOperandTable = 1;
}
-class SOPP <bits<7> op, dag ins, string asm, list<dag> pattern> :
+class SOPP <bits<7> op, dag ins, string asm, list<dag> pattern = []> :
InstSI <(outs), ins, asm, pattern >, SOPPe <op> {
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 3842f84..a082736 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 {
@@ -372,7 +380,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 {
@@ -393,36 +401,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"
@@ -441,12 +444,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",
@@ -456,12 +457,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 0000000..ad9ce25
--- /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 0000000..65fc97b
--- /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]
<div class="moz-txt-sig">--
1.8.1.5
</div></pre>
</div>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset>
<br>
<div class="moz-text-plain" wrap="true" graphical-quote="true"
style="font-family: -moz-fixed; font-size: 12px;"
lang="x-western">
<pre wrap="">_______________________________________________
llvm-commits mailing list
<a moz-do-not-send="true" class="moz-txt-link-abbreviated" href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a>
<a moz-do-not-send="true" class="moz-txt-link-freetext" href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a>
</pre>
</div>
</blockquote>
<br>
</body>
</html>