ARM LDR_PRE/LDR_POST/STR_PRE/STR_POST (and the *B counterparts) binary encoding.

llvm-svn: 119180
This commit is contained in:
Jim Grosbach 2010-11-15 20:47:07 +00:00
parent db73d599b7
commit 38b469effd
4 changed files with 151 additions and 38 deletions

View File

@ -214,6 +214,10 @@ namespace {
Binary |= (Reg << 13);
return Binary;
}
uint32_t getAddrMode2OpValue(const MachineInstr &MI, unsigned OpIdx)
const { return 0;}
uint32_t getAddrMode2OffsetOpValue(const MachineInstr &MI, unsigned OpIdx)
const { return 0;}
uint32_t getAddrMode3OffsetOpValue(const MachineInstr &MI, unsigned OpIdx)
const { return 0;}
uint32_t getAddrMode3OpValue(const MachineInstr &MI, unsigned Op) const

View File

@ -438,11 +438,13 @@ class AI2ldstidx<bit isLd, bit isByte, bit isPre, dag oops, dag iops,
string asm, string cstr, list<dag> pattern>
: I<oops, iops, AddrMode2, Size4Bytes, im, f, itin,
opc, asm, cstr, pattern> {
bits<4> Rt;
let Inst{27-26} = 0b01;
let Inst{24} = isPre; // P bit
let Inst{22} = isByte; // B bit
let Inst{21} = isPre; // W bit
let Inst{20} = isLd; // L bit
let Inst{15-12} = Rt;
}
class AXI2ldw<dag oops, dag iops, Format f, InstrItinClass itin,

View File

@ -440,6 +440,7 @@ def ldst_so_reg : Operand<i32>,
//
def addrmode2 : Operand<i32>,
ComplexPattern<i32, 3, "SelectAddrMode2", []> {
string EncoderMethod = "getAddrMode2OpValue";
let PrintMethod = "printAddrMode2Operand";
let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}
@ -447,6 +448,7 @@ def addrmode2 : Operand<i32>,
def am2offset : Operand<i32>,
ComplexPattern<i32, 2, "SelectAddrMode2Offset",
[], [SDNPWantRoot]> {
string EncoderMethod = "getAddrMode2OffsetOpValue";
let PrintMethod = "printAddrMode2OffsetOperand";
let MIOperandInfo = (ops GPR, i32imm);
}
@ -1550,11 +1552,31 @@ def LDRD : AI3ldd<(outs GPR:$dst1, GPR:$dst2), (ins addrmode3:$addr), LdMiscFrm,
multiclass AI2_ldridx<bit isByte, string opc, InstrItinClass itin> {
def _PRE : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins addrmode2:$addr), IndexModePre, LdFrm, itin,
opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []>;
opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
// {17-14} Rn
// {13} 1 == Rm, 0 == imm12
// {12} isAdd
// {11-0} imm12/Rm
bits<18> addr;
let Inst{25} = addr{13};
let Inst{23} = addr{12};
let Inst{19-16} = addr{17-14};
let Inst{11-0} = addr{11-0};
}
def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
(ins GPR:$Rn, am2offset:$offset),
IndexModePost, LdFrm, itin,
opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []>;
opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> {
// {13} 1 == Rm, 0 == imm12
// {12} isAdd
// {11-0} imm12/Rm
bits<14> offset;
bits<4> Rn;
let Inst{25} = offset{13};
let Inst{23} = offset{12};
let Inst{19-16} = Rn;
let Inst{11-0} = offset{11-0};
}
}
defm LDR : AI2_ldridx<0, "ldr", IIC_iLoad_ru>;
@ -1647,19 +1669,39 @@ def STRD : AI3std<(outs), (ins GPR:$src1, GPR:$src2, addrmode3:$addr),
"strd", "\t$src1, $addr", []>, Requires<[IsARM, HasV5TE]>;
// Indexed stores
def STR_PRE : AI2ldstidx<0, 0, 1, (outs GPR:$base_wb),
(ins GPR:$src, GPR:$base, am2offset:$offset),
def STR_PRE : AI2ldstidx<0, 0, 1, (outs GPR:$Rn_wb),
(ins GPR:$Rt, GPR:$Rn, am2offset:$offset),
IndexModePre, StFrm, IIC_iStore_ru,
"str", "\t$src, [$base, $offset]!", "$base = $base_wb",
[(set GPR:$base_wb,
(pre_store GPR:$src, GPR:$base, am2offset:$offset))]>;
"str", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb",
[(set GPR:$Rn_wb,
(pre_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]> {
// {13} 1 == Rm, 0 == imm12
// {12} isAdd
// {11-0} imm12/Rm
bits<14> offset;
bits<4> Rn;
let Inst{25} = offset{13};
let Inst{23} = offset{12};
let Inst{19-16} = Rn;
let Inst{11-0} = offset{11-0};
}
def STR_POST : AI2ldstidx<0, 0, 0, (outs GPR:$base_wb),
(ins GPR:$src, GPR:$base,am2offset:$offset),
def STR_POST : AI2ldstidx<0, 0, 0, (outs GPR:$Rn_wb),
(ins GPR:$Rt, GPR:$Rn, am2offset:$offset),
IndexModePost, StFrm, IIC_iStore_ru,
"str", "\t$src, [$base], $offset", "$base = $base_wb",
[(set GPR:$base_wb,
(post_store GPR:$src, GPR:$base, am2offset:$offset))]>;
"str", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",
[(set GPR:$Rn_wb,
(post_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]> {
// {13} 1 == Rm, 0 == imm12
// {12} isAdd
// {11-0} imm12/Rm
bits<14> offset;
bits<4> Rn;
let Inst{25} = offset{13};
let Inst{23} = offset{12};
let Inst{19-16} = Rn;
let Inst{11-0} = offset{11-0};
}
def STRH_PRE : AI3sthpr<(outs GPR:$base_wb),
(ins GPR:$src, GPR:$base,am3offset:$offset),
@ -1675,19 +1717,39 @@ def STRH_POST: AI3sthpo<(outs GPR:$base_wb),
[(set GPR:$base_wb, (post_truncsti16 GPR:$src,
GPR:$base, am3offset:$offset))]>;
def STRB_PRE : AI2ldstidx<0, 1, 1, (outs GPR:$base_wb),
(ins GPR:$src, GPR:$base,am2offset:$offset),
def STRB_PRE : AI2ldstidx<0, 1, 1, (outs GPR:$Rn_wb),
(ins GPR:$Rt, GPR:$Rn,am2offset:$offset),
IndexModePre, StFrm, IIC_iStore_bh_ru,
"strb", "\t$src, [$base, $offset]!", "$base = $base_wb",
[(set GPR:$base_wb, (pre_truncsti8 GPR:$src,
GPR:$base, am2offset:$offset))]>;
"strb", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb",
[(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt,
GPR:$Rn, am2offset:$offset))]> {
// {13} 1 == Rm, 0 == imm12
// {12} isAdd
// {11-0} imm12/Rm
bits<14> offset;
bits<4> Rn;
let Inst{25} = offset{13};
let Inst{23} = offset{12};
let Inst{19-16} = Rn;
let Inst{11-0} = offset{11-0};
}
def STRB_POST: AI2ldstidx<0, 1, 0, (outs GPR:$base_wb),
(ins GPR:$src, GPR:$base,am2offset:$offset),
def STRB_POST: AI2ldstidx<0, 1, 0, (outs GPR:$Rn_wb),
(ins GPR:$Rt, GPR:$Rn,am2offset:$offset),
IndexModePost, StFrm, IIC_iStore_bh_ru,
"strb", "\t$src, [$base], $offset", "$base = $base_wb",
[(set GPR:$base_wb, (post_truncsti8 GPR:$src,
GPR:$base, am2offset:$offset))]>;
"strb", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",
[(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt,
GPR:$Rn, am2offset:$offset))]> {
// {13} 1 == Rm, 0 == imm12
// {12} isAdd
// {11-0} imm12/Rm
bits<14> offset;
bits<4> Rn;
let Inst{25} = offset{13};
let Inst{23} = offset{12};
let Inst{19-16} = Rn;
let Inst{11-0} = offset{11-0};
}
// For disassembly only
def STRD_PRE : AI3stdpr<(outs GPR:$base_wb),

View File

@ -101,6 +101,29 @@ public:
case ARM_AM::ib: return 3;
}
}
/// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value.
///
unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const {
switch (ShOpc) {
default: llvm_unreachable("Unknown shift opc!");
case ARM_AM::no_shift:
case ARM_AM::lsl: return 0;
case ARM_AM::lsr: return 1;
case ARM_AM::asr: return 2;
case ARM_AM::ror:
case ARM_AM::rrx: return 3;
}
return 0;
}
/// getAddrMode2OpValue - Return encoding for addrmode2 operands.
uint32_t getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getAddrMode2OffsetOpValue - Return encoding for am2offset operands.
uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getAddrMode3OffsetOpValue - Return encoding for am3offset operands.
uint32_t getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
@ -380,24 +403,10 @@ getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
const MCOperand &MO2 = MI.getOperand(OpIdx+2);
unsigned Rn = getARMRegisterNumbering(MO.getReg());
unsigned Rm = getARMRegisterNumbering(MO1.getReg());
ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm());
unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm());
bool isAdd = ARM_AM::getAM2Op(MO2.getImm()) == ARM_AM::add;
unsigned SBits;
// LSL - 00
// LSR - 01
// ASR - 10
// ROR - 11
switch (ShOp) {
default: llvm_unreachable("Unknown shift opc!");
case ARM_AM::no_shift:
assert(ShImm == 0 && "Non-zero shift amount with no shift type!");
// fall through
case ARM_AM::lsl: SBits = 0x0; break;
case ARM_AM::lsr: SBits = 0x1; break;
case ARM_AM::asr: SBits = 0x2; break;
case ARM_AM::ror: SBits = 0x3; break;
}
ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm());
unsigned SBits = getShiftOp(ShOp);
// {16-13} = Rn
// {12} = isAdd
@ -415,6 +424,42 @@ getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
return Binary;
}
uint32_t ARMMCCodeEmitter::
getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
// {17-14} Rn
// {13} 1 == imm12, 0 == Rm
// {12} isAdd
// {11-0} imm12/Rm
const MCOperand &MO = MI.getOperand(OpIdx);
unsigned Rn = getARMRegisterNumbering(MO.getReg());
uint32_t Binary = getAddrMode2OffsetOpValue(MI, OpIdx + 1, Fixups);
Binary |= Rn << 14;
return Binary;
}
uint32_t ARMMCCodeEmitter::
getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
// {13} 1 == imm12, 0 == Rm
// {12} isAdd
// {11-0} imm12/Rm
const MCOperand &MO = MI.getOperand(OpIdx);
const MCOperand &MO1 = MI.getOperand(OpIdx+1);
unsigned Imm = MO1.getImm();
bool isAdd = ARM_AM::getAM2Op(Imm) == ARM_AM::add;
bool isReg = MO.getReg() != 0;
uint32_t Binary = ARM_AM::getAM2Offset(Imm);
// if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm12
if (isReg) {
ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(Imm);
Binary <<= 7; // Shift amount is bits [11:7]
Binary |= getShiftOp(ShOp) << 5; // Shift type is bits [6:5]
Binary |= getARMRegisterNumbering(MO.getReg()); // Rm is bits [3:0]
}
return Binary | (isAdd << 12) | (isReg << 13);
}
uint32_t ARMMCCodeEmitter::
getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {