mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-03 19:02:35 +00:00
- Implement asm parsing support for LDRSBT, LDRHT, LDRSHT and STRHT
also fix the encoding of the later. - Add a new encoding bit to describe the index mode used in AM3. - Teach printAddrMode3Operand to check by the addressing mode which index mode to print. - Testcases. llvm-svn: 128832
This commit is contained in:
parent
94fc1341f5
commit
74363376e4
@ -409,7 +409,7 @@ namespace ARM_AM {
|
||||
// The first operand is always a Reg. The second operand is a reg if in
|
||||
// reg/reg form, otherwise it's reg#0. The third field encodes the operation
|
||||
// in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
|
||||
// forth operand 16-17 encodes the index mode.
|
||||
// fourth operand 16-17 encodes the index mode.
|
||||
//
|
||||
// If this addressing mode is a frame index (before prolog/epilog insertion
|
||||
// and code rewriting), this operand will have the form: FI#, reg0, <offs>
|
||||
@ -446,12 +446,14 @@ namespace ARM_AM {
|
||||
//
|
||||
// The first operand is always a Reg. The second operand is a reg if in
|
||||
// reg/reg form, otherwise it's reg#0. The third field encodes the operation
|
||||
// in bit 8, the immediate in bits 0-7.
|
||||
// in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the
|
||||
// index mode.
|
||||
|
||||
/// getAM3Opc - This function encodes the addrmode3 opc field.
|
||||
static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset) {
|
||||
static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset,
|
||||
unsigned IdxMode = 0) {
|
||||
bool isSub = Opc == sub;
|
||||
return ((int)isSub << 8) | Offset;
|
||||
return ((int)isSub << 8) | Offset | (IdxMode << 9);
|
||||
}
|
||||
static inline unsigned char getAM3Offset(unsigned AM3Opc) {
|
||||
return AM3Opc & 0xFF;
|
||||
@ -459,6 +461,9 @@ namespace ARM_AM {
|
||||
static inline AddrOpc getAM3Op(unsigned AM3Opc) {
|
||||
return ((AM3Opc >> 8) & 1) ? sub : add;
|
||||
}
|
||||
static inline unsigned getAM3IdxMode(unsigned AM3Opc) {
|
||||
return (AM3Opc >> 9);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #4
|
||||
|
@ -577,6 +577,34 @@ class AI3ldstidx<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
|
||||
let Inst{15-12} = Rt; // Rt
|
||||
let Inst{7-4} = op;
|
||||
}
|
||||
|
||||
// FIXME: Merge with the above class when addrmode2 gets used for LDR, LDRB
|
||||
// but for now use this class for LDRSBT, LDRHT, LDSHT.
|
||||
class AI3ldstidxT<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
|
||||
IndexMode im, Format f, InstrItinClass itin, string opc,
|
||||
string asm, string cstr, list<dag> pattern>
|
||||
: I<oops, iops, AddrMode3, Size4Bytes, im, f, itin,
|
||||
opc, asm, cstr, pattern> {
|
||||
// {13} 1 == imm8, 0 == Rm
|
||||
// {12-9} Rn
|
||||
// {8} isAdd
|
||||
// {7-4} imm7_4/zero
|
||||
// {3-0} imm3_0/Rm
|
||||
bits<14> addr;
|
||||
bits<4> Rt;
|
||||
let Inst{27-25} = 0b000;
|
||||
let Inst{24} = isPre; // P bit
|
||||
let Inst{23} = addr{8}; // U bit
|
||||
let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm
|
||||
let Inst{20} = op20; // L bit
|
||||
let Inst{19-16} = addr{12-9}; // Rn
|
||||
let Inst{15-12} = Rt; // Rt
|
||||
let Inst{11-8} = addr{7-4}; // imm7_4/zero
|
||||
let Inst{7-4} = op;
|
||||
let Inst{3-0} = addr{3-0}; // imm3_0/Rm
|
||||
let AsmMatchConverter = "CvtLdWriteBackRegAddrMode3";
|
||||
}
|
||||
|
||||
class AI3stridx<bits<4> op, bit isByte, bit isPre, dag oops, dag iops,
|
||||
IndexMode im, Format f, InstrItinClass itin, string opc,
|
||||
string asm, string cstr, list<dag> pattern>
|
||||
@ -649,12 +677,25 @@ class AI3sthpo<dag oops, dag iops, Format f, InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: I<oops, iops, AddrMode3, Size4Bytes, IndexModePost, f, itin,
|
||||
opc, asm, cstr,pattern> {
|
||||
// {13} 1 == imm8, 0 == Rm
|
||||
// {12-9} Rn
|
||||
// {8} isAdd
|
||||
// {7-4} imm7_4/zero
|
||||
// {3-0} imm3_0/Rm
|
||||
bits<14> addr;
|
||||
bits<4> Rt;
|
||||
let Inst{3-0} = addr{3-0}; // imm3_0/Rm
|
||||
let Inst{4} = 1;
|
||||
let Inst{5} = 1; // H bit
|
||||
let Inst{6} = 0; // S bit
|
||||
let Inst{7} = 1;
|
||||
let Inst{11-8} = addr{7-4}; // imm7_4/zero
|
||||
let Inst{15-12} = Rt; // Rt
|
||||
let Inst{19-16} = addr{12-9}; // Rn
|
||||
let Inst{20} = 0; // L bit
|
||||
let Inst{21} = 0; // W bit
|
||||
let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm
|
||||
let Inst{23} = addr{8}; // U bit
|
||||
let Inst{24} = 0; // P bit
|
||||
let Inst{27-25} = 0b000;
|
||||
}
|
||||
|
@ -475,6 +475,17 @@ def width_imm : Operand<i32>, PatLeaf<(imm), [{
|
||||
|
||||
// Define ARM specific addressing modes.
|
||||
|
||||
def MemMode2AsmOperand : AsmOperandClass {
|
||||
let Name = "MemMode2";
|
||||
let SuperClasses = [];
|
||||
let ParserMethod = "tryParseMemMode2Operand";
|
||||
}
|
||||
|
||||
def MemMode3AsmOperand : AsmOperandClass {
|
||||
let Name = "MemMode3";
|
||||
let SuperClasses = [];
|
||||
let ParserMethod = "tryParseMemMode3Operand";
|
||||
}
|
||||
|
||||
// addrmode_imm12 := reg +/- imm12
|
||||
//
|
||||
@ -498,12 +509,6 @@ def ldst_so_reg : Operand<i32>,
|
||||
let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
|
||||
}
|
||||
|
||||
def MemMode2AsmOperand : AsmOperandClass {
|
||||
let Name = "MemMode2";
|
||||
let SuperClasses = [];
|
||||
let ParserMethod = "tryParseMemMode2Operand";
|
||||
}
|
||||
|
||||
// addrmode2 := reg +/- imm12
|
||||
// := reg +/- reg shop imm
|
||||
//
|
||||
@ -530,6 +535,7 @@ def addrmode3 : Operand<i32>,
|
||||
ComplexPattern<i32, 3, "SelectAddrMode3", []> {
|
||||
let EncoderMethod = "getAddrMode3OpValue";
|
||||
let PrintMethod = "printAddrMode3Operand";
|
||||
let ParserMatchClass = MemMode3AsmOperand;
|
||||
let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
|
||||
}
|
||||
|
||||
@ -1763,22 +1769,19 @@ def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
|
||||
let Inst{11-0} = addr{11-0};
|
||||
let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
|
||||
}
|
||||
def LDRSBT : AI3ldstidx<0b1101, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base, am3offset:$offset), IndexModePost,
|
||||
LdMiscFrm, IIC_iLoad_bh_ru,
|
||||
"ldrsbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
|
||||
def LDRSBT : AI3ldstidxT<0b1101, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
|
||||
(ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru,
|
||||
"ldrsbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
|
||||
let Inst{21} = 1; // overwrite
|
||||
}
|
||||
def LDRHT : AI3ldstidx<0b1011, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base, am3offset:$offset), IndexModePost,
|
||||
LdMiscFrm, IIC_iLoad_bh_ru,
|
||||
"ldrht", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
|
||||
def LDRHT : AI3ldstidxT<0b1011, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
|
||||
(ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru,
|
||||
"ldrht", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
|
||||
let Inst{21} = 1; // overwrite
|
||||
}
|
||||
def LDRSHT : AI3ldstidx<0b1111, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base, am3offset:$offset), IndexModePost,
|
||||
LdMiscFrm, IIC_iLoad_bh_ru,
|
||||
"ldrsht", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
|
||||
def LDRSHT : AI3ldstidxT<0b1111, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
|
||||
(ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru,
|
||||
"ldrsht", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
|
||||
let Inst{21} = 1; // overwrite
|
||||
}
|
||||
}
|
||||
@ -1870,12 +1873,12 @@ def STRBT : AI2stridxT<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),
|
||||
let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";
|
||||
}
|
||||
|
||||
def STRHT: AI3sthpo<(outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base,am3offset:$offset),
|
||||
def STRHT: AI3sthpo<(outs GPR:$base_wb), (ins GPR:$Rt, addrmode3:$addr),
|
||||
StMiscFrm, IIC_iStore_bh_ru,
|
||||
"strht", "\t$src, [$base], $offset", "$base = $base_wb",
|
||||
"strht", "\t$Rt, $addr", "$addr.base = $base_wb",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{21} = 1; // overwrite
|
||||
let AsmMatchConverter = "CvtStWriteBackRegAddrMode3";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -98,12 +98,18 @@ class ARMAsmParser : public TargetAsmParser {
|
||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||
OperandMatchResultTy tryParseMemMode2Operand(
|
||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||
OperandMatchResultTy tryParseMemMode3Operand(
|
||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||
|
||||
// Asm Match Converter Methods
|
||||
bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||
bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||
bool CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||
bool CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||
|
||||
public:
|
||||
ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
|
||||
@ -371,6 +377,30 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
bool isMemMode3() const {
|
||||
if (getMemAddrMode() != ARMII::AddrMode3)
|
||||
return false;
|
||||
|
||||
if (getMemOffsetIsReg()) {
|
||||
if (getMemOffsetRegShifted())
|
||||
return false; // No shift with offset reg allowed
|
||||
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-255 (imm8).
|
||||
if (Value > 255 || Value < -255)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool isMemMode5() const {
|
||||
if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||
|
||||
getMemNegative())
|
||||
@ -539,6 +569,37 @@ public:
|
||||
-Offset, ARM_AM::no_shift, IdxMode)));
|
||||
}
|
||||
|
||||
void addMemMode3Operands(MCInst &Inst, unsigned N) const {
|
||||
assert(isMemMode3() && "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;
|
||||
Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(AMOpc, 0,
|
||||
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 3 offset operand!");
|
||||
int64_t Offset = CE->getValue();
|
||||
|
||||
if (Offset >= 0)
|
||||
Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::add,
|
||||
Offset, IdxMode)));
|
||||
else
|
||||
Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::sub,
|
||||
-Offset, IdxMode)));
|
||||
}
|
||||
|
||||
void addMemMode5Operands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && isMemMode5() && "Invalid number of operands!");
|
||||
|
||||
@ -1219,6 +1280,17 @@ tryParseMemMode2Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
||||
/// tryParseMemMode3Operand - Try to parse memory addressing mode 3 operand.
|
||||
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
|
||||
tryParseMemMode3Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\"");
|
||||
|
||||
if (ParseMemory(Operands, ARMII::AddrMode3))
|
||||
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.
|
||||
@ -1249,6 +1321,36 @@ CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
|
||||
return true;
|
||||
}
|
||||
|
||||
/// CvtLdWriteBackRegAddrMode3 - 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::
|
||||
CvtLdWriteBackRegAddrMode3(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])->addMemMode3Operands(Inst, 3);
|
||||
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// CvtStWriteBackRegAddrMode3 - 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::
|
||||
CvtStWriteBackRegAddrMode3(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])->addMemMode3Operands(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.
|
||||
///
|
||||
@ -1310,6 +1412,10 @@ ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
|
||||
const AsmToken &ExclaimTok = Parser.getTok();
|
||||
if (ExclaimTok.is(AsmToken::Exclaim)) {
|
||||
// None of addrmode3 instruction uses "!"
|
||||
if (AddrMode == ARMII::AddrMode3)
|
||||
return true;
|
||||
|
||||
WBOp = ARMOperand::CreateToken(ExclaimTok.getString(),
|
||||
ExclaimTok.getLoc());
|
||||
Writeback = true;
|
||||
@ -1350,6 +1456,11 @@ ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
if (!OffsetIsReg) {
|
||||
if (!Offset)
|
||||
Offset = MCConstantExpr::Create(0, getContext());
|
||||
} else {
|
||||
if (AddrMode == ARMII::AddrMode3 && OffsetRegShifted) {
|
||||
Error(E, "shift amount not supported");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg,
|
||||
|
@ -1237,19 +1237,22 @@ static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
|
||||
"Expect 1 reg operand followed by 1 imm operand");
|
||||
|
||||
ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
|
||||
unsigned IndexMode =
|
||||
(TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
|
||||
if (getAM3IBit(insn) == 1) {
|
||||
MI.addOperand(MCOperand::CreateReg(0));
|
||||
|
||||
// Disassemble the 8-bit immediate offset.
|
||||
unsigned Imm4H = (insn >> ARMII::ImmHiShift) & 0xF;
|
||||
unsigned Imm4L = insn & 0xF;
|
||||
unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L);
|
||||
unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L,
|
||||
IndexMode);
|
||||
MI.addOperand(MCOperand::CreateImm(Offset));
|
||||
} else {
|
||||
// Disassemble the offset reg (Rm).
|
||||
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
|
||||
decodeRm(insn))));
|
||||
unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0);
|
||||
unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0, IndexMode);
|
||||
MI.addOperand(MCOperand::CreateImm(Offset));
|
||||
}
|
||||
OpIdx += 2;
|
||||
|
@ -181,6 +181,10 @@ void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
|
||||
}
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #2
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
@ -276,11 +280,35 @@ void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
|
||||
<< " #" << ShImm;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
const MCOperand &MO3 = MI->getOperand(OpNum+2);
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #3
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
void ARMInstPrinter::printAM3PostIndexOp(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
const MCOperand &MO3 = MI->getOperand(Op+2);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg()) << "], ";
|
||||
|
||||
if (MO2.getReg()) {
|
||||
O << (char)ARM_AM::getAM3Op(MO3.getImm())
|
||||
<< getRegisterName(MO2.getReg());
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
|
||||
O << '#'
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
|
||||
<< ImmOffs;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
const MCOperand &MO3 = MI->getOperand(Op+2);
|
||||
|
||||
O << '[' << getRegisterName(MO1.getReg());
|
||||
|
||||
@ -297,6 +325,18 @@ void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
|
||||
O << ']';
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO3 = MI->getOperand(Op+2);
|
||||
unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm());
|
||||
|
||||
if (IdxMode == ARMII::IndexModePost) {
|
||||
printAM3PostIndexOp(MI, Op, O);
|
||||
return;
|
||||
}
|
||||
printAM3PreOrOffsetIndexOp(MI, Op, O);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
|
||||
unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
|
@ -49,9 +49,14 @@ public:
|
||||
raw_ostream &O);
|
||||
void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
|
||||
void printAddrMode3Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printAM3PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printAddrMode3OffsetOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
|
||||
void printLdStmModeOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printAddrMode5Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printAddrMode6Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
|
18
test/MC/ARM/arm_addrmode3.s
Normal file
18
test/MC/ARM/arm_addrmode3.s
Normal file
@ -0,0 +1,18 @@
|
||||
@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding %s | FileCheck %s
|
||||
|
||||
@ CHECK: ldrsbt r1, [r0], +r2 @ encoding: [0xd2,0x10,0xb0,0xe0]
|
||||
@ CHECK: ldrsbt r1, [r0], #4 @ encoding: [0xd4,0x10,0xf0,0xe0]
|
||||
@ CHECK: ldrsht r1, [r0], +r2 @ encoding: [0xf2,0x10,0xb0,0xe0]
|
||||
@ CHECK: ldrsht r1, [r0], #4 @ encoding: [0xf4,0x10,0xf0,0xe0]
|
||||
@ CHECK: ldrht r1, [r0], +r2 @ encoding: [0xb2,0x10,0xb0,0xe0]
|
||||
@ CHECK: ldrht r1, [r0], #4 @ encoding: [0xb4,0x10,0xf0,0xe0]
|
||||
@ CHECK: strht r1, [r0], +r2 @ encoding: [0xb2,0x10,0xa0,0xe0]
|
||||
@ CHECK: strht r1, [r0], #4 @ encoding: [0xb4,0x10,0xe0,0xe0]
|
||||
ldrsbt r1, [r0], r2
|
||||
ldrsbt r1, [r0], #4
|
||||
ldrsht r1, [r0], r2
|
||||
ldrsht r1, [r0], #4
|
||||
ldrht r1, [r0], r2
|
||||
ldrht r1, [r0], #4
|
||||
strht r1, [r0], r2
|
||||
strht r1, [r0], #4
|
Loading…
x
Reference in New Issue
Block a user