Index: llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1354,7 +1354,6 @@ const OperandInfoTy &Offset, const OperandInfoTy &Width); - OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val); SMLoc getFlatOffsetLoc(const OperandVector &Operands) const; SMLoc getSMEMOffsetLoc(const OperandVector &Operands) const; @@ -5879,76 +5878,24 @@ // exp //===----------------------------------------------------------------------===// -OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str, - uint8_t &Val) { - if (Str == "null") { - Val = Exp::ET_NULL; - return MatchOperand_Success; - } - - if (Str.startswith("mrt")) { - Str = Str.drop_front(3); - if (Str == "z") { // == mrtz - Val = Exp::ET_MRTZ; - return MatchOperand_Success; - } - - if (Str.getAsInteger(10, Val)) - return MatchOperand_ParseFail; - - if (Val > Exp::ET_MRT7) - return MatchOperand_ParseFail; - - return MatchOperand_Success; - } - - if (Str.startswith("pos")) { - Str = Str.drop_front(3); - if (Str.getAsInteger(10, Val)) - return MatchOperand_ParseFail; - - if (Val > (isGFX10Plus() ? 4 : 3)) - return MatchOperand_ParseFail; - - Val += Exp::ET_POS0; - return MatchOperand_Success; - } - - if (isGFX10Plus() && Str == "prim") { - Val = Exp::ET_PRIM; - return MatchOperand_Success; - } - - if (Str.startswith("param")) { - Str = Str.drop_front(5); - if (Str.getAsInteger(10, Val)) - return MatchOperand_ParseFail; - - if (Val >= 32) - return MatchOperand_ParseFail; - - Val += Exp::ET_PARAM0; - return MatchOperand_Success; - } - - return MatchOperand_ParseFail; -} - OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) { + using namespace llvm::AMDGPU::Exp; + StringRef Str; SMLoc S = getLoc(); if (!parseId(Str)) return MatchOperand_NoMatch; - uint8_t Val; - auto Res = parseExpTgtImpl(Str, Val); - if (Res != MatchOperand_Success) { - Error(S, "invalid exp target"); - return Res; + unsigned Id = getTgtId(Str); + if (Id == ET_INVALID || !isSupportedTgtId(Id, getSTI())) { + Error(S, (Id == ET_INVALID) ? + "invalid exp target" : + "exp target is not supported on this GPU"); + return MatchOperand_ParseFail; } - Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, + Operands.push_back(AMDGPUOperand::CreateImm(this, Id, S, AMDGPUOperand::ImmTyExpTgt)); return MatchOperand_Success; } Index: llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp =================================================================== --- llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp +++ llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp @@ -1004,25 +1004,19 @@ void AMDGPUInstPrinter::printExpTgt(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O) { + using namespace llvm::AMDGPU::Exp; + // This is really a 6 bit field. - uint32_t Tgt = MI->getOperand(OpNo).getImm() & ((1 << 6) - 1); - - if (Tgt <= Exp::ET_MRT7) - O << " mrt" << Tgt - Exp::ET_MRT0; - else if (Tgt == Exp::ET_MRTZ) - O << " mrtz"; - else if (Tgt == Exp::ET_NULL) - O << " null"; - else if (Tgt >= Exp::ET_POS0 && - Tgt <= uint32_t(isGFX10Plus(STI) ? Exp::ET_POS4 : Exp::ET_POS3)) - O << " pos" << Tgt - Exp::ET_POS0; - else if (isGFX10Plus(STI) && Tgt == Exp::ET_PRIM) - O << " prim"; - else if (Tgt >= Exp::ET_PARAM0 && Tgt <= Exp::ET_PARAM31) - O << " param" << Tgt - Exp::ET_PARAM0; - else { - // Reserved values 10, 11 - O << " invalid_target_" << Tgt; + uint32_t Id = MI->getOperand(OpNo).getImm() & ((1 << 6) - 1); + + int Index; + StringRef TgtName; + if (getTgtName(Id, TgtName, Index) && isSupportedTgtId(Id, STI)) { + O << ' ' << TgtName; + if (Index >= 0) + O << Index; + } else { + O << " invalid_target_" << Id; } } Index: llvm/lib/Target/AMDGPU/SIDefines.h =================================================================== --- llvm/lib/Target/AMDGPU/SIDefines.h +++ llvm/lib/Target/AMDGPU/SIDefines.h @@ -704,6 +704,7 @@ ET_PRIM = 20, // GFX10+ ET_PARAM0 = 32, ET_PARAM31 = 63, + ET_INVALID = 255, }; } // namespace Exp Index: llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h =================================================================== --- llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -486,6 +486,18 @@ } // namespace Hwreg +namespace Exp { + +bool getTgtName(unsigned Id, StringRef &Name, int &Index); + +LLVM_READONLY +unsigned getTgtId(const StringRef Name); + +LLVM_READNONE +bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI); + +} // namespace Exp + namespace MTBUFFormat { LLVM_READNONE Index: llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp =================================================================== --- llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -787,6 +787,67 @@ } // namespace Hwreg +//===----------------------------------------------------------------------===// +// exp tgt +//===----------------------------------------------------------------------===// + +namespace Exp { + +struct ExpTgt { + StringLiteral Name; + unsigned Tgt; + unsigned MaxIndex; +}; + +static constexpr ExpTgt ExpTgtInfo[] = { + {{"null"}, ET_NULL, 0}, + {{"mrtz"}, ET_MRTZ, 0}, + {{"prim"}, ET_PRIM, 0}, + {{"mrt"}, ET_MRT0, 7}, + {{"pos"}, ET_POS0, 7}, + {{"param"}, ET_PARAM0, 31}, +}; + +bool getTgtName(unsigned Id, StringRef &Name, int &Index) { + for (const ExpTgt &Val : ExpTgtInfo) { + if (Val.Tgt <= Id && Id <= Val.Tgt + Val.MaxIndex) { + Index = (Val.MaxIndex == 0) ? -1 : (Id - Val.Tgt); + Name = Val.Name; + return true; + } + } + return false; +} + +unsigned getTgtId(const StringRef Name) { + + for (const ExpTgt &Val : ExpTgtInfo) { + if (Val.MaxIndex == 0 && Name == Val.Name) + return Val.Tgt; + + if (Val.MaxIndex > 0 && Name.startswith(Val.Name)) { + StringRef Suffix = Name.drop_front(Val.Name.size()); + + unsigned Id; + if (Suffix.getAsInteger(10, Id) || Id > Val.MaxIndex) + return ET_INVALID; + + // Disable leading zeroes + if (Suffix.size() > 1 && Suffix[0] == '0') + return ET_INVALID; + + return Val.Tgt + Id; + } + } + return ET_INVALID; +} + +bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI) { + return (Id != ET_POS4 && Id != ET_PRIM) || isGFX10Plus(STI); +} + +} // namespace Exp + //===----------------------------------------------------------------------===// // MTBUF Format //===----------------------------------------------------------------------===// Index: llvm/test/MC/AMDGPU/exp-err.s =================================================================== --- llvm/test/MC/AMDGPU/exp-err.s +++ llvm/test/MC/AMDGPU/exp-err.s @@ -5,7 +5,7 @@ // GCN: :5: error: invalid exp target exp pos4 v3, v2, v1, v0 -// GCN: :5: error: invalid exp target +// GCN: :5: error: exp target is not supported on this GPU exp param32 v3, v2, v1, v0 // GCN: :5: error: invalid exp target Index: llvm/test/MC/AMDGPU/exp-gfx10.s =================================================================== --- llvm/test/MC/AMDGPU/exp-gfx10.s +++ llvm/test/MC/AMDGPU/exp-gfx10.s @@ -3,13 +3,13 @@ // RUN: llvm-mc -arch=amdgcn -mcpu=gfx1010 -show-encoding %s | FileCheck -check-prefix=GFX10 %s exp prim v1, off, off, off -// SIVI: :5: error: invalid exp target +// SIVI: :5: error: exp target is not supported on this GPU // GFX10: exp prim v1, off, off, off ; encoding: [0x41,0x01,0x00,0xf8,0x01,0x00,0x00,0x00] exp prim v2, v3, off, off -// SIVI: :5: error: invalid exp target +// SIVI: :5: error: exp target is not supported on this GPU // GFX10: exp prim v2, v3, off, off ; encoding: [0x43,0x01,0x00,0xf8,0x02,0x03,0x00,0x00] exp pos4 v4, v3, v2, v1 -// SIVI: error: invalid exp target +// SIVI: error: exp target is not supported on this GPU // GFX10: exp pos4 v4, v3, v2, v1 ; encoding: [0x0f,0x01,0x00,0xf8,0x04,0x03,0x02,0x01] Index: llvm/test/MC/AMDGPU/gfx10_err_pos.s =================================================================== --- llvm/test/MC/AMDGPU/gfx10_err_pos.s +++ llvm/test/MC/AMDGPU/gfx10_err_pos.s @@ -631,6 +631,11 @@ // CHECK-NEXT:{{^}}exp invalid_target_10 v3, v2, v1, v0 // CHECK-NEXT:{{^}} ^ +exp pos00 v3, v2, v1, v0 +// CHECK: error: invalid exp target +// CHECK-NEXT:{{^}}exp pos00 v3, v2, v1, v0 +// CHECK-NEXT:{{^}} ^ + //============================================================================== // invalid immediate: only 16-bit values are legal Index: llvm/test/MC/AMDGPU/gfx9_err_pos.s =================================================================== --- llvm/test/MC/AMDGPU/gfx9_err_pos.s +++ llvm/test/MC/AMDGPU/gfx9_err_pos.s @@ -24,6 +24,14 @@ // CHECK-NEXT:{{^}}s_set_gpr_idx_on s0, gpr_idx(SRC0,DST,SRC1,DST) // CHECK-NEXT:{{^}} ^ +//============================================================================== +// exp target is not supported on this GPU + +exp pos4 v4, v3, v2, v1 +// CHECK: error: exp target is not supported on this GPU +// CHECK-NEXT:{{^}}exp pos4 v4, v3, v2, v1 +// CHECK-NEXT:{{^}} ^ + //============================================================================== // expected a 12-bit unsigned offset