Reapply r128585 without generating a lib depedency cycle. An updated log:

- Implement asm parsing support for LDRT, LDRBT, STRT, STRBT and
  {STR,LDC}{2}_{PRE,POST} fixing the encoding wherever is possible.
- Move all instructions which use am2offset without a pattern to use
  addrmode2.
- Add a new encoding bit to describe the index mode used and teach
  printAddrMode2Operand to check by the addressing mode which index
  mode to print.
- Testcases

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128632 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bruno Cardoso Lopes
2011-03-31 14:52:28 +00:00
parent 56584fcbfd
commit bcd3a9cd84
10 changed files with 359 additions and 86 deletions
+134 -12
View File
@@ -48,7 +48,8 @@ class ARMAsmParser : public TargetAsmParser {
bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
bool TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &,
ARMII::AddrMode AddrMode);
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);
const MCExpr *ApplyPrefixToExpr(const MCExpr *E,
@@ -95,6 +96,14 @@ class ARMAsmParser : public TargetAsmParser {
SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy tryParseMSRMaskOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy tryParseMemMode2Operand(
SmallVectorImpl<MCParsedAsmOperand*>&);
// Asm Match Converter Methods
bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
public:
ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
@@ -172,6 +181,7 @@ class ARMOperand : public MCParsedAsmOperand {
/// Combined record for all forms of ARM address expressions.
struct {
ARMII::AddrMode AddrMode;
unsigned BaseRegNum;
union {
unsigned RegNum; ///< Offset register num, when OffsetIsReg.
@@ -293,7 +303,9 @@ public:
/// @name Memory Operand Accessors
/// @{
ARMII::AddrMode getMemAddrMode() const {
return Mem.AddrMode;
}
unsigned getMemBaseRegNum() const {
return Mem.BaseRegNum;
}
@@ -338,6 +350,27 @@ public:
bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
bool isMemory() const { return Kind == Memory; }
bool isShifter() const { return Kind == Shifter; }
bool isMemMode2() const {
if (getMemAddrMode() != ARMII::AddrMode2)
return false;
if (getMemOffsetIsReg())
return true;
if (getMemNegative() &&
!(getMemPostindexed() || getMemPreindexed()))
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
if (!CE) return false;
int64_t Value = CE->getValue();
// The offset must be in the range 0-4095 (imm12).
if (Value > 4095 || Value < -4095)
return false;
return true;
}
bool isMemMode5() const {
if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||
getMemNegative())
@@ -465,6 +498,47 @@ public:
"No offset operand support in mode 7");
}
void addMemMode2Operands(MCInst &Inst, unsigned N) const {
assert(isMemMode2() && "Invalid mode or number of operands!");
Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1);
if (getMemOffsetIsReg()) {
Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));
ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;
ARM_AM::ShiftOpc ShOpc = ARM_AM::no_shift;
int64_t ShiftAmount = 0;
if (getMemOffsetRegShifted()) {
ShOpc = getMemShiftType();
const MCConstantExpr *CE =
dyn_cast<MCConstantExpr>(getMemShiftAmount());
ShiftAmount = CE->getValue();
}
Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(AMOpc, ShiftAmount,
ShOpc, IdxMode)));
return;
}
// Create a operand placeholder to always yield the same number of operands.
Inst.addOperand(MCOperand::CreateReg(0));
// FIXME: #-0 is encoded differently than #0. Does the parser preserve
// the difference?
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
assert(CE && "Non-constant mode 2 offset operand!");
int64_t Offset = CE->getValue();
if (Offset >= 0)
Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::add,
Offset, ARM_AM::no_shift, IdxMode)));
else
Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::sub,
-Offset, ARM_AM::no_shift, IdxMode)));
}
void addMemMode5Operands(MCInst &Inst, unsigned N) const {
assert(N == 2 && isMemMode5() && "Invalid number of operands!");
@@ -599,9 +673,9 @@ public:
return Op;
}
static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg,
const MCExpr *Offset, int OffsetRegNum,
bool OffsetRegShifted,
static ARMOperand *CreateMem(ARMII::AddrMode AddrMode, unsigned BaseRegNum,
bool OffsetIsReg, const MCExpr *Offset,
int OffsetRegNum, bool OffsetRegShifted,
enum ARM_AM::ShiftOpc ShiftType,
const MCExpr *ShiftAmount, bool Preindexed,
bool Postindexed, bool Negative, bool Writeback,
@@ -618,6 +692,7 @@ public:
"Cannot have expression offset and register offset!");
ARMOperand *Op = new ARMOperand(Memory);
Op->Mem.AddrMode = AddrMode;
Op->Mem.BaseRegNum = BaseRegNum;
Op->Mem.OffsetIsReg = OffsetIsReg;
if (OffsetIsReg)
@@ -689,7 +764,8 @@ void ARMOperand::dump(raw_ostream &OS) const {
break;
case Memory:
OS << "<memory "
<< "base:" << getMemBaseRegNum();
<< "am:" << ARMII::AddrModeToString(getMemAddrMode())
<< " base:" << getMemBaseRegNum();
if (getMemOffsetIsReg()) {
OS << " offset:<register " << getMemOffsetRegNum();
if (getMemOffsetRegShifted()) {
@@ -1132,13 +1208,57 @@ tryParseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
/// tryParseMemMode2Operand - Try to parse memory addressing mode 2 operand.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
tryParseMemMode2Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
assert(Tok.is(AsmToken::LBrac) && "Token is not a \"[\"");
if (ParseMemory(Operands, ARMII::AddrMode2))
return MatchOperand_NoMatch;
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.
bool ARMAsmParser::
CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
// Create a writeback register dummy placeholder.
Inst.addOperand(MCOperand::CreateImm(0));
((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
return true;
}
/// CvtStWriteBackRegAddrMode2 - 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.
bool ARMAsmParser::
CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// Create a writeback register dummy placeholder.
Inst.addOperand(MCOperand::CreateImm(0));
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
return true;
}
/// Parse an ARM memory expression, return false if successful else return true
/// or an error. The first token must be a '[' when called.
///
/// TODO Only preindexing and postindexing addressing are started, unindexed
/// with option, etc are still to do.
bool ARMAsmParser::
ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
ARMII::AddrMode AddrMode = ARMII::AddrModeNone) {
SMLoc S, E;
assert(Parser.getTok().is(AsmToken::LBrac) &&
"Token is not a Left Bracket");
@@ -1196,6 +1316,9 @@ ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
ExclaimTok.getLoc());
Writeback = true;
Parser.Lex(); // Eat exclaim token
} else { // In addressing mode 2, pre-indexed mode always end with "!"
if (AddrMode == ARMII::AddrMode2)
Preindexed = false;
}
} else {
// The "[Rn" we have so far was not followed by a comma.
@@ -1231,11 +1354,10 @@ ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Offset = MCConstantExpr::Create(0, getContext());
}
Operands.push_back(ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset,
OffsetRegNum, OffsetRegShifted,
ShiftType, ShiftAmount, Preindexed,
Postindexed, Negative, Writeback,
S, E));
Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg,
Offset, OffsetRegNum, OffsetRegShifted,
ShiftType, ShiftAmount, Preindexed,
Postindexed, Negative, Writeback, S, E));
if (WBOp)
Operands.push_back(WBOp);