@@ -6865,8 +6865,9 @@ static void applyMnemonicAliases(StringRef &Mnemonic,
6865
6865
const FeatureBitset &Features,
6866
6866
unsigned VariantID);
6867
6867
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.
6870
6871
//
6871
6872
// We have to be careful to not emit an invalid Rt2 here, because the rest of
6872
6873
// the assembly parser could then generate confusing diagnostics refering to
@@ -6876,13 +6877,19 @@ static void applyMnemonicAliases(StringRef &Mnemonic,
6876
6877
void ARMAsmParser::fixupGNULDRDAlias (StringRef Mnemonic,
6877
6878
OperandVector &Operands,
6878
6879
unsigned MnemonicOpsEndInd) {
6879
- if (Mnemonic != " ldrd" && Mnemonic != " strd" )
6880
+ if (Mnemonic != " ldrd" && Mnemonic != " strd" && Mnemonic != " ldrexd" &&
6881
+ Mnemonic != " strexd" && Mnemonic != " ldaexd" && Mnemonic != " stlexd" )
6880
6882
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 )
6882
6889
return ;
6883
6890
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 ]);
6886
6893
6887
6894
if (!Op2.isReg ())
6888
6895
return ;
@@ -6907,7 +6914,7 @@ void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic,
6907
6914
return ;
6908
6915
6909
6916
Operands.insert (
6910
- Operands.begin () + MnemonicOpsEndInd + 1 ,
6917
+ Operands.begin () + IdX + 1 ,
6911
6918
ARMOperand::CreateReg (PairedReg, Op2.getStartLoc (), Op2.getEndLoc ()));
6912
6919
}
6913
6920
@@ -7336,47 +7343,53 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
7336
7343
static_cast <ARMOperand &>(*Operands[MnemonicOpsEndInd]).isImm ())
7337
7344
removeCondCode (Operands, MnemonicOpsEndInd);
7338
7345
7346
+ // GNU Assembler extension (compatibility).
7347
+ fixupGNULDRDAlias (Mnemonic, Operands, MnemonicOpsEndInd);
7348
+
7339
7349
// Adjust operands of ldrexd/strexd to MCK_GPRPair.
7340
7350
// ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
7341
7351
// a single GPRPair reg operand is used in the .td file to replace the two
7342
7352
// GPRs. However, when parsing from asm, the two GRPs cannot be
7343
7353
// automatically
7344
7354
// expressed as a GPRPair, so we have to manually merge them.
7345
7355
// 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) &&
7347
7358
(Mnemonic == " ldrexd" || Mnemonic == " strexd" || Mnemonic == " ldaexd" ||
7348
7359
Mnemonic == " stlexd" )) {
7349
- bool isLoad = (Mnemonic == " ldrexd" || Mnemonic == " ldaexd" );
7350
- unsigned Idx = isLoad ? MnemonicOpsEndInd : MnemonicOpsEndInd + 1 ;
7360
+ unsigned Idx = IsLoad ? MnemonicOpsEndInd : MnemonicOpsEndInd + 1 ;
7351
7361
ARMOperand &Op1 = static_cast <ARMOperand &>(*Operands[Idx]);
7352
7362
ARMOperand &Op2 = static_cast <ARMOperand &>(*Operands[Idx + 1 ]);
7353
7363
7354
7364
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 ())) {
7358
7367
unsigned Reg1 = Op1.getReg ();
7359
- unsigned Reg2 = Op2.getReg ();
7360
7368
unsigned Rt = MRI->getEncodingValue (Reg1);
7369
+ unsigned Reg2 = Op2.getReg ();
7361
7370
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)
7365
7373
return Error (Op2.getStartLoc (),
7366
- isLoad ? " destination operands must be sequential"
7374
+ IsLoad ? " destination operands must be sequential"
7367
7375
: " 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
+
7369
7384
unsigned NewReg = MRI->getMatchingSuperReg (
7370
7385
Reg1, ARM::gsub_0, &(MRI->getRegClass (ARM::GPRPairRegClassID)));
7386
+
7371
7387
Operands[Idx] =
7372
7388
ARMOperand::CreateReg (NewReg, Op1.getStartLoc (), Op2.getEndLoc ());
7373
7389
Operands.erase (Operands.begin () + Idx + 1 );
7374
7390
}
7375
7391
}
7376
7392
7377
- // GNU Assembler extension (compatibility).
7378
- fixupGNULDRDAlias (Mnemonic, Operands, MnemonicOpsEndInd);
7379
-
7380
7393
// FIXME: As said above, this is all a pretty gross hack. This instruction
7381
7394
// does not fit with other "subs" and tblgen.
7382
7395
// Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction
0 commit comments