forked from OSchip/llvm-project
ARM SSAT instruction 5-bit immediate handling.
The immediate is in the range 1-32, but is encoded as 0-31 in a 5-bit bitfield. Update the representation such that we store the operand as 0-31, allowing us to remove the encoder method and the special case handling in the disassembler. Update the assembly parser and the instruction printer accordingly. llvm-svn: 135823
This commit is contained in:
parent
c8eab671cf
commit
801e0a3fde
|
@ -553,10 +553,14 @@ def width_imm : Operand<i32>, ImmLeaf<i32, [{
|
|||
let EncoderMethod = "getMsbOpValue";
|
||||
}
|
||||
|
||||
def ssat_imm : Operand<i32>, ImmLeaf<i32, [{
|
||||
return Imm > 0 && Imm <= 32;
|
||||
}]> {
|
||||
let EncoderMethod = "getSsatBitPosValue";
|
||||
def imm1_32_XFORM: SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant((int)N->getZExtValue() - 1, MVT::i32);
|
||||
}]>;
|
||||
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 ParserMatchClass = Imm1_32AsmOperand;
|
||||
}
|
||||
|
||||
// Define ARM specific addressing modes.
|
||||
|
@ -2723,9 +2727,8 @@ def USADA8 : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
|
|||
|
||||
// Signed/Unsigned saturate -- for disassembly only
|
||||
|
||||
def SSAT : AI<(outs GPR:$Rd), (ins ssat_imm:$sat_imm, GPR:$a, shift_imm:$sh),
|
||||
SatFrm, NoItinerary, "ssat", "\t$Rd, $sat_imm, $a$sh",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
def SSAT : AI<(outs GPR:$Rd), (ins imm1_32:$sat_imm, GPR:$a, shift_imm:$sh),
|
||||
SatFrm, NoItinerary, "ssat", "\t$Rd, $sat_imm, $a$sh", []> {
|
||||
bits<4> Rd;
|
||||
bits<5> sat_imm;
|
||||
bits<4> Rn;
|
||||
|
@ -2739,9 +2742,8 @@ def SSAT : AI<(outs GPR:$Rd), (ins ssat_imm:$sat_imm, GPR:$a, shift_imm:$sh),
|
|||
let Inst{3-0} = Rn;
|
||||
}
|
||||
|
||||
def SSAT16 : AI<(outs GPR:$Rd), (ins ssat_imm:$sat_imm, GPR:$Rn), SatFrm,
|
||||
NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
def SSAT16 : AI<(outs GPR:$Rd), (ins imm1_32:$sat_imm, GPR:$Rn), SatFrm,
|
||||
NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn", []> {
|
||||
bits<4> Rd;
|
||||
bits<4> sat_imm;
|
||||
bits<4> Rn;
|
||||
|
|
|
@ -1925,7 +1925,7 @@ class T2SatI<dag oops, dag iops, InstrItinClass itin,
|
|||
}
|
||||
|
||||
def t2SSAT: T2SatI<
|
||||
(outs rGPR:$Rd), (ins ssat_imm:$sat_imm, rGPR:$Rn, shift_imm:$sh),
|
||||
(outs rGPR:$Rd), (ins imm1_32:$sat_imm, rGPR:$Rn, shift_imm:$sh),
|
||||
NoItinerary, "ssat", "\t$Rd, $sat_imm, $Rn$sh",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{31-27} = 0b11110;
|
||||
|
@ -1935,7 +1935,7 @@ def t2SSAT: T2SatI<
|
|||
}
|
||||
|
||||
def t2SSAT16: T2SatI<
|
||||
(outs rGPR:$Rd), (ins ssat_imm:$sat_imm, rGPR:$Rn), NoItinerary,
|
||||
(outs rGPR:$Rd), (ins imm1_32:$sat_imm, rGPR:$Rn), NoItinerary,
|
||||
"ssat16", "\t$Rd, $sat_imm, $Rn",
|
||||
[/* For disassembly only; pattern left blank */]>,
|
||||
Requires<[IsThumb2, HasThumb2DSP]> {
|
||||
|
|
|
@ -1170,13 +1170,6 @@ getMsbOpValue(const MCInst &MI, unsigned Op,
|
|||
return msb;
|
||||
}
|
||||
|
||||
unsigned ARMMCCodeEmitter::
|
||||
getSsatBitPosValue(const MCInst &MI, unsigned Op,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
// For ssat instructions, the bit position should be encoded decremented by 1
|
||||
return MI.getOperand(Op).getImm()-1;
|
||||
}
|
||||
|
||||
unsigned ARMMCCodeEmitter::
|
||||
getRegisterListOpValue(const MCInst &MI, unsigned Op,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
|
|
|
@ -427,6 +427,14 @@ public:
|
|||
int64_t Value = CE->getValue();
|
||||
return Value >= 0 && Value < 32;
|
||||
}
|
||||
bool isImm1_32() 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 < 33;
|
||||
}
|
||||
bool isImm0_65535() const {
|
||||
if (Kind != Immediate)
|
||||
return false;
|
||||
|
@ -690,6 +698,14 @@ public:
|
|||
addExpr(Inst, getImm());
|
||||
}
|
||||
|
||||
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
|
||||
// the bits as encoded, so subtract off one here.
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
|
||||
}
|
||||
|
||||
void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
addExpr(Inst, getImm());
|
||||
|
|
|
@ -1726,8 +1726,6 @@ static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
|
|||
decodeRd(insn))));
|
||||
|
||||
unsigned Pos = slice(insn, 20, 16);
|
||||
if (Opcode == ARM::SSAT || Opcode == ARM::SSAT16)
|
||||
Pos += 1;
|
||||
MI.addOperand(MCOperand::CreateImm(Pos));
|
||||
|
||||
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
|
||||
|
|
|
@ -1609,8 +1609,6 @@ static bool DisassembleThumb2Sat(MCInst &MI, unsigned Opcode, uint32_t insn,
|
|||
decodeRs(insn))));
|
||||
|
||||
unsigned Pos = slice(insn, 4, 0);
|
||||
if (Opcode == ARM::t2SSAT || Opcode == ARM::t2SSAT16)
|
||||
Pos += 1;
|
||||
MI.addOperand(MCOperand::CreateImm(Pos));
|
||||
|
||||
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
|
||||
|
|
|
@ -837,3 +837,9 @@ void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
|
|||
uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
|
||||
O << "#0x" << utohexstr(Val);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printImm1_32Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
unsigned Imm = MI->getOperand(OpNum).getImm();
|
||||
O << "#" << Imm + 1;
|
||||
}
|
||||
|
|
|
@ -114,6 +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 printPCLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
};
|
||||
|
|
|
@ -587,6 +587,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
|||
IMM("neg_zero");
|
||||
IMM("imm0_31");
|
||||
IMM("imm0_31_m1");
|
||||
IMM("imm1_32");
|
||||
IMM("nModImm");
|
||||
IMM("imm0_7");
|
||||
IMM("imm0_15");
|
||||
|
@ -603,7 +604,6 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
|||
IMM("t_adrlabel");
|
||||
IMM("t2adrlabel");
|
||||
IMM("shift_imm");
|
||||
IMM("ssat_imm");
|
||||
IMM("neon_vcvt_imm32");
|
||||
IMM("shr_imm8");
|
||||
IMM("shr_imm16");
|
||||
|
|
Loading…
Reference in New Issue