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:
Jim Grosbach 2011-07-22 23:16:18 +00:00
parent c8eab671cf
commit 801e0a3fde
9 changed files with 38 additions and 24 deletions

View File

@ -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;

View File

@ -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]> {

View File

@ -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 {

View File

@ -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());

View File

@ -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,

View File

@ -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,

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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");