ARM assembly parsing and encoding for BFC and BFI.

Add parsing support that handles converting the lsb+width source into the
odd way we represent the instruction (an inverted bitfield mask).


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136399 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2011-07-28 21:34:26 +00:00
parent fa44725233
commit 293a2ee306
3 changed files with 130 additions and 2 deletions

View File

@ -536,12 +536,17 @@ def imm24b : Operand<i32>, ImmLeaf<i32, [{
/// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield
/// e.g., 0xf000ffff
def BitfieldAsmOperand : AsmOperandClass {
let Name = "Bitfield";
let ParserMethod = "parseBitfield";
}
def bf_inv_mask_imm : Operand<i32>,
PatLeaf<(imm), [{
return ARM::isBitFieldInvertedMask(N->getZExtValue());
}] > {
let EncoderMethod = "getBitfieldInvertedMaskOpValue";
let PrintMethod = "printBitfieldInvMaskImmOperand";
let ParserMatchClass = BitfieldAsmOperand;
}
/// lsb_pos_imm - position of the lsb bit, used by BFI4p and t2BFI4p

View File

@ -125,6 +125,7 @@ class ARMAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
// Asm Match Converter Methods
bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
@ -184,6 +185,7 @@ class ARMOperand : public MCParsedAsmOperand {
ShiftedImmediate,
ShifterImmediate,
RotateImmediate,
BitfieldDescriptor,
Token
} Kind;
@ -260,6 +262,10 @@ class ARMOperand : public MCParsedAsmOperand {
struct {
unsigned Imm;
} RotImm;
struct {
unsigned LSB;
unsigned Width;
} Bitfield;
};
ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
@ -315,6 +321,9 @@ public:
case RotateImmediate:
RotImm = o.RotImm;
break;
case BitfieldDescriptor:
Bitfield = o.Bitfield;
break;
}
}
@ -535,6 +544,7 @@ public:
bool isRegShiftedReg() const { return Kind == ShiftedRegister; }
bool isRegShiftedImm() const { return Kind == ShiftedImmediate; }
bool isRotImm() const { return Kind == RotateImmediate; }
bool isBitfield() const { return Kind == BitfieldDescriptor; }
bool isMemMode2() const {
if (getMemAddrMode() != ARMII::AddrMode2)
return false;
@ -711,6 +721,17 @@ public:
Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
}
void addBitfieldOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// Munge the lsb/width into a bitfield mask.
unsigned lsb = Bitfield.LSB;
unsigned width = Bitfield.Width;
// Make a 32-bit mask w/ the referenced bits clear and all other bits set.
uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
(32 - (lsb + width)));
Inst.addOperand(MCOperand::CreateImm(Mask));
}
void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
@ -1026,6 +1047,16 @@ public:
return Op;
}
static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
SMLoc S, SMLoc E) {
ARMOperand *Op = new ARMOperand(BitfieldDescriptor);
Op->Bitfield.LSB = LSB;
Op->Bitfield.Width = Width;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static ARMOperand *
CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
SMLoc StartLoc, SMLoc EndLoc) {
@ -1204,6 +1235,10 @@ void ARMOperand::print(raw_ostream &OS) const {
case RotateImmediate:
OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
break;
case BitfieldDescriptor:
OS << "<bitfield " << "lsb: " << Bitfield.LSB
<< ", width: " << Bitfield.Width << ">";
break;
case RegisterList:
case DPRRegisterList:
case SPRRegisterList: {
@ -1883,6 +1918,72 @@ parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
// The bitfield descriptor is really two operands, the LSB and the width.
if (Parser.getTok().isNot(AsmToken::Hash)) {
Error(Parser.getTok().getLoc(), "'#' expected");
return MatchOperand_ParseFail;
}
Parser.Lex(); // Eat hash token.
const MCExpr *LSBExpr;
SMLoc E = Parser.getTok().getLoc();
if (getParser().ParseExpression(LSBExpr)) {
Error(E, "malformed immediate expression");
return MatchOperand_ParseFail;
}
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
if (!CE) {
Error(E, "'lsb' operand must be an immediate");
return MatchOperand_ParseFail;
}
int64_t LSB = CE->getValue();
// The LSB must be in the range [0,31]
if (LSB < 0 || LSB > 31) {
Error(E, "'lsb' operand must be in the range [0,31]");
return MatchOperand_ParseFail;
}
E = Parser.getTok().getLoc();
// Expect another immediate operand.
if (Parser.getTok().isNot(AsmToken::Comma)) {
Error(Parser.getTok().getLoc(), "too few operands");
return MatchOperand_ParseFail;
}
Parser.Lex(); // Eat hash token.
if (Parser.getTok().isNot(AsmToken::Hash)) {
Error(Parser.getTok().getLoc(), "'#' expected");
return MatchOperand_ParseFail;
}
Parser.Lex(); // Eat hash token.
const MCExpr *WidthExpr;
if (getParser().ParseExpression(WidthExpr)) {
Error(E, "malformed immediate expression");
return MatchOperand_ParseFail;
}
CE = dyn_cast<MCConstantExpr>(WidthExpr);
if (!CE) {
Error(E, "'width' operand must be an immediate");
return MatchOperand_ParseFail;
}
int64_t Width = CE->getValue();
// The LSB must be in the range [1,32-lsb]
if (Width < 1 || Width > 32 - LSB) {
Error(E, "'width' operand must be in the range [1,32-lsb]");
return MatchOperand_ParseFail;
}
E = Parser.getTok().getLoc();
Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
return MatchOperand_Success;
}
/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.

View File

@ -258,12 +258,34 @@ Lforward:
@------------------------------------------------------------------------------
@ FIXME: B
@------------------------------------------------------------------------------
b _bar
beq _baz
@ CHECK: b _bar @ encoding: [A,A,A,0xea]
@ fixup A - offset: 0, value: _bar, kind: fixup_arm_uncondbranch
@ CHECK: beq _baz @ encoding: [A,A,A,0x0a]
@ fixup A - offset: 0, value: _baz, kind: fixup_arm_condbranch
@------------------------------------------------------------------------------
@ FIXME: BFC
@ BFC
@------------------------------------------------------------------------------
bfc r5, #3, #17
bfccc r5, #3, #17
@ CHECK: bfc r5, #3, #17 @ encoding: [0x9f,0x51,0xd3,0xe7]
@ CHECK: bfclo r5, #3, #17 @ encoding: [0x9f,0x51,0xd3,0x37]
@------------------------------------------------------------------------------
@ FIXME: BFI
@ BFI
@------------------------------------------------------------------------------
bfi r5, r2, #3, #17
bfine r5, r2, #3, #17
@ CHECK: bfi r5, r2, #3, #17 @ encoding: [0x92,0x51,0xd3,0xe7]
@ CHECK: bfine r5, r2, #3, #17 @ encoding: [0x92,0x51,0xd3,0x17]
@------------------------------------------------------------------------------
@ BIC