@@ -6865,8 +6865,9 @@ static void applyMnemonicAliases(StringRef &Mnemonic,
68656865 const FeatureBitset &Features,
68666866 unsigned VariantID);
68676867
6868- // The GNU assembler has aliases of ldrd and strd with the second register
6869- // omitted. We don't have a way to do that in tablegen, so fix it up here.
6868+ // The GNU assembler has aliases of ldrd, strd, ldrexd, strexd, ldaexd, and
6869+ // stlexd with the second register omitted. We don't have a way to do that in
6870+ // tablegen, so fix it up here.
68706871//
68716872// We have to be careful to not emit an invalid Rt2 here, because the rest of
68726873// the assembly parser could then generate confusing diagnostics refering to
@@ -6876,13 +6877,19 @@ static void applyMnemonicAliases(StringRef &Mnemonic,
68766877void ARMAsmParser::fixupGNULDRDAlias (StringRef Mnemonic,
68776878 OperandVector &Operands,
68786879 unsigned MnemonicOpsEndInd) {
6879- if (Mnemonic != " ldrd" && Mnemonic != " strd" )
6880+ if (Mnemonic != " ldrd" && Mnemonic != " strd" && Mnemonic != " ldrexd" &&
6881+ Mnemonic != " strexd" && Mnemonic != " ldaexd" && Mnemonic != " stlexd" )
68806882 return ;
6881- if (Operands.size () < MnemonicOpsEndInd + 2 )
6883+
6884+ unsigned IdX = Mnemonic == " strexd" || Mnemonic == " stlexd"
6885+ ? MnemonicOpsEndInd + 1
6886+ : MnemonicOpsEndInd;
6887+
6888+ if (Operands.size () < IdX + 2 )
68826889 return ;
68836890
6884- ARMOperand &Op2 = static_cast <ARMOperand &>(*Operands[MnemonicOpsEndInd ]);
6885- ARMOperand &Op3 = static_cast <ARMOperand &>(*Operands[MnemonicOpsEndInd + 1 ]);
6891+ ARMOperand &Op2 = static_cast <ARMOperand &>(*Operands[IdX ]);
6892+ ARMOperand &Op3 = static_cast <ARMOperand &>(*Operands[IdX + 1 ]);
68866893
68876894 if (!Op2.isReg ())
68886895 return ;
@@ -6907,7 +6914,7 @@ void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic,
69076914 return ;
69086915
69096916 Operands.insert (
6910- Operands.begin () + MnemonicOpsEndInd + 1 ,
6917+ Operands.begin () + IdX + 1 ,
69116918 ARMOperand::CreateReg (PairedReg, Op2.getStartLoc (), Op2.getEndLoc ()));
69126919}
69136920
@@ -7336,47 +7343,53 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
73367343 static_cast <ARMOperand &>(*Operands[MnemonicOpsEndInd]).isImm ())
73377344 removeCondCode (Operands, MnemonicOpsEndInd);
73387345
7346+ // GNU Assembler extension (compatibility).
7347+ fixupGNULDRDAlias (Mnemonic, Operands, MnemonicOpsEndInd);
7348+
73397349 // Adjust operands of ldrexd/strexd to MCK_GPRPair.
73407350 // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
73417351 // a single GPRPair reg operand is used in the .td file to replace the two
73427352 // GPRs. However, when parsing from asm, the two GRPs cannot be
73437353 // automatically
73447354 // expressed as a GPRPair, so we have to manually merge them.
73457355 // FIXME: We would really like to be able to tablegen'erate this.
7346- if (!isThumb () && Operands.size () > MnemonicOpsEndInd + 1 &&
7356+ bool IsLoad = (Mnemonic == " ldrexd" || Mnemonic == " ldaexd" );
7357+ if (!isThumb () && Operands.size () > MnemonicOpsEndInd + 1 + (!IsLoad) &&
73477358 (Mnemonic == " ldrexd" || Mnemonic == " strexd" || Mnemonic == " ldaexd" ||
73487359 Mnemonic == " stlexd" )) {
7349- bool isLoad = (Mnemonic == " ldrexd" || Mnemonic == " ldaexd" );
7350- unsigned Idx = isLoad ? MnemonicOpsEndInd : MnemonicOpsEndInd + 1 ;
7360+ unsigned Idx = IsLoad ? MnemonicOpsEndInd : MnemonicOpsEndInd + 1 ;
73517361 ARMOperand &Op1 = static_cast <ARMOperand &>(*Operands[Idx]);
73527362 ARMOperand &Op2 = static_cast <ARMOperand &>(*Operands[Idx + 1 ]);
73537363
73547364 const MCRegisterClass &MRC = MRI->getRegClass (ARM::GPRRegClassID);
7355- // Adjust only if Op1 and Op2 are GPRs.
7356- if (Op1.isReg () && Op2.isReg () && MRC.contains (Op1.getReg ()) &&
7357- MRC.contains (Op2.getReg ())) {
7365+ // Adjust only if Op1 is a GPR.
7366+ if (Op1.isReg () && MRC.contains (Op1.getReg ())) {
73587367 unsigned Reg1 = Op1.getReg ();
7359- unsigned Reg2 = Op2.getReg ();
73607368 unsigned Rt = MRI->getEncodingValue (Reg1);
7369+ unsigned Reg2 = Op2.getReg ();
73617370 unsigned Rt2 = MRI->getEncodingValue (Reg2);
7362-
7363- // Rt2 must be Rt + 1 and Rt must be even.
7364- if (Rt + 1 != Rt2 || (Rt & 1 )) {
7371+ // Rt2 must be Rt + 1.
7372+ if (Rt + 1 != Rt2)
73657373 return Error (Op2.getStartLoc (),
7366- isLoad ? " destination operands must be sequential"
7374+ IsLoad ? " destination operands must be sequential"
73677375 : " source operands must be sequential" );
7368- }
7376+
7377+ // Rt must be even
7378+ if (Rt & 1 )
7379+ return Error (
7380+ Op1.getStartLoc (),
7381+ IsLoad ? " destination operands must start start at an even register"
7382+ : " source operands must start start at an even register" );
7383+
73697384 unsigned NewReg = MRI->getMatchingSuperReg (
73707385 Reg1, ARM::gsub_0, &(MRI->getRegClass (ARM::GPRPairRegClassID)));
7386+
73717387 Operands[Idx] =
73727388 ARMOperand::CreateReg (NewReg, Op1.getStartLoc (), Op2.getEndLoc ());
73737389 Operands.erase (Operands.begin () + Idx + 1 );
73747390 }
73757391 }
73767392
7377- // GNU Assembler extension (compatibility).
7378- fixupGNULDRDAlias (Mnemonic, Operands, MnemonicOpsEndInd);
7379-
73807393 // FIXME: As said above, this is all a pretty gross hack. This instruction
73817394 // does not fit with other "subs" and tblgen.
73827395 // Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction
0 commit comments