mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-26 12:20:42 +00:00
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:
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user