Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -43,6 +43,8 @@ struct OptionalOperand; +enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL }; + class AMDGPUOperand : public MCParsedAsmOperand { enum KindTy { Token, @@ -455,6 +457,8 @@ bool ParseSectionDirectiveHSADataGlobalAgent(); bool ParseSectionDirectiveHSADataGlobalProgram(); bool ParseSectionDirectiveHSARodataReadonlyAgent(); + bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum); + bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth); public: enum AMDGPUMatchResultTy { @@ -574,8 +578,6 @@ } -enum RegisterKind { IS_VGPR, IS_SGPR, IS_TTMP }; - static int getRegClass(RegisterKind Is, unsigned RegWidth) { if (Is == IS_VGPR) { switch (RegWidth) { @@ -606,14 +608,15 @@ return -1; } -static unsigned getRegForName(StringRef RegName) { - +static unsigned getSpecialRegForName(StringRef RegName) { return StringSwitch(RegName) .Case("exec", AMDGPU::EXEC) .Case("vcc", AMDGPU::VCC) .Case("flat_scratch", AMDGPU::FLAT_SCR) .Case("m0", AMDGPU::M0) .Case("scc", AMDGPU::SCC) + .Case("tba", AMDGPU::TBA) + .Case("tma", AMDGPU::TMA) .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO) .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI) .Case("vcc_lo", AMDGPU::VCC_LO) @@ -637,86 +640,136 @@ return false; } -std::unique_ptr AMDGPUAsmParser::parseRegister() { - const AsmToken &Tok = Parser.getTok(); - SMLoc StartLoc = Tok.getLoc(); - SMLoc EndLoc = Tok.getEndLoc(); - const MCRegisterInfo *TRI = getContext().getRegisterInfo(); - - StringRef RegName = Tok.getString(); - unsigned RegNo = getRegForName(RegName); - - if (RegNo) { - Parser.Lex(); - if (!subtargetHasRegister(*TRI, RegNo)) - return nullptr; - return AMDGPUOperand::CreateReg(RegNo, StartLoc, EndLoc, - TRI, &getSTI(), false); +bool AMDGPUAsmParser::AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum) +{ + switch (RegKind) { + case IS_SPECIAL: + if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { Reg = AMDGPU::EXEC; RegWidth = 2; return true; } + if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { Reg = AMDGPU::FLAT_SCR; RegWidth = 2; return true; } + if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { Reg = AMDGPU::VCC; RegWidth = 2; return true; } + if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { Reg = AMDGPU::TBA; RegWidth = 2; return true; } + if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { Reg = AMDGPU::TMA; RegWidth = 2; return true; } + return false; + case IS_VGPR: + case IS_SGPR: + case IS_TTMP: + if (Reg1 != Reg + RegWidth) { return false; } + RegWidth++; + return true; + default: + assert(false); return false; } +} - // Match vgprs, sgprs and ttmps - if (RegName[0] != 's' && RegName[0] != 'v' && !RegName.startswith("ttmp")) - return nullptr; - - const RegisterKind Is = RegName[0] == 'v' ? IS_VGPR : RegName[0] == 's' ? IS_SGPR : IS_TTMP; - unsigned RegWidth; - unsigned RegIndexInClass; - if (RegName.size() > (Is == IS_TTMP ? strlen("ttmp") : 1) ) { - // We have a single 32-bit register. Syntax: vXX - RegWidth = 1; - if (RegName.substr(Is == IS_TTMP ? strlen("ttmp") : 1).getAsInteger(10, RegIndexInClass)) - return nullptr; - Parser.Lex(); - } else { - // We have a register greater than 32-bits (a range of single registers). Syntax: v[XX:YY] +bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth) +{ + const MCRegisterInfo *TRI = getContext().getRegisterInfo(); + if (getLexer().is(AsmToken::Identifier)) { + StringRef RegName = Parser.getTok().getString(); + if ((Reg = getSpecialRegForName(RegName))) { + Parser.Lex(); + RegKind = IS_SPECIAL; + } else { + unsigned RegNumIndex = 0; + if (RegName[0] == 'v') { RegNumIndex = 1; RegKind = IS_VGPR; } + else if (RegName[0] == 's') { RegNumIndex = 1; RegKind = IS_SGPR; } + else if (RegName.startswith("ttmp")) { RegNumIndex = strlen("ttmp"); RegKind = IS_TTMP; } + else { return false; } + if (RegName.size() > RegNumIndex) { + // Single 32-bit register: vXX. + if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum)) { return false; } + Parser.Lex(); + RegWidth = 1; + } else { + // Range of registers: v[XX:YY]. + Parser.Lex(); + int64_t RegLo, RegHi; + if (getLexer().isNot(AsmToken::LBrac)) { return false; } + Parser.Lex(); - int64_t RegLo, RegHi; - Parser.Lex(); - if (getLexer().isNot(AsmToken::LBrac)) - return nullptr; + if (getParser().parseAbsoluteExpression(RegLo)) { return false; } - Parser.Lex(); - if (getParser().parseAbsoluteExpression(RegLo)) - return nullptr; + if (getLexer().isNot(AsmToken::Colon)) { return false; } + Parser.Lex(); - if (getLexer().isNot(AsmToken::Colon)) - return nullptr; + if (getParser().parseAbsoluteExpression(RegHi)) { return false; } - Parser.Lex(); - if (getParser().parseAbsoluteExpression(RegHi)) - return nullptr; - - if (getLexer().isNot(AsmToken::RBrac)) - return nullptr; + if (getLexer().isNot(AsmToken::RBrac)) { return false; } + Parser.Lex(); + RegNum = (unsigned) RegLo; + RegWidth = (RegHi - RegLo) + 1; + } + } + } else if (getLexer().is(AsmToken::LBrac)) { + // List of consecutive registers: [s0,s1,s2,s3] Parser.Lex(); - RegWidth = (RegHi - RegLo) + 1; - if (Is == IS_VGPR) { - // VGPR registers aren't aligned. - RegIndexInClass = RegLo; - } else { + if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) { return false; } + if (RegWidth != 1) { return false; } + RegisterKind RegKind1; + unsigned Reg1, RegNum1, RegWidth1; + do { + if (getLexer().is(AsmToken::Comma)) { + Parser.Lex(); + } else if (getLexer().is(AsmToken::RBrac)) { + Parser.Lex(); + break; + } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1)) { + if (RegWidth1 != 1) { return false; } + if (RegKind1 != RegKind) { return false; } + if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) { return false; } + } else { + return false; + } + } while (true); + } else { + return false; + } + switch (RegKind) { + case IS_SPECIAL: + RegNum = 0; + RegWidth = 1; + break; + case IS_VGPR: + case IS_SGPR: + case IS_TTMP: + { + unsigned Size = 1; + if (RegKind == IS_SGPR || RegKind == IS_TTMP) { // SGPR and TTMP registers must be are aligned. Max required alignment is 4 dwords. - unsigned Size = std::min(RegWidth, 4u); - if (RegLo % Size != 0) - return nullptr; - - RegIndexInClass = RegLo / Size; + Size = std::min(RegWidth, 4u); } + if (RegNum % Size != 0) { return false; } + RegNum = RegNum / Size; + int RCID = getRegClass(RegKind, RegWidth); + if (RCID == -1) { return false; } + const MCRegisterClass RC = TRI->getRegClass(RCID); + if (RegNum >= RC.getNumRegs()) { return false; } + Reg = RC.getRegister(RegNum); + break; } - int RCID = getRegClass(Is, RegWidth); - if (RCID == -1) - return nullptr; + default: + assert(false); return false; + } - const MCRegisterClass RC = TRI->getRegClass(RCID); - if (RegIndexInClass >= RC.getNumRegs()) - return nullptr; + if (!subtargetHasRegister(*TRI, Reg)) { return false; } + return true; +} - RegNo = RC.getRegister(RegIndexInClass); - if (!subtargetHasRegister(*TRI, RegNo)) - return nullptr; +std::unique_ptr AMDGPUAsmParser::parseRegister() { + const auto &Tok = Parser.getTok(); + SMLoc StartLoc = Tok.getLoc(); + SMLoc EndLoc = Tok.getEndLoc(); + const MCRegisterInfo *TRI = getContext().getRegisterInfo(); - return AMDGPUOperand::CreateReg(RegNo, StartLoc, EndLoc, + RegisterKind RegKind; + unsigned Reg, RegNum, RegWidth; + + if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) { + return nullptr; + } + return AMDGPUOperand::CreateReg(Reg, StartLoc, EndLoc, TRI, &getSTI(), false); } @@ -1115,6 +1168,7 @@ AMDGPUOperand::CreateImm(F.bitcastToAPInt().getZExtValue(), S)); return MatchOperand_Success; } + case AsmToken::LBrac: case AsmToken::Identifier: { if (auto R = parseRegister()) { unsigned Modifiers = 0; Index: lib/Target/AMDGPU/SIRegisterInfo.td =================================================================== --- lib/Target/AMDGPU/SIRegisterInfo.td +++ lib/Target/AMDGPU/SIRegisterInfo.td @@ -262,7 +262,7 @@ } def SReg_64 : RegisterClass<"AMDGPU", [v2i32, i64, f64, i1], 32, - (add SGPR_64, VCC, EXEC, FLAT_SCR, TTMP_64) + (add SGPR_64, VCC, EXEC, FLAT_SCR, TTMP_64, TBA, TMA) >; def SReg_128 : RegisterClass<"AMDGPU", [v4i32, v16i8, v2i64], 32, (add SGPR_128)> { Index: test/MC/AMDGPU/reg-syntax-extra.s =================================================================== --- /dev/null +++ test/MC/AMDGPU/reg-syntax-extra.s @@ -0,0 +1,55 @@ +// RUN: not llvm-mc -arch=amdgcn -show-encoding %s | FileCheck --check-prefix=GCN --check-prefix=SICI %s +// RUN: not llvm-mc -arch=amdgcn -mcpu=SI -show-encoding %s | FileCheck --check-prefix=GCN --check-prefix=SICI %s +// RUN: not llvm-mc -arch=amdgcn -mcpu=SI -show-encoding %s 2>&1 | FileCheck --check-prefix=NOSICI %s +// RUN: llvm-mc -arch=amdgcn -mcpu=fiji -show-encoding %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=VI %s + +s_mov_b32 [ttmp5], [ttmp3] +// SICI: s_mov_b32 ttmp5, ttmp3 ; encoding: [0x73,0x03,0xf5,0xbe] +// VI: s_mov_b32 ttmp5, ttmp3 ; encoding: [0x73,0x00,0xf5,0xbe] + +s_mov_b64 [ttmp4,ttmp5], [ttmp2,ttmp3] +// SICI: s_mov_b64 ttmp[4:5], ttmp[2:3] ; encoding: [0x72,0x04,0xf4,0xbe] +// VI: s_mov_b64 ttmp[4:5], ttmp[2:3] ; encoding: [0x72,0x01,0xf4,0xbe] + +s_mov_b64 ttmp[4:5], ttmp[2:3] +// SICI: s_mov_b64 ttmp[4:5], ttmp[2:3] ; encoding: [0x72,0x04,0xf4,0xbe] +// VI: s_mov_b64 ttmp[4:5], ttmp[2:3] ; encoding: [0x72,0x01,0xf4,0xbe] + +s_mov_b64 [s6,s7], s[8:9] +// SICI: s_mov_b64 s[6:7], s[8:9] ; encoding: [0x08,0x04,0x86,0xbe] +// VI: s_mov_b64 s[6:7], s[8:9] ; encoding: [0x08,0x01,0x86,0xbe] + +s_mov_b64 s[6:7], [s8,s9] +// SICI: s_mov_b64 s[6:7], s[8:9] ; encoding: [0x08,0x04,0x86,0xbe] +// VI: s_mov_b64 s[6:7], s[8:9] ; encoding: [0x08,0x01,0x86,0xbe] + +s_mov_b64 [exec_lo,exec_hi], s[2:3] +// SICI: s_mov_b64 exec, s[2:3] ; encoding: [0x02,0x04,0xfe,0xbe] +// VI: s_mov_b64 exec, s[2:3] ; encoding: [0x02,0x01,0xfe,0xbe] + +s_mov_b64 [flat_scratch_lo,flat_scratch_hi], s[2:3] +// NOSICI: error: +// VI: s_mov_b64 flat_scratch, s[2:3] ; encoding: [0x02,0x01,0xe6,0xbe] + +s_mov_b64 [vcc_lo,vcc_hi], s[2:3] +// SICI: s_mov_b64 vcc, s[2:3] ; encoding: [0x02,0x04,0xea,0xbe] +// VI: s_mov_b64 vcc, s[2:3] ; encoding: [0x02,0x01,0xea,0xbe] + +s_mov_b64 [tba_lo,tba_hi], s[2:3] +// SICI: s_mov_b64 tba, s[2:3] ; encoding: [0x02,0x04,0xec,0xbe] +// VI: s_mov_b64 tba, s[2:3] ; encoding: [0x02,0x01,0xec,0xbe] + +s_mov_b64 [tma_lo,tma_hi], s[2:3] +// SICI: s_mov_b64 tma, s[2:3] ; encoding: [0x02,0x04,0xee,0xbe] +// VI: s_mov_b64 tma, s[2:3] ; encoding: [0x02,0x01,0xee,0xbe] + +v_mov_b32 [v1], [v2] +// GCN: v_mov_b32_e32 v1, v2 ; encoding: [0x02,0x03,0x02,0x7e] + +v_rcp_f64 [v1,v2], [v2,v3] +// SICI: v_rcp_f64_e32 v[1:2], v[2:3] ; encoding: [0x02,0x5f,0x02,0x7e] +// VI: v_rcp_f64_e32 v[1:2], v[2:3] ; encoding: [0x02,0x4b,0x02,0x7e] + +buffer_load_dwordx4 [v1,v2,v3,v4], [s4,s5,s6,s7], s1 +// SICI: buffer_load_dwordx4 v[1:4], s[4:7], s1 ; encoding: [0x00,0x00,0x38,0xe0,0x00,0x01,0x01,0x01] +// VI: buffer_load_dwordx4 v[1:4], s[4:7], s1 ; encoding: [0x00,0x00,0x5c,0xe0,0x00,0x01,0x01,0x01] Index: test/MC/AMDGPU/trap.s =================================================================== --- test/MC/AMDGPU/trap.s +++ test/MC/AMDGPU/trap.s @@ -97,3 +97,19 @@ s_mov_b64 ttmp[4:5], exec // SICI: s_mov_b64 ttmp[4:5], exec ; encoding: [0x7e,0x04,0xf4,0xbe] // VI: s_mov_b64 ttmp[4:5], exec ; encoding: [0x7e,0x01,0xf4,0xbe] + +s_mov_b64 tba, ttmp[4:5] +// SICI: s_mov_b64 tba, ttmp[4:5] ; encoding: [0x74,0x04,0xec,0xbe] +// VI: s_mov_b64 tba, ttmp[4:5] ; encoding: [0x74,0x01,0xec,0xbe] + +s_mov_b64 ttmp[4:5], tba +// SICI: s_mov_b64 ttmp[4:5], tba ; encoding: [0x6c,0x04,0xf4,0xbe] +// VI: s_mov_b64 ttmp[4:5], tba ; encoding: [0x6c,0x01,0xf4,0xbe] + +s_mov_b64 tma, ttmp[4:5] +// SICI: s_mov_b64 tma, ttmp[4:5] ; encoding: [0x74,0x04,0xee,0xbe] +// VI: s_mov_b64 tma, ttmp[4:5] ; encoding: [0x74,0x01,0xee,0xbe] + +s_mov_b64 ttmp[4:5], tma +// SICI: s_mov_b64 ttmp[4:5], tma ; encoding: [0x6e,0x04,0xf4,0xbe] +// VI: s_mov_b64 ttmp[4:5], tma ; encoding: [0x6e,0x01,0xf4,0xbe]