Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 26 additions & 14 deletions llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7343,34 +7343,46 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
// automatically
// expressed as a GPRPair, so we have to manually merge them.
// FIXME: We would really like to be able to tablegen'erate this.
if (!isThumb() && Operands.size() > MnemonicOpsEndInd + 1 &&
bool IsLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd");
if (!isThumb() && Operands.size() > MnemonicOpsEndInd + 1 + (!IsLoad) &&
(Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" ||
Mnemonic == "stlexd")) {
bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd");
unsigned Idx = isLoad ? MnemonicOpsEndInd : MnemonicOpsEndInd + 1;
unsigned Idx = IsLoad ? MnemonicOpsEndInd : MnemonicOpsEndInd + 1;
ARMOperand &Op1 = static_cast<ARMOperand &>(*Operands[Idx]);
ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[Idx + 1]);

const MCRegisterClass &MRC = MRI->getRegClass(ARM::GPRRegClassID);
// Adjust only if Op1 and Op2 are GPRs.
if (Op1.isReg() && Op2.isReg() && MRC.contains(Op1.getReg()) &&
MRC.contains(Op2.getReg())) {
bool IsGNUAlias = !(Op2.isReg() && MRC.contains(Op2.getReg()));
// Adjust only if Op1 is a GPR.
if (Op1.isReg() && MRC.contains(Op1.getReg())) {
unsigned Reg1 = Op1.getReg();
unsigned Reg2 = Op2.getReg();
unsigned Rt = MRI->getEncodingValue(Reg1);
unsigned Rt2 = MRI->getEncodingValue(Reg2);

// Rt2 must be Rt + 1 and Rt must be even.
if (Rt + 1 != Rt2 || (Rt & 1)) {
return Error(Op2.getStartLoc(),
isLoad ? "destination operands must be sequential"
: "source operands must be sequential");
// Check we are not in the GNU alias case with only one of the register
// pair specified
if (!IsGNUAlias) {
unsigned Reg2 = Op2.getReg();
unsigned Rt2 = MRI->getEncodingValue(Reg2);
// Rt2 must be Rt + 1.
if (Rt + 1 != Rt2)
return Error(Op2.getStartLoc(),
IsLoad ? "destination operands must be sequential"
: "source operands must be sequential");
}
// Rt must be even
if (Rt & 1)
return Error(
Op1.getStartLoc(),
IsLoad ? "destination operands must start start at an even register"
: "source operands must start start at an even register");

unsigned NewReg = MRI->getMatchingSuperReg(
Reg1, ARM::gsub_0, &(MRI->getRegClass(ARM::GPRPairRegClassID)));
Operands[Idx] =
ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc());
Operands.erase(Operands.begin() + Idx + 1);
// redundant operand only exists if not in GNU alias case
if (!IsGNUAlias)
Operands.erase(Operands.begin() + Idx + 1);
}
}

Expand Down
8 changes: 8 additions & 0 deletions llvm/test/MC/ARM/basic-arm-instructions.s
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,10 @@ Lforward:
@ CHECK: ldrex r1, [r7] @ encoding: [0x9f,0x1f,0x97,0xe1]
@ CHECK: ldrexd r6, r7, [r8] @ encoding: [0x9f,0x6f,0xb8,0xe1]

@ GNU alias
ldrexd r6, [r8]
@ CHECK: ldrexd r6, r7, [r8] @ encoding: [0x9f,0x6f,0xb8,0xe1]

@------------------------------------------------------------------------------
@ LDRHT
@------------------------------------------------------------------------------
Expand Down Expand Up @@ -2904,6 +2908,10 @@ Lforward:
@ CHECK: strex r2, r1, [r7] @ encoding: [0x91,0x2f,0x87,0xe1]
@ CHECK: strexd r6, r2, r3, [r8] @ encoding: [0x92,0x6f,0xa8,0xe1]

@ GNU alias
strexd r6, r2, [r8]
@ CHECK: strexd r6, r2, r3, [r8] @ encoding: [0x92,0x6f,0xa8,0xe1]

@------------------------------------------------------------------------------
@ STR
@------------------------------------------------------------------------------
Expand Down