* Add support for encoding t_addrmode_s2 and t_addrmode_s1. They are the same as

t_addrmode_s4, but with a different scaling factor.

* Encode the Thumb1 load and store instructions. This involved a bit of
  refactoring (hi, Chris! :-). Some of the patterns became dead afterwards and
  were removed.

llvm-svn: 120482
This commit is contained in:
Bill Wendling 2010-11-30 22:57:21 +00:00
parent 8335e8fa63
commit a9e3df7aa0
5 changed files with 147 additions and 86 deletions

View File

@ -241,6 +241,10 @@ namespace {
const { return 0; }
uint32_t getAddrModeS4OpValue(const MachineInstr &MI, unsigned Op)
const { return 0; }
uint32_t getAddrModeS2OpValue(const MachineInstr &MI, unsigned Op)
const { return 0; }
uint32_t getAddrModeS1OpValue(const MachineInstr &MI, unsigned Op)
const { return 0; }
uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const {
// {17-13} = reg
// {12} = (U)nsigned (add == '1', sub == '0')

View File

@ -863,15 +863,6 @@ class T1pIt<dag oops, dag iops, InstrItinClass itin,
: Thumb1pI<oops, iops, AddrModeNone, Size2Bytes, itin, opc, asm,
"$lhs = $dst", pattern>;
class T1pI1<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
: Thumb1pI<oops, iops, AddrModeT1_1, Size2Bytes, itin, opc, asm, "", pattern>;
class T1pI2<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
: Thumb1pI<oops, iops, AddrModeT1_2, Size2Bytes, itin, opc, asm, "", pattern>;
class T1pI4<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
: Thumb1pI<oops, iops, AddrModeT1_4, Size2Bytes, itin, opc, asm, "", pattern>;
class T1pIs<dag oops, dag iops,
InstrItinClass itin, string opc, string asm, list<dag> pattern>
: Thumb1pI<oops, iops, AddrModeT1_s, Size2Bytes, itin, opc, asm, "", pattern>;
@ -909,11 +900,39 @@ class T1LoadStore<bits<4> opA, bits<3> opB> : Encoding16 {
let Inst{11-9} = opB;
}
class T1LdSt<bits<3> opB> : T1LoadStore<0b0101, opB>;
class T1LdSt4Imm<bits<3> opB> : T1LoadStore<0b0110, opB>; // Immediate, 4 bytes
class T1LdSt1Imm<bits<3> opB> : T1LoadStore<0b0111, opB>; // Immediate, 1 byte
class T1LdSt2Imm<bits<3> opB> : T1LoadStore<0b1000, opB>; // Immediate, 2 bytes
class T1LdStSP<bits<3> opB> : T1LoadStore<0b1001, opB>; // SP relative
// Helper classes to encode Thumb1 loads and stores. For immediates, the
// following bits are used for "opA":
//
// 0b0110 => Immediate, 4 bytes
// 0b1000 => Immediate, 2 bytes
// 0b0111 => Immediate, 1 byte
class T1LdStImm<bits<4> opA, bits<3> opB> : T1LoadStore<opA, opB>;
class T1pIEncode<bits<3> opcode, dag oops, dag iops, AddrMode am,
InstrItinClass itin, string opc, string asm,
list<dag> pattern>
: Thumb1pI<oops, iops, am, Size2Bytes, itin, opc, asm, "", pattern>,
T1LdSt<opcode> {
bits<3> Rt;
bits<8> addr;
let Inst{8-6} = addr{5-3}; // Rm
let Inst{5-3} = addr{2-0}; // Rn
let Inst{2-0} = Rt;
}
class T1pIEncodeImm<bits<4> opA, bit opB, dag oops, dag iops, AddrMode am,
InstrItinClass itin, string opc, string asm,
list<dag> pattern>
: Thumb1pI<oops, iops, am, Size2Bytes, itin, opc, asm, "", pattern>,
T1LdStImm<opA, {opB,?,?}> {
bits<3> Rt;
bits<8> addr;
let Inst{10-6} = addr{7-3}; // imm5
let Inst{5-3} = addr{2-0}; // Rn
let Inst{2-0} = Rt;
}
// A6.2.5 Miscellaneous 16-bit instructions encoding.
class T1Misc<bits<7> opcode> : Encoding16 {
let Inst{15-12} = 0b1011;

View File

@ -103,8 +103,10 @@ def t_addrmode_s4 : Operand<i32>,
//
def t_addrmode_s2 : Operand<i32>,
ComplexPattern<i32, 3, "SelectThumbAddrModeS2", []> {
string EncoderMethod = "getAddrModeS2OpValue";
let PrintMethod = "printThumbAddrModeS2Operand";
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
let ParserMatchClass = MemModeThumbAsmOperand;
}
// t_addrmode_s1 := reg + reg
@ -112,8 +114,10 @@ def t_addrmode_s2 : Operand<i32>,
//
def t_addrmode_s1 : Operand<i32>,
ComplexPattern<i32, 3, "SelectThumbAddrModeS1", []> {
string EncoderMethod = "getAddrModeS1OpValue";
let PrintMethod = "printThumbAddrModeS1Operand";
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
let ParserMatchClass = MemModeThumbAsmOperand;
}
// t_addrmode_sp := sp + imm8 * 4
@ -122,6 +126,7 @@ def t_addrmode_sp : Operand<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> {
let PrintMethod = "printThumbAddrModeSPOperand";
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
let ParserMatchClass = MemModeThumbAsmOperand;
}
//===----------------------------------------------------------------------===//
@ -508,59 +513,55 @@ def tTRAP : TI<(outs), (ins), IIC_Br,
//
let canFoldAsLoad = 1, isReMaterializable = 1 in
def tLDR : T1pI4<(outs tGPR:$Rt), (ins t_addrmode_s4:$addr), IIC_iLoad_r,
"ldr", "\t$Rt, $addr",
[(set tGPR:$Rt, (load t_addrmode_s4:$addr))]>,
T1LdSt<0b100> {
// A8.6.60
bits<3> Rt;
bits<8> addr;
let Inst{8-6} = addr{5-3}; // Rm
let Inst{5-3} = addr{2-0}; // Rn
let Inst{2-0} = Rt;
}
def tLDR : // A8.6.60
T1pIEncode<0b100, (outs tGPR:$Rt), (ins t_addrmode_s4:$addr),
AddrModeT1_4, IIC_iLoad_r,
"ldr", "\t$Rt, $addr",
[(set tGPR:$Rt, (load t_addrmode_s4:$addr))]>;
def tLDRi: T1pI4<(outs tGPR:$Rt), (ins t_addrmode_s4:$addr), IIC_iLoad_r,
"ldr", "\t$Rt, $addr",
[]>,
T1LdSt4Imm<{1,?,?}> {
// A8.6.57
bits<3> Rt;
bits<8> addr;
let Inst{10-6} = addr{7-3}; // imm5
let Inst{5-3} = addr{2-0}; // Rn
let Inst{2-0} = Rt;
}
def tLDRi: // A8.6.57
T1pIEncodeImm<0b0110, 1, (outs tGPR:$Rt), (ins t_addrmode_s4:$addr),
AddrModeT1_4, IIC_iLoad_r,
"ldr", "\t$Rt, $addr",
[]>;
def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoad_bh_r,
def tLDRB : // A8.6.64
T1pIEncode<0b110, (outs tGPR:$Rt), (ins t_addrmode_s1:$addr),
AddrModeT1_1, IIC_iLoad_bh_r,
"ldrb", "\t$Rt, $addr",
[(set tGPR:$Rt, (zextloadi8 t_addrmode_s1:$addr))]>;
def tLDRBi : // A8.6.61
T1pIEncodeImm<0b0111, 1, (outs tGPR:$dst), (ins t_addrmode_s1:$addr),
AddrModeT1_1, IIC_iLoad_bh_r,
"ldrb", "\t$dst, $addr",
[(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>,
T1LdSt<0b110>;
def tLDRBi: T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoad_bh_r,
"ldrb", "\t$dst, $addr",
[]>,
T1LdSt1Imm<{1,?,?}>;
[]>;
def tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoad_bh_r,
def tLDRH : // A8.6.76
T1pIEncode<0b101, (outs tGPR:$dst), (ins t_addrmode_s2:$addr),
AddrModeT1_2, IIC_iLoad_bh_r,
"ldrh", "\t$dst, $addr",
[(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>;
def tLDRHi: // A8.6.73
T1pIEncodeImm<0b1000, 1, (outs tGPR:$dst), (ins t_addrmode_s2:$addr),
AddrModeT1_2, IIC_iLoad_bh_r,
"ldrh", "\t$dst, $addr",
[(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>,
T1LdSt<0b101>;
def tLDRHi: T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoad_bh_r,
"ldrh", "\t$dst, $addr",
[]>,
T1LdSt2Imm<{1,?,?}>;
[]>;
let AddedComplexity = 10 in
def tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoad_bh_r,
"ldrsb", "\t$dst, $addr",
[(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>,
T1LdSt<0b011>;
def tLDRSB : // A8.6.80
T1pIEncode<0b011, (outs tGPR:$dst), (ins t_addrmode_rr:$addr),
AddrModeT1_1, IIC_iLoad_bh_r,
"ldrsb", "\t$dst, $addr",
[(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>;
let AddedComplexity = 10 in
def tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoad_bh_r,
"ldrsh", "\t$dst, $addr",
[(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>,
T1LdSt<0b111>;
def tLDRSH : // A8.6.84
T1pIEncode<0b111, (outs tGPR:$dst), (ins t_addrmode_rr:$addr),
AddrModeT1_2, IIC_iLoad_bh_r,
"ldrsh", "\t$dst, $addr",
[(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>;
let canFoldAsLoad = 1 in
def tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoad_i,
@ -590,32 +591,41 @@ def tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoad_i,
"ldr", "\t$dst, $addr", []>,
T1LdStSP<{1,?,?}>;
def tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStore_r,
"str", "\t$src, $addr",
[(store tGPR:$src, t_addrmode_s4:$addr)]>,
T1LdSt<0b000>;
def tSTRi: T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStore_r,
"str", "\t$src, $addr",
[]>,
T1LdSt4Imm<{0,?,?}>;
def tSTR : // A8.6.194
T1pIEncode<0b000, (outs), (ins tGPR:$src, t_addrmode_s4:$addr),
AddrModeT1_4, IIC_iStore_r,
"str", "\t$src, $addr",
[(store tGPR:$src, t_addrmode_s4:$addr)]>;
def tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStore_bh_r,
"strb", "\t$src, $addr",
[(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>,
T1LdSt<0b010>;
def tSTRBi: T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStore_bh_r,
"strb", "\t$src, $addr",
[]>,
T1LdSt1Imm<{0,?,?}>;
def tSTRi : // A8.6.192
T1pIEncodeImm<0b0110, 0, (outs), (ins tGPR:$src, t_addrmode_s4:$addr),
AddrModeT1_4, IIC_iStore_r,
"str", "\t$src, $addr",
[]>;
def tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStore_bh_r,
"strh", "\t$src, $addr",
[(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>,
T1LdSt<0b001>;
def tSTRHi: T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStore_bh_r,
"strh", "\t$src, $addr",
[]>,
T1LdSt2Imm<{0,?,?}>;
def tSTRB : // A8.6.197
T1pIEncode<0b010, (outs), (ins tGPR:$src, t_addrmode_s1:$addr),
AddrModeT1_1, IIC_iStore_bh_r,
"strb", "\t$src, $addr",
[(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>;
def tSTRBi : // A8.6.195
T1pIEncodeImm<0b0111, 0, (outs), (ins tGPR:$src, t_addrmode_s1:$addr),
AddrModeT1_1, IIC_iStore_bh_r,
"strb", "\t$src, $addr",
[]>;
def tSTRH : // A8.6.207
T1pIEncode<0b001, (outs), (ins tGPR:$src, t_addrmode_s2:$addr),
AddrModeT1_2, IIC_iStore_bh_r,
"strh", "\t$src, $addr",
[(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>;
def tSTRHi : // A8.6.205
T1pIEncodeImm<0b1000, 0, (outs), (ins tGPR:$src, t_addrmode_s2:$addr),
AddrModeT1_2, IIC_iStore_bh_r,
"strh", "\t$src, $addr",
[]>;
def tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStore_i,
"str", "\t$src, $addr",

View File

@ -140,6 +140,14 @@ public:
uint32_t getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getAddrModeS2OpValue - Return encoding for t_addrmode_s2 operands.
uint32_t getAddrModeS2OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getAddrModeS1OpValue - Return encoding for t_addrmode_s1 operands.
uint32_t getAddrModeS1OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand.
uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
@ -545,10 +553,9 @@ getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13);
}
/// getAddrModeS4OpValue - Return encoding for t_addrmode_s4 operands.
uint32_t ARMMCCodeEmitter::
getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
/// getAddrModeSOpValue - Encode the t_addrmode_s# operands.
static unsigned getAddrModeSOpValue(const MCInst &MI, unsigned OpIdx,
unsigned Scale) {
// [Rn, Rm]
// {5-3} = Rm
// {2-0} = Rn
@ -560,11 +567,32 @@ getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx,
const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
const MCOperand &MO2 = MI.getOperand(OpIdx + 2);
unsigned Rn = getARMRegisterNumbering(MO.getReg());
unsigned Imm5 = MO1.getImm();
unsigned Imm5 = (MO1.getImm() / Scale) & 0x1f;
unsigned Rm = getARMRegisterNumbering(MO2.getReg());
return (Rm << 3) | (Imm5 << 3) | Rn;
}
/// getAddrModeS4OpValue - Return encoding for t_addrmode_s4 operands.
uint32_t ARMMCCodeEmitter::
getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &) const {
return getAddrModeSOpValue(MI, OpIdx, 4);
}
/// getAddrModeS2OpValue - Return encoding for t_addrmode_s2 operands.
uint32_t ARMMCCodeEmitter::
getAddrModeS2OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &) const {
return getAddrModeSOpValue(MI, OpIdx, 2);
}
/// getAddrModeS1OpValue - Return encoding for t_addrmode_s1 operands.
uint32_t ARMMCCodeEmitter::
getAddrModeS1OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &) const {
return getAddrModeSOpValue(MI, OpIdx, 1);
}
/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm12' operand.
uint32_t ARMMCCodeEmitter::
getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,

View File

@ -323,7 +323,7 @@ public:
if (Mem.Offset) {
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
assert(CE && "Non-constant mode offset operand!");
Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
Inst.addOperand(MCOperand::CreateReg(0));
} else {
Inst.addOperand(MCOperand::CreateImm(0));