summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorArtem Tamazov <artem.tamazov@amd.com>2016-04-25 14:13:51 +0000
committerArtem Tamazov <artem.tamazov@amd.com>2016-04-25 14:13:51 +0000
commitd6468666b540364feec63b5abed9aa428832fe8d (patch)
tree8efdccb79942350a8a772d349eda9fc43cef6c54 /llvm/lib
parent926bff8c3e3f3fd12395968423380b84caf087f1 (diff)
downloadbcm5719-llvm-d6468666b540364feec63b5abed9aa428832fe8d.tar.gz
bcm5719-llvm-d6468666b540364feec63b5abed9aa428832fe8d.zip
[AMDGPU][llvm-mc] s_getreg/setreg* - Add hwreg(...) syntax.
Added hwreg(reg[,offset,width]) syntax. Default offset = 0, default width = 32. Possibility to specify 16-bit immediate kept. Added out-of-range checks. Disassembling is always to hwreg(...) format. Tests updated/added. Differential Revision: http://reviews.llvm.org/D19329 llvm-svn: 267410
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp94
-rw-r--r--llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp14
-rw-r--r--llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h1
-rw-r--r--llvm/lib/Target/AMDGPU/SIInstrInfo.td12
-rw-r--r--llvm/lib/Target/AMDGPU/SIInstructions.td9
5 files changed, 127 insertions, 3 deletions
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index e6462689d24..c099c9b3a36 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -79,6 +79,7 @@ public:
ImmTyDA,
ImmTyR128,
ImmTyLWE,
+ ImmTyHwreg,
};
struct TokOp {
@@ -406,6 +407,7 @@ public:
bool isDSOffset() const;
bool isDSOffset01() const;
bool isSWaitCnt() const;
+ bool isHwreg() const;
bool isMubufOffset() const;
bool isSMRDOffset() const;
bool isSMRDLiteralOffset() const;
@@ -530,6 +532,8 @@ public:
bool parseCnt(int64_t &IntVal);
OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
+ bool parseHwreg(int64_t &HwRegCode, int64_t &Offset, int64_t &Width);
+ OperandMatchResultTy parseHwregOp(OperandVector &Operands);
OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
OperandMatchResultTy parseFlatOptionalOps(OperandVector &Operands);
@@ -1570,10 +1574,100 @@ AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
return MatchOperand_Success;
}
+bool AMDGPUAsmParser::parseHwreg(int64_t &HwRegCode, int64_t &Offset, int64_t &Width) {
+ if (Parser.getTok().getString() != "hwreg")
+ return true;
+ Parser.Lex();
+
+ if (getLexer().isNot(AsmToken::LParen))
+ return true;
+ Parser.Lex();
+
+ if (getLexer().isNot(AsmToken::Integer))
+ return true;
+ if (getParser().parseAbsoluteExpression(HwRegCode))
+ return true;
+
+ if (getLexer().is(AsmToken::RParen)) {
+ Parser.Lex();
+ return false;
+ }
+
+ // optional params
+ if (getLexer().isNot(AsmToken::Comma))
+ return true;
+ Parser.Lex();
+
+ if (getLexer().isNot(AsmToken::Integer))
+ return true;
+ if (getParser().parseAbsoluteExpression(Offset))
+ return true;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return true;
+ Parser.Lex();
+
+ if (getLexer().isNot(AsmToken::Integer))
+ return true;
+ if (getParser().parseAbsoluteExpression(Width))
+ return true;
+
+ if (getLexer().isNot(AsmToken::RParen))
+ return true;
+ Parser.Lex();
+
+ return false;
+}
+
+AMDGPUAsmParser::OperandMatchResultTy
+AMDGPUAsmParser::parseHwregOp(OperandVector &Operands) {
+ int64_t Imm16Val = 0;
+ SMLoc S = Parser.getTok().getLoc();
+
+ switch(getLexer().getKind()) {
+ default: return MatchOperand_ParseFail;
+ case AsmToken::Integer:
+ // The operand can be an integer value.
+ if (getParser().parseAbsoluteExpression(Imm16Val))
+ return MatchOperand_ParseFail;
+ if (!isInt<16>(Imm16Val) && !isUInt<16>(Imm16Val)) {
+ Error(S, "invalid immediate: only 16-bit values are legal");
+ // Do not return error code, but create an imm operand anyway and proceed
+ // to the next operand, if any. That avoids unneccessary error messages.
+ }
+ break;
+
+ case AsmToken::Identifier: {
+ int64_t HwRegCode = 0;
+ int64_t Offset = 0; // default
+ int64_t Width = 32; // default
+ if (parseHwreg(HwRegCode, Offset, Width))
+ return MatchOperand_ParseFail;
+ // HwRegCode (6) [5:0]
+ // Offset (5) [10:6]
+ // WidthMinusOne (5) [15:11]
+ if (HwRegCode < 0 || HwRegCode > 63)
+ Error(S, "invalid code of hardware register: only 6-bit values are legal");
+ if (Offset < 0 || Offset > 31)
+ Error(S, "invalid bit offset: only 5-bit values are legal");
+ if (Width < 1 || Width > 32)
+ Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
+ Imm16Val = HwRegCode | (Offset << 6) | ((Width-1) << 11);
+ }
+ break;
+ }
+ Operands.push_back(AMDGPUOperand::CreateImm(Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
+ return MatchOperand_Success;
+}
+
bool AMDGPUOperand::isSWaitCnt() const {
return isImm();
}
+bool AMDGPUOperand::isHwreg() const {
+ return isImmTy(ImmTyHwreg);
+}
+
//===----------------------------------------------------------------------===//
// sopp branch targets
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp b/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
index 0bdff1af82c..e02bc90e89c 100644
--- a/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
@@ -760,4 +760,18 @@ void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
}
}
+void AMDGPUInstPrinter::printHwreg(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ unsigned SImm16 = MI->getOperand(OpNo).getImm();
+ const unsigned HwRegCode = SImm16 & 0x3F;
+ const unsigned Offset = (SImm16 >> 6) & 0x1f;
+ const unsigned Width = ((SImm16 >> 11) & 0x1F) + 1;
+
+ if (Width == 32 && Offset == 0) {
+ O << "hwreg(" << HwRegCode << ')';
+ } else {
+ O << "hwreg(" << HwRegCode << ", " << Offset << ", " << Width << ')';
+ }
+}
+
#include "AMDGPUGenAsmWriter.inc"
diff --git a/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h b/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h
index 682894f92df..64618c737e7 100644
--- a/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h
+++ b/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h
@@ -91,6 +91,7 @@ private:
static void printKCache(const MCInst *MI, unsigned OpNo, raw_ostream &O);
static void printSendMsg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
static void printWaitFlag(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ static void printHwreg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
};
} // End namespace llvm
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.td b/llvm/lib/Target/AMDGPU/SIInstrInfo.td
index fa19af19c80..79ef1c66218 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.td
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.td
@@ -603,6 +603,13 @@ class NamedBitOperand<string BitName> : Operand<i1> {
let PrintMethod = "print"#BitName;
}
+def HwregMatchClass : AsmOperandClass {
+ let Name = "Hwreg";
+ let PredicateMethod = "isHwreg";
+ let ParserMethod = "parseHwregOp";
+ let RenderMethod = "addImmOperands";
+}
+
let OperandType = "OPERAND_IMMEDIATE" in {
def offen : Operand<i1> {
@@ -730,6 +737,11 @@ def bound_ctrl : Operand <i1> {
let ParserMatchClass = DPPOptionalMatchClass<"BoundCtrl">;
}
+def hwreg : Operand <i16> {
+ let PrintMethod = "printHwreg";
+ let ParserMatchClass = HwregMatchClass;
+}
+
} // End OperandType = "OPERAND_IMMEDIATE"
diff --git a/llvm/lib/Target/AMDGPU/SIInstructions.td b/llvm/lib/Target/AMDGPU/SIInstructions.td
index b2c059d2770..64d42b76d44 100644
--- a/llvm/lib/Target/AMDGPU/SIInstructions.td
+++ b/llvm/lib/Target/AMDGPU/SIInstructions.td
@@ -418,18 +418,21 @@ defm S_CBRANCH_I_FORK : SOPK_m <
>;
let mayLoad = 1 in {
-defm S_GETREG_B32 : SOPK_32 <sopk<0x12, 0x11>, "s_getreg_b32", []>;
+defm S_GETREG_B32 : SOPK_m <
+ sopk<0x12, 0x11>, "s_getreg_b32", (outs SReg_32:$sdst),
+ (ins hwreg:$simm16), " $sdst, $simm16"
+>;
}
defm S_SETREG_B32 : SOPK_m <
sopk<0x13, 0x12>, "s_setreg_b32", (outs),
- (ins SReg_32:$sdst, u16imm:$simm16), " $simm16, $sdst"
+ (ins SReg_32:$sdst, hwreg:$simm16), " $simm16, $sdst"
>;
// FIXME: Not on SI?
//defm S_GETREG_REGRD_B32 : SOPK_32 <sopk<0x14, 0x13>, "s_getreg_regrd_b32", []>;
defm S_SETREG_IMM32_B32 : SOPK_IMM32 <
sopk<0x15, 0x14>, "s_setreg_imm32_b32", (outs),
- (ins i32imm:$imm, u16imm:$simm16), " $simm16, $imm"
+ (ins i32imm:$imm, hwreg:$simm16), " $simm16, $imm"
>;
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud