Skip to content

Commit

Permalink
[ARM] Add <saturate> operand to SQRSHRL and UQRSHLL
Browse files Browse the repository at this point in the history
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:
  llvm#64 Encoded as sat = 0
  llvm#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
  • Loading branch information
miyuki committed Jul 19, 2019
1 parent 9c37710 commit 0b001f9
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 17 deletions.
10 changes: 10 additions & 0 deletions llvm/lib/Target/ARM/ARMInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -2724,6 +2724,16 @@ def complexrotateopodd : Operand<i32> {
let PrintMethod = "printComplexRotationOp<180, 90>";
}

def MveSaturateOperand : AsmOperandClass {
let PredicateMethod = "isMveSaturateOp";
let DiagnosticString = "saturate operand must be 48 or 64";
let Name = "MveSaturate";
}
def saturateop : Operand<i32> {
let ParserMatchClass = MveSaturateOperand;
let PrintMethod = "printMveSaturateOp";
}

// Data type suffix token aliases. Implements Table A7-3 in the ARM ARM.
def : TokenAlias<".s8", ".i8">;
def : TokenAlias<".u8", ".i8">;
Expand Down
36 changes: 26 additions & 10 deletions llvm/lib/Target/ARM/ARMInstrMVE.td
Original file line number Diff line number Diff line change
Expand Up @@ -403,18 +403,17 @@ class MVE_ScalarShiftDRegImm<string iname, bits<2> op5_4, bit op16,
let Inst{3-0} = 0b1111;
}

class MVE_ScalarShiftDRegReg<string iname, bit op5, bit op16,
list<dag> pattern=[]>
class MVE_ScalarShiftDRegRegBase<string iname, dag iops, string asm,
bit op5, bit op16, list<dag> pattern=[]>
: MVE_ScalarShiftDoubleReg<
iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm),
"$RdaLo, $RdaHi, $Rm", "@earlyclobber $RdaHi,@earlyclobber $RdaLo,"
"$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src",
iname, iops, asm, "@earlyclobber $RdaHi,@earlyclobber $RdaLo,"
"$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src",
pattern> {
bits<4> Rm;

let Inst{16} = op16;
let Inst{15-12} = Rm{3-0};
let Inst{7-6} = 0b00;
let Inst{6} = 0b0;
let Inst{5} = op5;
let Inst{4} = 0b0;
let Inst{3-0} = 0b1101;
Expand All @@ -427,13 +426,30 @@ class MVE_ScalarShiftDRegReg<string iname, bit op5, bit op16,
let DecoderMethod = "DecodeMVEOverlappingLongShift";
}

def MVE_ASRLr : MVE_ScalarShiftDRegReg<"asrl", 0b1, 0b0, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
class MVE_ScalarShiftDRegReg<string iname, bit op5, list<dag> pattern=[]>
: MVE_ScalarShiftDRegRegBase<
iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm),
"$RdaLo, $RdaHi, $Rm", op5, 0b0, pattern> {

let Inst{7} = 0b0;
}

class MVE_ScalarShiftDRegRegWithSat<string iname, bit op5, list<dag> pattern=[]>
: MVE_ScalarShiftDRegRegBase<
iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm, saturateop:$sat),
"$RdaLo, $RdaHi, $sat, $Rm", op5, 0b1, pattern> {
bit sat;

let Inst{7} = sat;
}

def MVE_ASRLr : MVE_ScalarShiftDRegReg<"asrl", 0b1, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
(ARMasrl tGPREven:$RdaLo_src,
tGPROdd:$RdaHi_src, rGPR:$Rm))]>;
def MVE_ASRLi : MVE_ScalarShiftDRegImm<"asrl", 0b10, ?, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
(ARMasrl tGPREven:$RdaLo_src,
tGPROdd:$RdaHi_src, (i32 imm:$imm)))]>;
def MVE_LSLLr : MVE_ScalarShiftDRegReg<"lsll", 0b0, 0b0, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
def MVE_LSLLr : MVE_ScalarShiftDRegReg<"lsll", 0b0, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
(ARMlsll tGPREven:$RdaLo_src,
tGPROdd:$RdaHi_src, rGPR:$Rm))]>;
def MVE_LSLLi : MVE_ScalarShiftDRegImm<"lsll", 0b00, ?, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
Expand All @@ -443,11 +459,11 @@ def MVE_LSRL : MVE_ScalarShiftDRegImm<"lsrl", 0b01, ?, [(set tGPREven:$Rda
(ARMlsrl tGPREven:$RdaLo_src,
tGPROdd:$RdaHi_src, (i32 imm:$imm)))]>;

def MVE_SQRSHRL : MVE_ScalarShiftDRegReg<"sqrshrl", 0b1, 0b1>;
def MVE_SQRSHRL : MVE_ScalarShiftDRegRegWithSat<"sqrshrl", 0b1>;
def MVE_SQSHLL : MVE_ScalarShiftDRegImm<"sqshll", 0b11, 0b1>;
def MVE_SRSHRL : MVE_ScalarShiftDRegImm<"srshrl", 0b10, 0b1>;

def MVE_UQRSHLL : MVE_ScalarShiftDRegReg<"uqrshll", 0b0, 0b1>;
def MVE_UQRSHLL : MVE_ScalarShiftDRegRegWithSat<"uqrshll", 0b0>;
def MVE_UQSHLL : MVE_ScalarShiftDRegImm<"uqshll", 0b00, 0b1>;
def MVE_URSHRL : MVE_ScalarShiftDRegImm<"urshrl", 0b01, 0b1>;

Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2275,6 +2275,14 @@ class ARMOperand : public MCParsedAsmOperand {
return Value >= 1 && Value <= 32;
}

bool isMveSaturateOp() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
uint64_t Value = CE->getValue();
return Value == 48 || Value == 64;
}

bool isITCondCodeNoAL() const {
if (!isITCondCode()) return false;
ARMCC::CondCodes CC = getCondCode();
Expand Down Expand Up @@ -3370,6 +3378,14 @@ class ARMOperand : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::createImm((CE->getValue() - 90) / 180));
}

void addMveSaturateOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
unsigned Imm = CE->getValue();
assert((Imm == 48 || Imm == 64) && "Invalid saturate operand");
Inst.addOperand(MCOperand::createImm(Imm == 48 ? 1 : 0));
}

void print(raw_ostream &OS) const override;

static std::unique_ptr<ARMOperand> CreateITMask(unsigned Mask, SMLoc S) {
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6503,6 +6503,13 @@ static DecodeStatus DecodeMVEOverlappingLongShift(
if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
return MCDisassembler::Fail;

if (Inst.getOpcode() == ARM::MVE_SQRSHRL ||
Inst.getOpcode() == ARM::MVE_UQRSHLL) {
unsigned Saturate = fieldFromInstruction(Insn, 7, 1);
// Saturate, the bit position for saturation
Inst.addOperand(MCOperand::createImm(Saturate));
}

return S;
}

Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1676,3 +1676,11 @@ void ARMInstPrinter::printExpandedImmOperand(const MCInst *MI, unsigned OpNum,
O.write_hex(Val);
O << markup(">");
}

void ARMInstPrinter::printMveSaturateOp(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O) {
uint32_t Val = MI->getOperand(OpNum).getImm();
assert(Val <= 1 && "Invalid MVE saturate operand");
O << "#" << (Val == 1 ? 48 : 64);
}
3 changes: 2 additions & 1 deletion llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ class ARMInstPrinter : public MCInstPrinter {
const MCSubtargetInfo &STI, raw_ostream &O);
void printExpandedImmOperand(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O);

void printMveSaturateOp(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O);
private:
unsigned DefaultAltIdx = ARM::NoRegAltName;
};
Expand Down
16 changes: 12 additions & 4 deletions llvm/test/MC/ARM/mve-scalar-shift.s
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,13 @@ sqrshr lr, r12
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve
sqrshr r11, r12

# CHECK: sqrshrl lr, r3, r8 @ encoding: [0x5f,0xea,0x2d,0x83]
# CHECK: sqrshrl lr, r3, #64, r8 @ encoding: [0x5f,0xea,0x2d,0x83]
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve
sqrshrl lr, r3, r8
sqrshrl lr, r3, #64, r8

# ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: saturate operand must be 48 or 64
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction
sqrshrl lr, r3, #32, r8

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

# CHECK: uqrshll lr, r1, r4 @ encoding: [0x5f,0xea,0x0d,0x41]
# CHECK: uqrshll lr, r1, #48, r4 @ encoding: [0x5f,0xea,0x8d,0x41]
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve
uqrshll lr, r1, r4
uqrshll lr, r1, #48, r4

# ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: saturate operand must be 48 or 64
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction
uqrshll lr, r1, #0, r4

# CHECK: uqshl r0, #1 @ encoding: [0x50,0xea,0x4f,0x0f]
# ERROR-NOMVE: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve
Expand Down
12 changes: 10 additions & 2 deletions llvm/test/MC/Disassembler/ARM/mve-scalar-shift.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@
# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding

[0x5f 0xea 0x2d 0x83]
# CHECK: sqrshrl lr, r3, r8 @ encoding: [0x5f,0xea,0x2d,0x83]
# CHECK: sqrshrl lr, r3, #64, r8 @ encoding: [0x5f,0xea,0x2d,0x83]
# CHECK-NOMVE: [[@LINE-2]]:2: warning: invalid instruction encoding

[0x5f 0xea 0xad 0x83]
# CHECK: sqrshrl lr, r3, #48, r8 @ encoding: [0x5f,0xea,0xad,0x83]
# CHECK-NOMVE: [[@LINE-2]]:2: warning: invalid instruction encoding

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

[0x5f 0xea 0x0d 0x41]
# CHECK: uqrshll lr, r1, r4 @ encoding: [0x5f,0xea,0x0d,0x41]
# CHECK: uqrshll lr, r1, #64, r4 @ encoding: [0x5f,0xea,0x0d,0x41]
# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding

[0x5f 0xea 0x8d 0x41]
# CHECK: uqrshll lr, r1, #48, r4 @ encoding: [0x5f,0xea,0x8d,0x41]
# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding

[0x50 0xea 0x4f 0x0f]
Expand Down

0 comments on commit 0b001f9

Please sign in to comment.