Skip to content

Commit 0b001f9

Browse files
committed
[ARM] Add <saturate> operand to SQRSHRL and UQRSHLL
Summary: According to the new Armv8-M specification https://static.docs.arm.com/ddi0553/bh/DDI0553B_h_armv8m_arm.pdf the instructions SQRSHRL and UQRSHLL now have an additional immediate operand <saturate>. The new assembly syntax is: SQRSHRL<c> RdaLo, RdaHi, #<saturate>, Rm UQRSHLL<c> RdaLo, RdaHi, #<saturate>, Rm where <saturate> can be either 64 (the existing behavior) or 48, in that case the result is saturated to 48 bits. The new operand is encoded as follows: #64 Encoded as sat = 0 #48 Encoded as sat = 1 sat is bit 7 of the instruction bit pattern. This patch adds a new assembler operand class MveSaturateOperand which implements parsing and encoding. Decoding is implemented in DecodeMVEOverlappingLongShift. Reviewers: ostannard, simon_tatham, t.p.northover, samparker, dmgreen, SjoerdMeijer Reviewed By: simon_tatham Subscribers: javed.absar, kristof.beyls, hiraditya, pbarrio, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D64810 llvm-svn: 366555
1 parent 9c37710 commit 0b001f9

File tree

8 files changed

+91
-17
lines changed

8 files changed

+91
-17
lines changed

llvm/lib/Target/ARM/ARMInstrFormats.td

+10
Original file line numberDiff line numberDiff line change
@@ -2724,6 +2724,16 @@ def complexrotateopodd : Operand<i32> {
27242724
let PrintMethod = "printComplexRotationOp<180, 90>";
27252725
}
27262726

2727+
def MveSaturateOperand : AsmOperandClass {
2728+
let PredicateMethod = "isMveSaturateOp";
2729+
let DiagnosticString = "saturate operand must be 48 or 64";
2730+
let Name = "MveSaturate";
2731+
}
2732+
def saturateop : Operand<i32> {
2733+
let ParserMatchClass = MveSaturateOperand;
2734+
let PrintMethod = "printMveSaturateOp";
2735+
}
2736+
27272737
// Data type suffix token aliases. Implements Table A7-3 in the ARM ARM.
27282738
def : TokenAlias<".s8", ".i8">;
27292739
def : TokenAlias<".u8", ".i8">;

llvm/lib/Target/ARM/ARMInstrMVE.td

+26-10
Original file line numberDiff line numberDiff line change
@@ -403,18 +403,17 @@ class MVE_ScalarShiftDRegImm<string iname, bits<2> op5_4, bit op16,
403403
let Inst{3-0} = 0b1111;
404404
}
405405

406-
class MVE_ScalarShiftDRegReg<string iname, bit op5, bit op16,
407-
list<dag> pattern=[]>
406+
class MVE_ScalarShiftDRegRegBase<string iname, dag iops, string asm,
407+
bit op5, bit op16, list<dag> pattern=[]>
408408
: MVE_ScalarShiftDoubleReg<
409-
iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm),
410-
"$RdaLo, $RdaHi, $Rm", "@earlyclobber $RdaHi,@earlyclobber $RdaLo,"
411-
"$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src",
409+
iname, iops, asm, "@earlyclobber $RdaHi,@earlyclobber $RdaLo,"
410+
"$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src",
412411
pattern> {
413412
bits<4> Rm;
414413

415414
let Inst{16} = op16;
416415
let Inst{15-12} = Rm{3-0};
417-
let Inst{7-6} = 0b00;
416+
let Inst{6} = 0b0;
418417
let Inst{5} = op5;
419418
let Inst{4} = 0b0;
420419
let Inst{3-0} = 0b1101;
@@ -427,13 +426,30 @@ class MVE_ScalarShiftDRegReg<string iname, bit op5, bit op16,
427426
let DecoderMethod = "DecodeMVEOverlappingLongShift";
428427
}
429428

430-
def MVE_ASRLr : MVE_ScalarShiftDRegReg<"asrl", 0b1, 0b0, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
429+
class MVE_ScalarShiftDRegReg<string iname, bit op5, list<dag> pattern=[]>
430+
: MVE_ScalarShiftDRegRegBase<
431+
iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm),
432+
"$RdaLo, $RdaHi, $Rm", op5, 0b0, pattern> {
433+
434+
let Inst{7} = 0b0;
435+
}
436+
437+
class MVE_ScalarShiftDRegRegWithSat<string iname, bit op5, list<dag> pattern=[]>
438+
: MVE_ScalarShiftDRegRegBase<
439+
iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm, saturateop:$sat),
440+
"$RdaLo, $RdaHi, $sat, $Rm", op5, 0b1, pattern> {
441+
bit sat;
442+
443+
let Inst{7} = sat;
444+
}
445+
446+
def MVE_ASRLr : MVE_ScalarShiftDRegReg<"asrl", 0b1, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
431447
(ARMasrl tGPREven:$RdaLo_src,
432448
tGPROdd:$RdaHi_src, rGPR:$Rm))]>;
433449
def MVE_ASRLi : MVE_ScalarShiftDRegImm<"asrl", 0b10, ?, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
434450
(ARMasrl tGPREven:$RdaLo_src,
435451
tGPROdd:$RdaHi_src, (i32 imm:$imm)))]>;
436-
def MVE_LSLLr : MVE_ScalarShiftDRegReg<"lsll", 0b0, 0b0, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
452+
def MVE_LSLLr : MVE_ScalarShiftDRegReg<"lsll", 0b0, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
437453
(ARMlsll tGPREven:$RdaLo_src,
438454
tGPROdd:$RdaHi_src, rGPR:$Rm))]>;
439455
def MVE_LSLLi : MVE_ScalarShiftDRegImm<"lsll", 0b00, ?, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
@@ -443,11 +459,11 @@ def MVE_LSRL : MVE_ScalarShiftDRegImm<"lsrl", 0b01, ?, [(set tGPREven:$Rda
443459
(ARMlsrl tGPREven:$RdaLo_src,
444460
tGPROdd:$RdaHi_src, (i32 imm:$imm)))]>;
445461

446-
def MVE_SQRSHRL : MVE_ScalarShiftDRegReg<"sqrshrl", 0b1, 0b1>;
462+
def MVE_SQRSHRL : MVE_ScalarShiftDRegRegWithSat<"sqrshrl", 0b1>;
447463
def MVE_SQSHLL : MVE_ScalarShiftDRegImm<"sqshll", 0b11, 0b1>;
448464
def MVE_SRSHRL : MVE_ScalarShiftDRegImm<"srshrl", 0b10, 0b1>;
449465

450-
def MVE_UQRSHLL : MVE_ScalarShiftDRegReg<"uqrshll", 0b0, 0b1>;
466+
def MVE_UQRSHLL : MVE_ScalarShiftDRegRegWithSat<"uqrshll", 0b0>;
451467
def MVE_UQSHLL : MVE_ScalarShiftDRegImm<"uqshll", 0b00, 0b1>;
452468
def MVE_URSHRL : MVE_ScalarShiftDRegImm<"urshrl", 0b01, 0b1>;
453469

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

+16
Original file line numberDiff line numberDiff line change
@@ -2275,6 +2275,14 @@ class ARMOperand : public MCParsedAsmOperand {
22752275
return Value >= 1 && Value <= 32;
22762276
}
22772277

2278+
bool isMveSaturateOp() const {
2279+
if (!isImm()) return false;
2280+
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2281+
if (!CE) return false;
2282+
uint64_t Value = CE->getValue();
2283+
return Value == 48 || Value == 64;
2284+
}
2285+
22782286
bool isITCondCodeNoAL() const {
22792287
if (!isITCondCode()) return false;
22802288
ARMCC::CondCodes CC = getCondCode();
@@ -3370,6 +3378,14 @@ class ARMOperand : public MCParsedAsmOperand {
33703378
Inst.addOperand(MCOperand::createImm((CE->getValue() - 90) / 180));
33713379
}
33723380

3381+
void addMveSaturateOperands(MCInst &Inst, unsigned N) const {
3382+
assert(N == 1 && "Invalid number of operands!");
3383+
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
3384+
unsigned Imm = CE->getValue();
3385+
assert((Imm == 48 || Imm == 64) && "Invalid saturate operand");
3386+
Inst.addOperand(MCOperand::createImm(Imm == 48 ? 1 : 0));
3387+
}
3388+
33733389
void print(raw_ostream &OS) const override;
33743390

33753391
static std::unique_ptr<ARMOperand> CreateITMask(unsigned Mask, SMLoc S) {

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

+7
Original file line numberDiff line numberDiff line change
@@ -6503,6 +6503,13 @@ static DecodeStatus DecodeMVEOverlappingLongShift(
65036503
if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
65046504
return MCDisassembler::Fail;
65056505

6506+
if (Inst.getOpcode() == ARM::MVE_SQRSHRL ||
6507+
Inst.getOpcode() == ARM::MVE_UQRSHLL) {
6508+
unsigned Saturate = fieldFromInstruction(Insn, 7, 1);
6509+
// Saturate, the bit position for saturation
6510+
Inst.addOperand(MCOperand::createImm(Saturate));
6511+
}
6512+
65066513
return S;
65076514
}
65086515

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

+8
Original file line numberDiff line numberDiff line change
@@ -1676,3 +1676,11 @@ void ARMInstPrinter::printExpandedImmOperand(const MCInst *MI, unsigned OpNum,
16761676
O.write_hex(Val);
16771677
O << markup(">");
16781678
}
1679+
1680+
void ARMInstPrinter::printMveSaturateOp(const MCInst *MI, unsigned OpNum,
1681+
const MCSubtargetInfo &STI,
1682+
raw_ostream &O) {
1683+
uint32_t Val = MI->getOperand(OpNum).getImm();
1684+
assert(Val <= 1 && "Invalid MVE saturate operand");
1685+
O << "#" << (Val == 1 ? 48 : 64);
1686+
}

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ class ARMInstPrinter : public MCInstPrinter {
262262
const MCSubtargetInfo &STI, raw_ostream &O);
263263
void printExpandedImmOperand(const MCInst *MI, unsigned OpNum,
264264
const MCSubtargetInfo &STI, raw_ostream &O);
265-
265+
void printMveSaturateOp(const MCInst *MI, unsigned OpNum,
266+
const MCSubtargetInfo &STI, raw_ostream &O);
266267
private:
267268
unsigned DefaultAltIdx = ARM::NoRegAltName;
268269
};

llvm/test/MC/ARM/mve-scalar-shift.s

+12-4
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,13 @@ sqrshr lr, r12
111111
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve
112112
sqrshr r11, r12
113113

114-
# CHECK: sqrshrl lr, r3, r8 @ encoding: [0x5f,0xea,0x2d,0x83]
114+
# CHECK: sqrshrl lr, r3, #64, r8 @ encoding: [0x5f,0xea,0x2d,0x83]
115115
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve
116-
sqrshrl lr, r3, r8
116+
sqrshrl lr, r3, #64, r8
117+
118+
# ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: saturate operand must be 48 or 64
119+
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction
120+
sqrshrl lr, r3, #32, r8
117121

118122
# CHECK: sqshl lr, #17 @ encoding: [0x5e,0xea,0x7f,0x4f]
119123
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve
@@ -135,9 +139,13 @@ srshrl lr, r11, #23
135139
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve
136140
uqrshl lr, r1
137141

138-
# CHECK: uqrshll lr, r1, r4 @ encoding: [0x5f,0xea,0x0d,0x41]
142+
# CHECK: uqrshll lr, r1, #48, r4 @ encoding: [0x5f,0xea,0x8d,0x41]
139143
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve
140-
uqrshll lr, r1, r4
144+
uqrshll lr, r1, #48, r4
145+
146+
# ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: saturate operand must be 48 or 64
147+
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction
148+
uqrshll lr, r1, #0, r4
141149

142150
# CHECK: uqshl r0, #1 @ encoding: [0x50,0xea,0x4f,0x0f]
143151
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve

llvm/test/MC/Disassembler/ARM/mve-scalar-shift.txt

+10-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@
2727
# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
2828

2929
[0x5f 0xea 0x2d 0x83]
30-
# CHECK: sqrshrl lr, r3, r8 @ encoding: [0x5f,0xea,0x2d,0x83]
30+
# CHECK: sqrshrl lr, r3, #64, r8 @ encoding: [0x5f,0xea,0x2d,0x83]
31+
# CHECK-NOMVE: [[@LINE-2]]:2: warning: invalid instruction encoding
32+
33+
[0x5f 0xea 0xad 0x83]
34+
# CHECK: sqrshrl lr, r3, #48, r8 @ encoding: [0x5f,0xea,0xad,0x83]
3135
# CHECK-NOMVE: [[@LINE-2]]:2: warning: invalid instruction encoding
3236

3337
[0x5e 0xea 0x7f 0x4f]
@@ -63,7 +67,11 @@
6367
# CHECK-NOMVE: [[@LINE-2]]:2: warning: invalid instruction encoding
6468

6569
[0x5f 0xea 0x0d 0x41]
66-
# CHECK: uqrshll lr, r1, r4 @ encoding: [0x5f,0xea,0x0d,0x41]
70+
# CHECK: uqrshll lr, r1, #64, r4 @ encoding: [0x5f,0xea,0x0d,0x41]
71+
# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
72+
73+
[0x5f 0xea 0x8d 0x41]
74+
# CHECK: uqrshll lr, r1, #48, r4 @ encoding: [0x5f,0xea,0x8d,0x41]
6775
# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
6876

6977
[0x50 0xea 0x4f 0x0f]

0 commit comments

Comments
 (0)