Skip to content

Commit d2749af

Browse files
Allow double-precision registers in VSCCLRMS
1 parent d1041be commit d2749af

File tree

7 files changed

+101
-23
lines changed

7 files changed

+101
-23
lines changed

llvm/lib/Target/ARM/ARMRegisterInfo.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,9 @@ def FPEXC : ARMReg<8, "fpexc">;
200200
def FPINST : ARMReg<9, "fpinst">;
201201
def FPINST2 : ARMReg<10, "fpinst2">;
202202
// These encodings aren't actual instruction encodings, their encoding depends
203-
// on the instruction they are used in and for VPR 32 was chosen such that it
203+
// on the instruction they are used in and for VPR 64 was chosen such that it
204204
// always comes last in spr_reglist_with_vpr.
205-
def VPR : ARMReg<32, "vpr">;
205+
def VPR : ARMReg<64, "vpr">;
206206
def FPSCR_NZCVQC
207207
: ARMReg<2, "fpscr_nzcvqc">;
208208
def P0 : ARMReg<13, "p0">;

llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,8 @@ class ARMAsmParser : public MCTargetAsmParser {
446446
int tryParseShiftRegister(OperandVector &);
447447
std::optional<ARM_AM::ShiftOpc> tryParseShiftToken();
448448
bool parseRegisterList(OperandVector &, bool EnforceOrder = true,
449-
bool AllowRAAC = false,
450-
bool AllowOutOfBoundReg = false);
449+
bool AllowRAAC = false, bool IsLazyLoadStore = false,
450+
bool IsVSCCLRM = false);
451451
bool parseMemory(OperandVector &);
452452
bool parseOperand(OperandVector &, StringRef Mnemonic);
453453
bool parseImmExpr(int64_t &Out);
@@ -4611,7 +4611,8 @@ insertNoDuplicates(SmallVectorImpl<std::pair<unsigned, MCRegister>> &Regs,
46114611

46124612
/// Parse a register list.
46134613
bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder,
4614-
bool AllowRAAC, bool AllowOutOfBoundReg) {
4614+
bool AllowRAAC, bool IsLazyLoadStore,
4615+
bool IsVSCCLRM) {
46154616
MCAsmParser &Parser = getParser();
46164617
if (Parser.getTok().isNot(AsmToken::LCurly))
46174618
return TokError("Token is not a Left Curly Brace");
@@ -4621,6 +4622,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder,
46214622

46224623
// Check the first register in the list to see what register class
46234624
// this is a list of.
4625+
bool AllowOutOfBoundReg = IsLazyLoadStore || IsVSCCLRM;
46244626
MCRegister Reg = tryParseRegister(AllowOutOfBoundReg);
46254627
if (!Reg)
46264628
return Error(RegLoc, "register expected");
@@ -4631,6 +4633,13 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder,
46314633
int EReg = 0;
46324634
SmallVector<std::pair<unsigned, MCRegister>, 32> Registers;
46334635

4636+
// Single-precision VSCCLRM can have double-precision registers in the
4637+
// register list. When VSCCLRMAdjustEncoding is true then we've switched from
4638+
// single-precision to double-precision and we pretend that these registers
4639+
// are encoded as S32 onwards, which we can do by adding 16 to the encoding
4640+
// value.
4641+
bool VSCCLRMAdjustEncoding = false;
4642+
46344643
// Allow Q regs and just interpret them as the two D sub-registers.
46354644
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
46364645
Reg = getDRegFromQReg(Reg);
@@ -4690,6 +4699,8 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder,
46904699
while (Reg != EndReg) {
46914700
Reg = getNextRegister(Reg);
46924701
EReg = MRI->getEncodingValue(Reg);
4702+
if (VSCCLRMAdjustEncoding)
4703+
EReg += 16;
46934704
if (!insertNoDuplicates(Registers, EReg, Reg)) {
46944705
Warning(AfterMinusLoc, StringRef("duplicated register (") +
46954706
ARMInstPrinter::getRegisterName(Reg) +
@@ -4701,6 +4712,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder,
47014712
Parser.Lex(); // Eat the comma.
47024713
RegLoc = Parser.getTok().getLoc();
47034714
MCRegister OldReg = Reg;
4715+
int EOldReg = EReg;
47044716
const AsmToken RegTok = Parser.getTok();
47054717
Reg = tryParseRegister(AllowOutOfBoundReg);
47064718
if (!Reg)
@@ -4732,6 +4744,12 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder,
47324744
}
47334745
continue;
47344746
}
4747+
// VSCCLRM can switch from single-precision to double-precision only when
4748+
// S31 is followed by D16.
4749+
if (IsVSCCLRM && OldReg == ARM::S31 && Reg == ARM::D16) {
4750+
VSCCLRMAdjustEncoding = true;
4751+
RC = &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID];
4752+
}
47354753
// The register must be in the same register class as the first.
47364754
if ((Reg == ARM::RA_AUTH_CODE &&
47374755
RC != &ARMMCRegisterClasses[ARM::GPRRegClassID]) ||
@@ -4741,8 +4759,10 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder,
47414759
// exception is CLRM, which is order-independent anyway, so
47424760
// there's no potential for confusion if you write clrm {r2,r1}
47434761
// instead of clrm {r1,r2}.
4744-
if (EnforceOrder &&
4745-
MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) {
4762+
EReg = MRI->getEncodingValue(Reg);
4763+
if (VSCCLRMAdjustEncoding)
4764+
EReg += 16;
4765+
if (EnforceOrder && EReg < EOldReg) {
47464766
if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
47474767
Warning(RegLoc, "register list not in ascending order");
47484768
else if (!ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg))
@@ -4751,9 +4771,9 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder,
47514771
// VFP register lists must also be contiguous.
47524772
if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
47534773
RC != &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID] &&
4754-
Reg != OldReg + 1)
4774+
EReg != EOldReg + 1)
47554775
return Error(RegLoc, "non-contiguous register range");
4756-
EReg = MRI->getEncodingValue(Reg);
4776+
47574777
if (!insertNoDuplicates(Registers, EReg, Reg)) {
47584778
Warning(RegLoc, "duplicated register (" + RegTok.getString() +
47594779
") in register list");
@@ -6341,10 +6361,10 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
63416361
case AsmToken::LBrac:
63426362
return parseMemory(Operands);
63436363
case AsmToken::LCurly: {
6344-
bool AllowOutOfBoundReg =
6345-
Mnemonic == "vlldm" || Mnemonic == "vlstm" || Mnemonic == "vscclrm";
6364+
bool IsLazyLoadStore = Mnemonic == "vlldm" || Mnemonic == "vlstm";
6365+
bool IsVSCCLRM = Mnemonic == "vscclrm";
63466366
return parseRegisterList(Operands, !Mnemonic.starts_with("clr"), false,
6347-
AllowOutOfBoundReg);
6367+
IsLazyLoadStore, IsVSCCLRM);
63486368
}
63496369
case AsmToken::Dollar:
63506370
case AsmToken::Hash: {

llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,7 @@ static const uint16_t DPRDecoderTable[] = {
15301530

15311531
// Does this instruction/subtarget permit use of registers d16-d31?
15321532
static bool PermitsD32(const MCInst &Inst, const MCDisassembler *Decoder) {
1533-
if (Inst.getOpcode() == ARM::VSCCLRMD)
1533+
if (Inst.getOpcode() == ARM::VSCCLRMD || Inst.getOpcode() == ARM::VSCCLRMS)
15341534
return true;
15351535
const FeatureBitset &featureBits =
15361536
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
@@ -6461,11 +6461,21 @@ static DecodeStatus DecodeVSCCLRM(MCInst &Inst, unsigned Insn, uint64_t Address,
64616461
return MCDisassembler::Fail;
64626462
}
64636463
} else {
6464-
unsigned reglist = regs | (fieldFromInstruction(Insn, 22, 1) << 8) |
6465-
(fieldFromInstruction(Insn, 12, 4) << 9);
6466-
if (!Check(S, DecodeSPRRegListOperand(Inst, reglist, Address, Decoder))) {
6467-
return MCDisassembler::Fail;
6468-
}
6464+
unsigned Vd = (fieldFromInstruction(Insn, 12, 4) << 1) |
6465+
fieldFromInstruction(Insn, 22, 1);
6466+
// Registers past s31 are permitted and treated as being half of a d
6467+
// register, though both halves of each d register must be present.
6468+
unsigned max_reg = Vd + regs;
6469+
if (max_reg > 64 || (max_reg > 32 && (max_reg & 1)))
6470+
S = MCDisassembler::SoftFail;
6471+
unsigned max_sreg = std::min(32u, max_reg);
6472+
unsigned max_dreg = std::min(32u, max_reg / 2);
6473+
for (unsigned i = Vd; i < max_sreg; ++i)
6474+
if (!Check(S, DecodeSPRRegisterClass(Inst, i, Address, Decoder)))
6475+
return MCDisassembler::Fail;
6476+
for (unsigned i = 16; i < max_dreg; ++i)
6477+
if (!Check(S, DecodeDPRRegisterClass(Inst, i, Address, Decoder)))
6478+
return MCDisassembler::Fail;
64696479
}
64706480
Inst.addOperand(MCOperand::createReg(ARM::VPR));
64716481

llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
851851
void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
852852
const MCSubtargetInfo &STI,
853853
raw_ostream &O) {
854-
if (MI->getOpcode() != ARM::t2CLRM) {
854+
if (MI->getOpcode() != ARM::t2CLRM && MI->getOpcode() != ARM::VSCCLRMS) {
855855
assert(is_sorted(drop_begin(*MI, OpNum),
856856
[&](const MCOperand &LHS, const MCOperand &RHS) {
857857
return MRI.getEncodingValue(LHS.getReg()) <

llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,9 +1749,22 @@ getRegisterListOpValue(const MCInst &MI, unsigned Op,
17491749
unsigned NumRegs = (MI.getNumOperands() - Op) & 0xff;
17501750
Binary |= (RegNo & 0x1f) << 8;
17511751

1752-
// Ignore VPR
1753-
if (MI.getOpcode() == ARM::VSCCLRMD || MI.getOpcode() == ARM::VSCCLRMS)
1752+
if (MI.getOpcode() == ARM::VSCCLRMD)
1753+
// Ignore VPR
17541754
--NumRegs;
1755+
else if (MI.getOpcode() == ARM::VSCCLRMS) {
1756+
// The register list can contain both S registers and D registers, with D
1757+
// registers counting as two registers. VPR doesn't count towards the
1758+
// number of registers.
1759+
NumRegs = 0;
1760+
for (unsigned I = Op, E = MI.getNumOperands(); I < E; ++I) {
1761+
Reg = MI.getOperand(I).getReg();
1762+
if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
1763+
NumRegs += 1;
1764+
else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
1765+
NumRegs += 2;
1766+
}
1767+
}
17551768
if (SPRRegs)
17561769
Binary |= NumRegs;
17571770
else

llvm/test/MC/ARM/vscclrm-asm.s

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,21 @@ vscclrm {d0-d31, vpr}
4444
// CHECK: vscclrm {d31, vpr} @ encoding: [0xdf,0xec,0x02,0xfb]
4545
vscclrm {d31, vpr}
4646

47+
// CHECK: vscclrm {s31, d16, vpr} @ encoding: [0xdf,0xec,0x03,0xfa]
48+
vscclrm {s31, d16, vpr}
49+
50+
// CHECK: vscclrm {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31, vpr} @ encoding: [0x9f,0xec,0x40,0x0a]
51+
vscclrm {s0-s31, d16-d31, vpr}
52+
53+
// CHECK: vscclrm {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31, vpr} @ encoding: [0x9f,0xec,0x40,0x0a]
54+
vscclrm {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31, vpr}
55+
4756
// ERROR: non-contiguous register range
4857
vscclrm {s0, s3-s4, vpr}
4958

59+
// ERROR: non-contiguous register range
60+
vscclrm {s31, d16, s30, vpr}
61+
5062
// ERROR: register expected
5163
vscclrm {s32, vpr}
5264

@@ -73,3 +85,12 @@ vscclrm {vpr, d0}
7385

7486
// ERROR: register list not in ascending order
7587
vscclrm {vpr, d31}
88+
89+
// ERROR: invalid register in register list
90+
vscclrm {s0, d0, vpr}
91+
92+
// ERROR: invalid register in register list
93+
vscclrm {s0, d1, vpr}
94+
95+
// ERROR: invalid register in register list
96+
vscclrm {d16, s31, vpr}

llvm/test/MC/Disassembler/ARM/vscclrm.txt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030
[0xdf 0xec 0x1d 0x1a]
3131
# CHECK: vscclrmhi {s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, vpr}
3232

33+
[0xdf,0xec,0x03,0xfa]
34+
# CHECK: vscclrm {s31, d16, vpr} @ encoding: [0xdf,0xec,0x03,0xfa]
35+
36+
[0x9f,0xec,0x40,0x0a]
37+
# CHECK: vscclrm {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31, vpr} @ encoding: [0x9f,0xec,0x40,0x0a]
38+
3339
# If the list size is zero then we get a list of only vpr, and the Vd register
3440
# doesn't matter.
3541

@@ -45,7 +51,8 @@
4551
[0xdf,0xec,0x00,0xfa]
4652
# CHECK: vscclrm {vpr} @ encoding: [0x9f,0xec,0x00,0x0a]
4753

48-
# If Vd+size goes past 31 the excess registers are ignored and we get a warning.
54+
# In double-precision if Vd+size goes past 31 the excess registers are ignored
55+
# and we get a warning.
4956

5057
[0x9f,0xec,0xfe,0x0b]
5158
# WARN: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
@@ -55,10 +62,17 @@
5562
# WARN: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
5663
# CHECK: vscclrm {d31, vpr} @ encoding: [0xdf,0xec,0x02,0xfb]
5764

65+
# In single-precision if Vd+size goes past 63, or if the encoding suggests half
66+
# a d registers, then the excess registers are ignored and we get a warning.
67+
5868
[0x9f,0xec,0xff,0x0a]
5969
# WARN: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
60-
# CHECK: vscclrm {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, vpr} @ encoding: [0x9f,0xec,0x20,0x0a]
70+
# CHECK: vscclrm {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31, vpr} @ encoding: [0x9f,0xec,0x40,0x0a]
6171

6272
[0xdf,0xec,0x02,0xfa]
6373
# WARN: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
6474
# CHECK: vscclrm {s31, vpr} @ encoding: [0xdf,0xec,0x01,0xfa]
75+
76+
[0xdf,0xec,0x23,0xfa]
77+
# WARN: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
78+
vscclrm {s31, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31, vpr} @ encoding: [0xdf,0xec,0x21,0xfa]

0 commit comments

Comments
 (0)