Thumb2 assembly parsing and encoding for LDR pre-indexed w/ writeback.

Adjust encoding of writeback load/store instructions to better reflect the
way the operand types are represented.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139270 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2011-09-08 00:39:19 +00:00
parent 170580e8f4
commit eeec025cf5
4 changed files with 118 additions and 59 deletions

View File

@ -1161,8 +1161,8 @@ class T2XIt<dag oops, dag iops, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
: Thumb2XI<oops, iops, AddrModeNone, 4, itin, asm, cstr, pattern>;
// T2Iidxldst - Thumb2 indexed load / store instructions.
class T2Iidxldst<bit signed, bits<2> opcod, bit load, bit pre,
// T2Ipreldst - Thumb2 pre-indexed load / store instructions.
class T2Ipreldst<bit signed, bits<2> opcod, bit load, bit pre,
dag oops, dag iops,
AddrMode am, IndexMode im, InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
@ -1173,25 +1173,55 @@ class T2Iidxldst<bit signed, bits<2> opcod, bit load, bit pre,
let Pattern = pattern;
list<Predicate> Predicates = [IsThumb2];
let DecoderNamespace = "Thumb2";
bits<4> Rt;
bits<13> addr;
let Inst{31-27} = 0b11111;
let Inst{26-25} = 0b00;
let Inst{24} = signed;
let Inst{23} = 0;
let Inst{22-21} = opcod;
let Inst{20} = load;
let Inst{19-16} = addr{12-9};
let Inst{15-12} = Rt{3-0};
let Inst{11} = 1;
// (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed
let Inst{10} = pre; // The P bit.
let Inst{9} = addr{8}; // Sign bit
let Inst{8} = 1; // The W bit.
let Inst{7-0} = addr{7-0};
}
bits<9> addr;
let Inst{7-0} = addr{7-0};
let Inst{9} = addr{8}; // Sign bit
// T2Ipostldst - Thumb2 post-indexed load / store instructions.
class T2Ipostldst<bit signed, bits<2> opcod, bit load, bit pre,
dag oops, dag iops,
AddrMode am, IndexMode im, InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
: InstARM<am, 4, im, ThumbFrm, GenericDomain, cstr, itin> {
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${p}", asm);
let Pattern = pattern;
list<Predicate> Predicates = [IsThumb2];
let DecoderNamespace = "Thumb2";
bits<4> Rt;
bits<4> Rn;
bits<9> addr;
let Inst{31-27} = 0b11111;
let Inst{26-25} = 0b00;
let Inst{24} = signed;
let Inst{23} = 0;
let Inst{22-21} = opcod;
let Inst{20} = load;
let Inst{19-16} = Rn;
let Inst{15-12} = Rt{3-0};
let Inst{19-16} = Rn{3-0};
let Inst{11} = 1;
// (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed
let Inst{10} = pre; // The P bit.
let Inst{9} = addr{8}; // Sign bit
let Inst{8} = 1; // The W bit.
let Inst{7-0} = addr{7-0};
}
// Tv5Pat - Same as Pat<>, but requires V5T Thumb mode.

View File

@ -1244,61 +1244,66 @@ def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
// Indexed loads
let mayLoad = 1, neverHasSideEffects = 1 in {
def t2LDR_PRE : T2Iidxldst<0, 0b10, 1, 1, (outs GPR:$Rt, GPR:$Rn),
def t2LDR_PRE : T2Ipreldst<0, 0b10, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iLoad_iu,
"ldr", "\t$Rt, $addr!", "$addr.base = $Rn",
[]>;
"ldr", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
[]> {
let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
}
def t2LDR_POST : T2Iidxldst<0, 0b10, 1, 0, (outs GPR:$Rt, GPR:$Rn),
(ins GPR:$base, t2am_imm8_offset:$addr),
def t2LDR_POST : T2Ipostldst<0, 0b10, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
(ins GPR:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePost, IIC_iLoad_iu,
"ldr", "\t$Rt, [$Rn], $addr", "$base = $Rn",
[]>;
"ldr", "\t$Rt, [$Rn], $addr", "$Rn = $Rn_wb", []>;
def t2LDRB_PRE : T2Iidxldst<0, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn),
def t2LDRB_PRE : T2Ipreldst<0, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
"ldrb", "\t$Rt, $addr!", "$addr.base = $Rn",
[]>;
def t2LDRB_POST : T2Iidxldst<0, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn),
(ins GPR:$base, t2am_imm8_offset:$addr),
"ldrb", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
[]> {
let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
}
def t2LDRB_POST : T2Ipostldst<0, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
(ins GPR:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
"ldrb", "\t$Rt, [$Rn], $addr", "$base = $Rn",
[]>;
"ldrb", "\t$Rt, [$Rn], $addr", "$Rn = $Rn_wb", []>;
def t2LDRH_PRE : T2Iidxldst<0, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn),
def t2LDRH_PRE : T2Ipreldst<0, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
"ldrh", "\t$Rt, $addr!", "$addr.base = $Rn",
[]>;
def t2LDRH_POST : T2Iidxldst<0, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn),
(ins GPR:$base, t2am_imm8_offset:$addr),
"ldrh", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
[]> {
let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
}
def t2LDRH_POST : T2Ipostldst<0, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
(ins GPR:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
"ldrh", "\t$Rt, [$Rn], $addr", "$base = $Rn",
[]>;
"ldrh", "\t$Rt, [$Rn], $addr", "$Rn = $Rn_wb", []>;
def t2LDRSB_PRE : T2Iidxldst<1, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn),
def t2LDRSB_PRE : T2Ipreldst<1, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
"ldrsb", "\t$Rt, $addr!", "$addr.base = $Rn",
[]>;
def t2LDRSB_POST : T2Iidxldst<1, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn),
(ins GPR:$base, t2am_imm8_offset:$addr),
"ldrsb", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
[]> {
let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
}
def t2LDRSB_POST : T2Ipostldst<1, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
(ins GPR:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
"ldrsb", "\t$Rt, [$Rn], $addr", "$base = $Rn",
[]>;
"ldrsb", "\t$Rt, [$Rn], $addr", "$Rn = $Rn_wb", []>;
def t2LDRSH_PRE : T2Iidxldst<1, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn),
def t2LDRSH_PRE : T2Ipreldst<1, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
"ldrsh", "\t$Rt, $addr!", "$addr.base = $Rn",
[]>;
def t2LDRSH_POST : T2Iidxldst<1, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn),
(ins GPR:$base, t2am_imm8_offset:$addr),
"ldrsh", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
[]> {
let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
}
def t2LDRSH_POST : T2Ipostldst<1, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
(ins GPR:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
"ldrsh", "\t$Rt, [$Rn], $addr", "$base = $Rn",
[]>;
"ldrsh", "\t$Rt, [$Rn], $addr", "$Rn = $Rn_wb", []>;
} // mayLoad = 1, neverHasSideEffects = 1
// LDRT, LDRBT, LDRHT, LDRSBT, LDRSHT all have offset mode (PUW=0b110).
@ -1342,52 +1347,52 @@ def t2STRDi8 : T2Ii8s4<1, 0, 0, (outs),
IIC_iStore_d_r, "strd", "\t$Rt, $Rt2, $addr", []>;
// Indexed stores
def t2STR_PRE : T2Iidxldst<0, 0b10, 0, 1, (outs GPRnopc:$base_wb),
def t2STR_PRE : T2Ipreldst<0, 0b10, 0, 1, (outs GPRnopc:$Rn_wb),
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePre, IIC_iStore_iu,
"str", "\t$Rt, [$Rn, $addr]!",
"$Rn = $base_wb,@earlyclobber $base_wb",
[(set GPRnopc:$base_wb,
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
[(set GPRnopc:$Rn_wb,
(pre_store rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
def t2STR_POST : T2Iidxldst<0, 0b10, 0, 0, (outs GPRnopc:$base_wb),
def t2STR_POST : T2Ipostldst<0, 0b10, 0, 0, (outs GPRnopc:$Rn_wb),
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePost, IIC_iStore_iu,
"str", "\t$Rt, [$Rn], $addr",
"$Rn = $base_wb,@earlyclobber $base_wb",
[(set GPRnopc:$base_wb,
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
[(set GPRnopc:$Rn_wb,
(post_store rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
def t2STRH_PRE : T2Iidxldst<0, 0b01, 0, 1, (outs GPRnopc:$base_wb),
def t2STRH_PRE : T2Ipreldst<0, 0b01, 0, 1, (outs GPRnopc:$Rn_wb),
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePre, IIC_iStore_iu,
"strh", "\t$Rt, [$Rn, $addr]!",
"$Rn = $base_wb,@earlyclobber $base_wb",
[(set GPRnopc:$base_wb,
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
[(set GPRnopc:$Rn_wb,
(pre_truncsti16 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
def t2STRH_POST : T2Iidxldst<0, 0b01, 0, 0, (outs GPRnopc:$base_wb),
def t2STRH_POST : T2Ipostldst<0, 0b01, 0, 0, (outs GPRnopc:$Rn_wb),
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
"strh", "\t$Rt, [$Rn], $addr",
"$Rn = $base_wb,@earlyclobber $base_wb",
[(set GPRnopc:$base_wb,
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
[(set GPRnopc:$Rn_wb,
(post_truncsti16 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
def t2STRB_PRE : T2Iidxldst<0, 0b00, 0, 1, (outs GPRnopc:$base_wb),
def t2STRB_PRE : T2Ipreldst<0, 0b00, 0, 1, (outs GPRnopc:$Rn_wb),
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePre, IIC_iStore_bh_iu,
"strb", "\t$Rt, [$Rn, $addr]!",
"$Rn = $base_wb,@earlyclobber $base_wb",
[(set GPRnopc:$base_wb,
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
[(set GPRnopc:$Rn_wb,
(pre_truncsti8 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPRnopc:$base_wb),
def t2STRB_POST : T2Ipostldst<0, 0b00, 0, 0, (outs GPRnopc:$Rn_wb),
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
"strb", "\t$Rt, [$Rn], $addr",
"$Rn = $base_wb,@earlyclobber $base_wb",
[(set GPRnopc:$base_wb,
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
[(set GPRnopc:$Rn_wb,
(post_truncsti8 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
// STRT, STRBT, STRHT all have offset mode (PUW=0b110) and are for disassembly

View File

@ -158,6 +158,8 @@ class ARMAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
// Asm Match Converter Methods
bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
@ -2398,6 +2400,22 @@ parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
/// cvtLdWriteBackRegT2AddrModeImm8 - 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::
cvtLdWriteBackRegT2AddrModeImm8(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])->addMemImm8OffsetOperands(Inst, 2);
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
return true;
}
/// 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.

View File

@ -548,6 +548,9 @@ _func:
ldr r8, [r8, r2, lsl #2]
ldr r7, [sp, r2, lsl #1]
ldr r7, [sp, r2, lsl #0]
ldr r2, [r4, #255]!
ldr r8, [sp, #4]!
ldr lr, [sp, #-4]!
@ CHECK: ldr.w r1, [r8, r1] @ encoding: [0x58,0xf8,0x01,0x10]
@ CHECK: ldr.w r4, [r5, r2] @ encoding: [0x55,0xf8,0x02,0x40]
@ -555,6 +558,9 @@ _func:
@ CHECK: ldr.w r8, [r8, r2, lsl #2] @ encoding: [0x58,0xf8,0x22,0x80]
@ CHECK: ldr.w r7, [sp, r2, lsl #1] @ encoding: [0x5d,0xf8,0x12,0x70]
@ CHECK: ldr.w r7, [sp, r2] @ encoding: [0x5d,0xf8,0x02,0x70]
@ CHECK: ldr r2, [r4, #255]! @ encoding: [0x54,0xf8,0xff,0x2f]
@ CHECK: ldr r8, [sp, #4]! @ encoding: [0x5d,0xf8,0x04,0x8f]
@ CHECK: ldr lr, [sp, #-4]! @ encoding: [0x5d,0xf8,0x04,0xed]
@------------------------------------------------------------------------------