mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 02:33:33 +00:00
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
This commit is contained in:
parent
40b0f5d6ce
commit
19cb35b4bc
43
docs/R600Usage.rst
Normal file
43
docs/R600Usage.rst
Normal file
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
320
lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
Normal file
320
lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp
Normal file
@ -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<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");
|
||||
}
|
||||
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<AMDGPUAsmParser> A(TheAMDGPUTarget);
|
||||
}
|
||||
|
||||
#define GET_REGISTER_MATCHER
|
||||
#define GET_MATCHER_IMPLEMENTATION
|
||||
#include "AMDGPUGenAsmMatcher.inc"
|
||||
|
3
lib/Target/R600/AsmParser/CMakeLists.txt
Normal file
3
lib/Target/R600/AsmParser/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
add_llvm_library(LLVMR600AsmParser
|
||||
AMDGPUAsmParser.cpp
|
||||
)
|
23
lib/Target/R600/AsmParser/LLVMBuild.txt
Normal file
23
lib/Target/R600/AsmParser/LLVMBuild.txt
Normal file
@ -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
|
15
lib/Target/R600/AsmParser/Makefile
Normal file
15
lib/Target/R600/AsmParser/Makefile
Normal file
@ -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
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -1496,6 +1496,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> {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
2
test/MC/R600/lit.local.cfg
Normal file
2
test/MC/R600/lit.local.cfg
Normal file
@ -0,0 +1,2 @@
|
||||
if not 'R600' in config.root.targets:
|
||||
config.unsupported = True
|
52
test/MC/R600/sopp.s
Normal file
52
test/MC/R600/sopp.s
Normal file
@ -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]
|
Loading…
x
Reference in New Issue
Block a user