mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-11 00:39:36 +00:00
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:
parent
fa44725233
commit
293a2ee306
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user