Skip to content

Commit d646866

Browse files
committedApr 25, 2016
[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
1 parent 926bff8 commit d646866

File tree

9 files changed

+183
-15
lines changed

9 files changed

+183
-15
lines changed
 

‎llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp

+94
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class AMDGPUOperand : public MCParsedAsmOperand {
7979
ImmTyDA,
8080
ImmTyR128,
8181
ImmTyLWE,
82+
ImmTyHwreg,
8283
};
8384

8485
struct TokOp {
@@ -406,6 +407,7 @@ class AMDGPUOperand : public MCParsedAsmOperand {
406407
bool isDSOffset() const;
407408
bool isDSOffset01() const;
408409
bool isSWaitCnt() const;
410+
bool isHwreg() const;
409411
bool isMubufOffset() const;
410412
bool isSMRDOffset() const;
411413
bool isSMRDLiteralOffset() const;
@@ -530,6 +532,8 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
530532

531533
bool parseCnt(int64_t &IntVal);
532534
OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
535+
bool parseHwreg(int64_t &HwRegCode, int64_t &Offset, int64_t &Width);
536+
OperandMatchResultTy parseHwregOp(OperandVector &Operands);
533537
OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
534538

535539
OperandMatchResultTy parseFlatOptionalOps(OperandVector &Operands);
@@ -1570,10 +1574,100 @@ AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
15701574
return MatchOperand_Success;
15711575
}
15721576

1577+
bool AMDGPUAsmParser::parseHwreg(int64_t &HwRegCode, int64_t &Offset, int64_t &Width) {
1578+
if (Parser.getTok().getString() != "hwreg")
1579+
return true;
1580+
Parser.Lex();
1581+
1582+
if (getLexer().isNot(AsmToken::LParen))
1583+
return true;
1584+
Parser.Lex();
1585+
1586+
if (getLexer().isNot(AsmToken::Integer))
1587+
return true;
1588+
if (getParser().parseAbsoluteExpression(HwRegCode))
1589+
return true;
1590+
1591+
if (getLexer().is(AsmToken::RParen)) {
1592+
Parser.Lex();
1593+
return false;
1594+
}
1595+
1596+
// optional params
1597+
if (getLexer().isNot(AsmToken::Comma))
1598+
return true;
1599+
Parser.Lex();
1600+
1601+
if (getLexer().isNot(AsmToken::Integer))
1602+
return true;
1603+
if (getParser().parseAbsoluteExpression(Offset))
1604+
return true;
1605+
1606+
if (getLexer().isNot(AsmToken::Comma))
1607+
return true;
1608+
Parser.Lex();
1609+
1610+
if (getLexer().isNot(AsmToken::Integer))
1611+
return true;
1612+
if (getParser().parseAbsoluteExpression(Width))
1613+
return true;
1614+
1615+
if (getLexer().isNot(AsmToken::RParen))
1616+
return true;
1617+
Parser.Lex();
1618+
1619+
return false;
1620+
}
1621+
1622+
AMDGPUAsmParser::OperandMatchResultTy
1623+
AMDGPUAsmParser::parseHwregOp(OperandVector &Operands) {
1624+
int64_t Imm16Val = 0;
1625+
SMLoc S = Parser.getTok().getLoc();
1626+
1627+
switch(getLexer().getKind()) {
1628+
default: return MatchOperand_ParseFail;
1629+
case AsmToken::Integer:
1630+
// The operand can be an integer value.
1631+
if (getParser().parseAbsoluteExpression(Imm16Val))
1632+
return MatchOperand_ParseFail;
1633+
if (!isInt<16>(Imm16Val) && !isUInt<16>(Imm16Val)) {
1634+
Error(S, "invalid immediate: only 16-bit values are legal");
1635+
// Do not return error code, but create an imm operand anyway and proceed
1636+
// to the next operand, if any. That avoids unneccessary error messages.
1637+
}
1638+
break;
1639+
1640+
case AsmToken::Identifier: {
1641+
int64_t HwRegCode = 0;
1642+
int64_t Offset = 0; // default
1643+
int64_t Width = 32; // default
1644+
if (parseHwreg(HwRegCode, Offset, Width))
1645+
return MatchOperand_ParseFail;
1646+
// HwRegCode (6) [5:0]
1647+
// Offset (5) [10:6]
1648+
// WidthMinusOne (5) [15:11]
1649+
if (HwRegCode < 0 || HwRegCode > 63)
1650+
Error(S, "invalid code of hardware register: only 6-bit values are legal");
1651+
if (Offset < 0 || Offset > 31)
1652+
Error(S, "invalid bit offset: only 5-bit values are legal");
1653+
if (Width < 1 || Width > 32)
1654+
Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
1655+
Imm16Val = HwRegCode | (Offset << 6) | ((Width-1) << 11);
1656+
}
1657+
break;
1658+
}
1659+
Operands.push_back(AMDGPUOperand::CreateImm(Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
1660+
return MatchOperand_Success;
1661+
}
1662+
15731663
bool AMDGPUOperand::isSWaitCnt() const {
15741664
return isImm();
15751665
}
15761666

1667+
bool AMDGPUOperand::isHwreg() const {
1668+
return isImmTy(ImmTyHwreg);
1669+
}
1670+
15771671
//===----------------------------------------------------------------------===//
15781672
// sopp branch targets
15791673
//===----------------------------------------------------------------------===//

‎llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -760,4 +760,18 @@ void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
760760
}
761761
}
762762

763+
void AMDGPUInstPrinter::printHwreg(const MCInst *MI, unsigned OpNo,
764+
raw_ostream &O) {
765+
unsigned SImm16 = MI->getOperand(OpNo).getImm();
766+
const unsigned HwRegCode = SImm16 & 0x3F;
767+
const unsigned Offset = (SImm16 >> 6) & 0x1f;
768+
const unsigned Width = ((SImm16 >> 11) & 0x1F) + 1;
769+
770+
if (Width == 32 && Offset == 0) {
771+
O << "hwreg(" << HwRegCode << ')';
772+
} else {
773+
O << "hwreg(" << HwRegCode << ", " << Offset << ", " << Width << ')';
774+
}
775+
}
776+
763777
#include "AMDGPUGenAsmWriter.inc"

‎llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class AMDGPUInstPrinter : public MCInstPrinter {
9191
static void printKCache(const MCInst *MI, unsigned OpNo, raw_ostream &O);
9292
static void printSendMsg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
9393
static void printWaitFlag(const MCInst *MI, unsigned OpNo, raw_ostream &O);
94+
static void printHwreg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
9495
};
9596

9697
} // End namespace llvm

‎llvm/lib/Target/AMDGPU/SIInstrInfo.td

+12
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,13 @@ class NamedBitOperand<string BitName> : Operand<i1> {
603603
let PrintMethod = "print"#BitName;
604604
}
605605

606+
def HwregMatchClass : AsmOperandClass {
607+
let Name = "Hwreg";
608+
let PredicateMethod = "isHwreg";
609+
let ParserMethod = "parseHwregOp";
610+
let RenderMethod = "addImmOperands";
611+
}
612+
606613
let OperandType = "OPERAND_IMMEDIATE" in {
607614

608615
def offen : Operand<i1> {
@@ -730,6 +737,11 @@ def bound_ctrl : Operand <i1> {
730737
let ParserMatchClass = DPPOptionalMatchClass<"BoundCtrl">;
731738
}
732739

740+
def hwreg : Operand <i16> {
741+
let PrintMethod = "printHwreg";
742+
let ParserMatchClass = HwregMatchClass;
743+
}
744+
733745
} // End OperandType = "OPERAND_IMMEDIATE"
734746

735747

‎llvm/lib/Target/AMDGPU/SIInstructions.td

+6-3
Original file line numberDiff line numberDiff line change
@@ -418,18 +418,21 @@ defm S_CBRANCH_I_FORK : SOPK_m <
418418
>;
419419

420420
let mayLoad = 1 in {
421-
defm S_GETREG_B32 : SOPK_32 <sopk<0x12, 0x11>, "s_getreg_b32", []>;
421+
defm S_GETREG_B32 : SOPK_m <
422+
sopk<0x12, 0x11>, "s_getreg_b32", (outs SReg_32:$sdst),
423+
(ins hwreg:$simm16), " $sdst, $simm16"
424+
>;
422425
}
423426

424427
defm S_SETREG_B32 : SOPK_m <
425428
sopk<0x13, 0x12>, "s_setreg_b32", (outs),
426-
(ins SReg_32:$sdst, u16imm:$simm16), " $simm16, $sdst"
429+
(ins SReg_32:$sdst, hwreg:$simm16), " $simm16, $sdst"
427430
>;
428431
// FIXME: Not on SI?
429432
//defm S_GETREG_REGRD_B32 : SOPK_32 <sopk<0x14, 0x13>, "s_getreg_regrd_b32", []>;
430433
defm S_SETREG_IMM32_B32 : SOPK_IMM32 <
431434
sopk<0x15, 0x14>, "s_setreg_imm32_b32", (outs),
432-
(ins i32imm:$imm, u16imm:$simm16), " $simm16, $imm"
435+
(ins i32imm:$imm, hwreg:$simm16), " $simm16, $imm"
433436
>;
434437

435438
//===----------------------------------------------------------------------===//

‎llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.getreg.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=fiji -verify-machineinstrs < %s | FileCheck %s
44

55
; FUNC-LABEL: {{^}}s_getreg_test:
6-
; CHECK: s_getreg_b32 s{{[0-9]+}}, 0xb206
6+
; CHECK: s_getreg_b32 s{{[0-9]+}}, hwreg(6, 8, 23)
77
define void @s_getreg_test(i32 addrspace(1)* %out) { ; simm16=45574 for lds size.
88
%lds_size_64dwords = call i32 @llvm.amdgcn.s.getreg(i32 45574) #0
99
%lds_size_bytes = shl i32 %lds_size_64dwords, 8

‎llvm/test/MC/AMDGPU/sopk-err.s

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: not llvm-mc -arch=amdgcn %s 2>&1 | FileCheck -check-prefix=GCN %s
2+
// RUN: not llvm-mc -arch=amdgcn -mcpu=tahiti %s 2>&1 | FileCheck -check-prefix=GCN -check-prefix=SI %s
3+
// RUN: not llvm-mc -arch=amdgcn -mcpu=tonga %s 2>&1 | FileCheck -check-prefix=GCN -check-prefix=VI %s
4+
5+
s_setreg_b32 0x1f803, s2
6+
// GCN: error: invalid immediate: only 16-bit values are legal
7+
8+
s_setreg_b32 hwreg(0x40), s2
9+
// GCN: error: invalid code of hardware register: only 6-bit values are legal
10+
11+
s_setreg_b32 hwreg(3,32,32), s2
12+
// GCN: error: invalid bit offset: only 5-bit values are legal
13+
14+
s_setreg_b32 hwreg(3,0,33), s2
15+
// GCN: error: invalid bitfield width: only values from 1 to 32 are legal
16+
17+
s_setreg_imm32_b32 0x1f803, 0xff
18+
// GCN: error: invalid immediate: only 16-bit values are legal
19+
20+
s_setreg_imm32_b32 hwreg(3,0,33), 0xff
21+
// GCN: error: invalid bitfield width: only values from 1 to 32 are legal
22+
23+
s_getreg_b32 s2, hwreg(3,32,32)
24+
// GCN: error: invalid bit offset: only 5-bit values are legal

‎llvm/test/MC/AMDGPU/sopk.s

+26-6
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,33 @@ s_cbranch_i_fork s[2:3], 0x6
7474
// VI: s_cbranch_i_fork s[2:3], 0x6 ; encoding: [0x06,0x00,0x02,0xb8]
7575

7676
s_getreg_b32 s2, 0x6
77-
// SICI: s_getreg_b32 s2, 0x6 ; encoding: [0x06,0x00,0x02,0xb9]
78-
// VI: s_getreg_b32 s2, 0x6 ; encoding: [0x06,0x00,0x82,0xb8]
77+
// SICI: s_getreg_b32 s2, hwreg(6, 0, 1) ; encoding: [0x06,0x00,0x02,0xb9]
78+
// VI: s_getreg_b32 s2, hwreg(6, 0, 1) ; encoding: [0x06,0x00,0x82,0xb8]
79+
80+
s_getreg_b32 s2, hwreg(5, 1, 31)
81+
// SICI: s_getreg_b32 s2, hwreg(5, 1, 31) ; encoding: [0x45,0xf0,0x02,0xb9]
82+
// VI: s_getreg_b32 s2, hwreg(5, 1, 31) ; encoding: [0x45,0xf0,0x82,0xb8]
7983

8084
s_setreg_b32 0x6, s2
81-
// SICI: s_setreg_b32 0x6, s2 ; encoding: [0x06,0x00,0x82,0xb9]
82-
// VI: s_setreg_b32 0x6, s2 ; encoding: [0x06,0x00,0x02,0xb9]
85+
// SICI: s_setreg_b32 hwreg(6, 0, 1), s2 ; encoding: [0x06,0x00,0x82,0xb9]
86+
// VI: s_setreg_b32 hwreg(6, 0, 1), s2 ; encoding: [0x06,0x00,0x02,0xb9]
87+
88+
s_setreg_b32 0xf803, s2
89+
// SICI: s_setreg_b32 hwreg(3), s2 ; encoding: [0x03,0xf8,0x82,0xb9]
90+
// VI: s_setreg_b32 hwreg(3), s2 ; encoding: [0x03,0xf8,0x02,0xb9]
91+
92+
s_setreg_b32 hwreg(4), s2
93+
// SICI: s_setreg_b32 hwreg(4), s2 ; encoding: [0x04,0xf8,0x82,0xb9]
94+
// VI: s_setreg_b32 hwreg(4), s2 ; encoding: [0x04,0xf8,0x02,0xb9]
95+
96+
s_setreg_b32 hwreg(5, 1, 31), s2
97+
// SICI: s_setreg_b32 hwreg(5, 1, 31), s2 ; encoding: [0x45,0xf0,0x82,0xb9]
98+
// VI: s_setreg_b32 hwreg(5, 1, 31), s2 ; encoding: [0x45,0xf0,0x02,0xb9]
8399

84100
s_setreg_imm32_b32 0x6, 0xff
85-
// SICI: s_setreg_imm32_b32 0x6, 0xff ; encoding: [0x06,0x00,0x80,0xba,0xff,0x00,0x00,0x00]
86-
// VI: s_setreg_imm32_b32 0x6, 0xff ; encoding: [0x06,0x00,0x00,0xba,0xff,0x00,0x00,0x00]
101+
// SICI: s_setreg_imm32_b32 hwreg(6, 0, 1), 0xff ; encoding: [0x06,0x00,0x80,0xba,0xff,0x00,0x00,0x00]
102+
// VI: s_setreg_imm32_b32 hwreg(6, 0, 1), 0xff ; encoding: [0x06,0x00,0x00,0xba,0xff,0x00,0x00,0x00]
103+
104+
s_setreg_imm32_b32 hwreg(5, 1, 31), 0xff
105+
// SICI: s_setreg_imm32_b32 hwreg(5, 1, 31), 0xff ; encoding: [0x45,0xf0,0x80,0xba,0xff,0x00,0x00,0x00]
106+
// VI: s_setreg_imm32_b32 hwreg(5, 1, 31), 0xff ; encoding: [0x45,0xf0,0x00,0xba,0xff,0x00,0x00,0x00]

‎llvm/test/MC/Disassembler/AMDGPU/sopk_vi.txt

+5-5
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@
4848
# VI: s_cbranch_i_fork s[2:3], 0x6 ; encoding: [0x06,0x00,0x02,0xb8]
4949
0x06 0x00 0x02 0xb8
5050

51-
# VI: s_getreg_b32 s2, 0x6 ; encoding: [0x06,0x00,0x82,0xb8]
52-
0x06 0x00 0x82 0xb8
51+
# VI: s_getreg_b32 s2, hwreg(6) ; encoding: [0x06,0xf8,0x82,0xb8]
52+
0x06 0xf8 0x82 0xb8
5353

54-
# VI: s_setreg_b32 0x6, s2 ; encoding: [0x06,0x00,0x02,0xb9]
54+
# VI: s_setreg_b32 hwreg(6, 0, 1), s2 ; encoding: [0x06,0x00,0x02,0xb9]
5555
0x06 0x00 0x02 0xb9
5656

57-
# VI: s_setreg_imm32_b32 0x6, 0xff ; encoding: [0x06,0x00,0x00,0xba,0xff,0x00,0x00,0x00]
58-
0x06 0x00 0x00 0xba 0xff 0x00 0x00 0x00
57+
# VI: s_setreg_imm32_b32 hwreg(5, 1, 31), 0xff ; encoding: [0x45,0xf0,0x00,0xba,0xff,0x00,0x00,0x00]
58+
0x45 0xf0 0x00 0xba 0xff 0x00 0x00 0x00

0 commit comments

Comments
 (0)
Please sign in to comment.