aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td14
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td2
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp16
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp4
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.h2
-rw-r--r--test/MC/ARM/basic-arm-instructions.s11
-rw-r--r--test/MC/ARM/diagnostics.s11
-rw-r--r--utils/TableGen/EDEmitter.cpp1
8 files changed, 55 insertions, 6 deletions
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index 6e9743ffad..83a2514804 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -543,10 +543,20 @@ def imm1_32_XFORM: SDNodeXForm<imm, [{
def Imm1_32AsmOperand: AsmOperandClass { let Name = "Imm1_32"; }
def imm1_32 : Operand<i32>, PatLeaf<(imm), [{ return Imm > 0 && Imm <= 32; }],
imm1_32_XFORM> {
- let PrintMethod = "printImm1_32Operand";
+ let PrintMethod = "printImmPlusOneOperand";
let ParserMatchClass = Imm1_32AsmOperand;
}
+def imm1_16_XFORM: SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant((int)N->getZExtValue() - 1, MVT::i32);
+}]>;
+def Imm1_16AsmOperand: AsmOperandClass { let Name = "Imm1_16"; }
+def imm1_16 : Operand<i32>, PatLeaf<(imm), [{ return Imm > 0 && Imm <= 16; }],
+ imm1_16_XFORM> {
+ let PrintMethod = "printImmPlusOneOperand";
+ let ParserMatchClass = Imm1_16AsmOperand;
+}
+
// Define ARM specific addressing modes.
// addrmode_imm12 := reg +/- imm12
//
@@ -2709,7 +2719,7 @@ def SSAT : AI<(outs GPR:$Rd), (ins imm1_32:$sat_imm, GPR:$Rn, shift_imm:$sh),
let Inst{3-0} = Rn;
}
-def SSAT16 : AI<(outs GPR:$Rd), (ins imm1_32:$sat_imm, GPR:$Rn), SatFrm,
+def SSAT16 : AI<(outs GPR:$Rd), (ins imm1_16:$sat_imm, GPR:$Rn), SatFrm,
NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn", []> {
bits<4> Rd;
bits<4> sat_imm;
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index 808ae51a60..1a9ab1c876 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -1935,7 +1935,7 @@ def t2SSAT: T2SatI<
}
def t2SSAT16: T2SatI<
- (outs rGPR:$Rd), (ins imm1_32:$sat_imm, rGPR:$Rn), NoItinerary,
+ (outs rGPR:$Rd), (ins imm1_16:$sat_imm, rGPR:$Rn), NoItinerary,
"ssat16", "\t$Rd, $sat_imm, $Rn",
[/* For disassembly only; pattern left blank */]>,
Requires<[IsThumb2, HasThumb2DSP]> {
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 02ed5477d4..f6f8adc666 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -433,6 +433,14 @@ public:
int64_t Value = CE->getValue();
return Value >= 0 && Value < 32;
}
+ bool isImm1_16() const {
+ if (Kind != Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value > 0 && Value < 17;
+ }
bool isImm1_32() const {
if (Kind != Immediate)
return false;
@@ -704,6 +712,14 @@ public:
addExpr(Inst, getImm());
}
+ void addImm1_16Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The constant encodes as the immediate-1, and we store in the instruction
+ // the bits as encoded, so subtract off one here.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
+ }
+
void addImm1_32Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The constant encodes as the immediate-1, and we store in the instruction
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
index 296080a817..3e58631c6c 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
@@ -830,8 +830,8 @@ void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
O << "#0x" << utohexstr(Val);
}
-void ARMInstPrinter::printImm1_32Operand(const MCInst *MI, unsigned OpNum,
- raw_ostream &O) {
+void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
unsigned Imm = MI->getOperand(OpNum).getImm();
O << "#" << Imm + 1;
}
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
index 208a3a71f1..c254ace6bc 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
@@ -114,7 +114,7 @@ public:
void printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
- void printImm1_32Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printPCLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O);
};
diff --git a/test/MC/ARM/basic-arm-instructions.s b/test/MC/ARM/basic-arm-instructions.s
index 0439e70c44..b00b70b7b4 100644
--- a/test/MC/ARM/basic-arm-instructions.s
+++ b/test/MC/ARM/basic-arm-instructions.s
@@ -1631,6 +1631,17 @@ _func:
@ CHECK: ssat r8, #1, r10, asr #32 @ encoding: [0x5a,0x80,0xa0,0xe6]
@ CHECK: ssat r8, #1, r10, asr #1 @ encoding: [0xda,0x80,0xa0,0xe6]
+
+@------------------------------------------------------------------------------
+@ SSAT16
+@------------------------------------------------------------------------------
+ ssat16 r2, #1, r7
+ ssat16 r3, #16, r5
+
+@ CHECK: ssat16 r2, #1, r7 @ encoding: [0x37,0x2f,0xa0,0xe6]
+@ CHECK: ssat16 r3, #16, r5 @ encoding: [0x35,0x3f,0xaf,0xe6]
+
+
@------------------------------------------------------------------------------
@ STM*
@------------------------------------------------------------------------------
diff --git a/test/MC/ARM/diagnostics.s b/test/MC/ARM/diagnostics.s
index a8b2d9d4fa..aff242cc0b 100644
--- a/test/MC/ARM/diagnostics.s
+++ b/test/MC/ARM/diagnostics.s
@@ -200,3 +200,14 @@
@ CHECK: error: shift amount must be an immediate
@ CHECK: ssat r8, #1, r10, lsl #fred
@ CHECK: ^
+
+ @ Out of range immediates for SSAT16
+ ssat16 r2, #0, r7
+ ssat16 r3, #17, r5
+
+@ CHECK: error: invalid operand for instruction
+@ CHECK: ssat16 r2, #0, r7
+@ CHECK: ^
+@ CHECK: error: invalid operand for instruction
+@ CHECK: ssat16 r3, #17, r5
+@ CHECK: ^
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index 3001192e7f..c9542cb8e7 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -587,6 +587,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
IMM("neg_zero");
IMM("imm0_31");
IMM("imm0_31_m1");
+ IMM("imm1_16");
IMM("imm1_32");
IMM("nModImm");
IMM("imm0_7");