Index: llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -42,6 +42,8 @@ struct OptionalOperand; +enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL }; + class AMDGPUOperand : public MCParsedAsmOperand { enum KindTy { Token, @@ -454,6 +456,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 { @@ -573,8 +577,6 @@ } -enum RegisterKind { IS_VGPR, IS_SGPR, IS_TTMP }; - static int getRegClass(RegisterKind Is, unsigned RegWidth) { if (Is == IS_VGPR) { switch (RegWidth) { @@ -605,14 +607,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) @@ -636,86 +639,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); } @@ -1114,6 +1167,7 @@ AMDGPUOperand::CreateImm(F.bitcastToAPInt().getZExtValue(), S)); return MatchOperand_Success; } + case AsmToken::LBrac: case AsmToken::Identifier: { if (auto R = parseRegister()) { unsigned Modifiers = 0; Index: llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.td =================================================================== --- llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.td +++ llvm/trunk/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: llvm/trunk/test/MC/AMDGPU/trap.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/trap.s +++ llvm/trunk/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]