aboutsummaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2011-08-03 23:50:40 +0000
committerJim Grosbach <grosbach@apple.com>2011-08-03 23:50:40 +0000
commit7ce057983ea7b8ad42d5cca1bb5d3f6941662269 (patch)
tree54a731f5142d082ed12dd47c2c4625ed0eb68619 /lib/Target
parent762797d1af1b9308c79982aedd9bd2f585f46171 (diff)
ARM refactoring assembly parsing of memory address operands.
Memory operand parsing is a bit haphazzard at the moment, in no small part due to the even more haphazzard representations of memory operands in the .td files. Start cleaning that all up, at least a bit. The addressing modes in the .td files will be being simplified to not be so monolithic, especially with regards to immediate vs. register offsets and post-indexed addressing. addrmode3 is on its way with this patch, for example. This patch is foundational to enable going back to smaller incremental patches for the individual memory referencing instructions themselves. It does just enough to get the basics in place and handle the "make check" regression tests we already have. Follow-up work will be fleshing out the details and adding more robust test cases for the individual instructions, starting with ARM mode and moving from there into Thumb and Thumb2. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136845 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp2
-rw-r--r--lib/Target/ARM/ARMInstrFormats.td45
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td161
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td22
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td8
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp869
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassembler.cpp8
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp37
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp14
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.h7
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h3
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp16
12 files changed, 562 insertions, 630 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index e0720b3da8..7d4eb6f18f 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -266,6 +266,8 @@ namespace {
const { return 0;}
uint32_t getAddrMode2OffsetOpValue(const MachineInstr &MI, unsigned OpIdx)
const { return 0;}
+ uint32_t getPostIdxRegOpValue(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)
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td
index 769fecf6d8..c3d9e39dfa 100644
--- a/lib/Target/ARM/ARMInstrFormats.td
+++ b/lib/Target/ARM/ARMInstrFormats.td
@@ -597,29 +597,24 @@ class AI3ldstidx<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
// 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,
+class AI3ldstidxT<bits<4> op, bit isLoad, dag oops, dag iops,
IndexMode im, Format f, InstrItinClass itin, string opc,
string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, 4, im, f, itin,
- opc, asm, cstr, pattern> {
+ : I<oops, iops, AddrMode3, 4, 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> 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{24} = 0; // P bit
+ let Inst{21} = 1;
+ let Inst{20} = isLoad; // L bit
+ let Inst{19-16} = addr; // 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,
@@ -690,32 +685,6 @@ class AI3stdpr<dag oops, dag iops, Format f, InstrItinClass itin,
}
// Post-indexed stores
-class AI3sthpo<dag oops, dag iops, Format f, InstrItinClass itin,
- string opc, string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, 4, 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;
-}
class AI3stdpo<dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
: I<oops, iops, AddrMode3, 4, IndexModePost, f, itin,
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index d94e287eff..f03aced9cb 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -590,6 +590,7 @@ def imm1_16 : Operand<i32>, PatLeaf<(imm), [{ return Imm > 0 && Imm <= 16; }],
// Define ARM specific addressing modes.
// addrmode_imm12 := reg +/- imm12
//
+def MemImm12OffsetAsmOperand : AsmOperandClass { let Name = "MemImm12Offset"; }
def addrmode_imm12 : Operand<i32>,
ComplexPattern<i32, 2, "SelectAddrModeImm12", []> {
// 12-bit immediate operand. Note that instructions using this encode
@@ -598,30 +599,58 @@ def addrmode_imm12 : Operand<i32>,
let EncoderMethod = "getAddrModeImm12OpValue";
let PrintMethod = "printAddrModeImm12Operand";
+ let ParserMatchClass = MemImm12OffsetAsmOperand;
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
}
// ldst_so_reg := reg +/- reg shop imm
//
+def MemRegOffsetAsmOperand : AsmOperandClass { let Name = "MemRegOffset"; }
def ldst_so_reg : Operand<i32>,
ComplexPattern<i32, 3, "SelectLdStSOReg", []> {
let EncoderMethod = "getLdStSORegOpValue";
// FIXME: Simplify the printer
let PrintMethod = "printAddrMode2Operand";
- let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
+ let ParserMatchClass = MemRegOffsetAsmOperand;
+ let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$shift);
}
+// postidx_imm8 := +/- [0,255]
+//
+// 9 bit value:
+// {8} 1 is imm8 is non-negative. 0 otherwise.
+// {7-0} [0,255] imm8 value.
+def PostIdxImm8AsmOperand : AsmOperandClass { let Name = "PostIdxImm8"; }
+def postidx_imm8 : Operand<i32> {
+ let PrintMethod = "printPostIdxImm8Operand";
+ let ParserMatchClass = PostIdxImm8AsmOperand;
+ let MIOperandInfo = (ops i32imm);
+}
+
+// postidx_reg := +/- reg
+//
+def PostIdxRegAsmOperand : AsmOperandClass {
+ let Name = "PostIdxReg";
+ let ParserMethod = "parsePostIdxReg";
+}
+def postidx_reg : Operand<i32> {
+ let EncoderMethod = "getPostIdxRegOpValue";
+ let PrintMethod = "printAddrMode3OffsetOperand";
+ let ParserMatchClass = PostIdxRegAsmOperand;
+ let MIOperandInfo = (ops GPR, i32imm);
+}
+
+
// addrmode2 := reg +/- imm12
// := reg +/- reg shop imm
//
-def MemMode2AsmOperand : AsmOperandClass {
- let Name = "MemMode2";
- let ParserMethod = "parseMemMode2Operand";
-}
+// FIXME: addrmode2 should be refactored the rest of the way to always
+// use explicit imm vs. reg versions above (addrmode_imm12 and ldst_so_reg).
+def AddrMode2AsmOperand : AsmOperandClass { let Name = "AddrMode2"; }
def addrmode2 : Operand<i32>,
ComplexPattern<i32, 3, "SelectAddrMode2", []> {
let EncoderMethod = "getAddrMode2OpValue";
let PrintMethod = "printAddrMode2Operand";
- let ParserMatchClass = MemMode2AsmOperand;
+ let ParserMatchClass = AddrMode2AsmOperand;
let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}
@@ -645,15 +674,11 @@ def am2offset_imm : Operand<i32>,
// addrmode3 := reg +/- reg
// addrmode3 := reg +/- imm8
//
-def MemMode3AsmOperand : AsmOperandClass {
- let Name = "MemMode3";
- let ParserMethod = "parseMemMode3Operand";
-}
+//def AddrMode3AsmOperand : AsmOperandClass { let Name = "AddrMode3"; }
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);
}
@@ -674,13 +699,13 @@ def ldstm_mode : OptionalDefOperand<OtherVT, (ops i32), (ops (i32 1))> {
// addrmode5 := reg +/- imm8*4
//
-def MemMode5AsmOperand : AsmOperandClass { let Name = "MemMode5"; }
+def AddrMode5AsmOperand : AsmOperandClass { let Name = "AddrMode5"; }
def addrmode5 : Operand<i32>,
ComplexPattern<i32, 2, "SelectAddrMode5", []> {
let PrintMethod = "printAddrMode5Operand";
- let MIOperandInfo = (ops GPR:$base, i32imm);
- let ParserMatchClass = MemMode5AsmOperand;
let EncoderMethod = "getAddrMode5OpValue";
+ let ParserMatchClass = AddrMode5AsmOperand;
+ let MIOperandInfo = (ops GPR:$base, i32imm);
}
// addrmode6 := reg with optional alignment
@@ -728,11 +753,11 @@ def addrmodepc : Operand<i32>,
// addr_offset_none := reg
//
-def MemMode7AsmOperand : AsmOperandClass { let Name = "MemMode7"; }
+def MemNoOffsetAsmOperand : AsmOperandClass { let Name = "MemNoOffset"; }
def addr_offset_none : Operand<i32> {
let PrintMethod = "printAddrMode7Operand";
- let MIOperandInfo = (ops GPR);
- let ParserMatchClass = MemMode7AsmOperand;
+ let ParserMatchClass = MemNoOffsetAsmOperand;
+ let MIOperandInfo = (ops GPR:$base);
}
def nohash_imm : Operand<i32> {
@@ -1822,7 +1847,7 @@ defm STRB : AI_str1<1, "strb", IIC_iStore_bh_r, IIC_iStore_bh_si,
// Special LDR for loads from non-pc-relative constpools.
let canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1,
- isReMaterializable = 1 in
+ isReMaterializable = 1, isCodeGenOnly = 1 in
def LDRcp : AI2ldst<0b010, 1, 0, (outs GPR:$Rt), (ins addrmode_imm12:$addr),
AddrMode_i12, LdFrm, IIC_iLoad_r, "ldr", "\t$Rt, $addr",
[]> {
@@ -2002,21 +2027,35 @@ def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
let Inst{11-0} = addr{11-0};
let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
}
-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 : 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 : 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
+
+multiclass AI3ldrT<bits<4> op, string opc> {
+ def i : AI3ldstidxT<op, 1, (outs GPR:$Rt, GPR:$base_wb),
+ (ins addr_offset_none:$addr, postidx_imm8:$offset),
+ IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, opc,
+ "\t$Rt, $addr, $offset", "$addr.base = $base_wb", []> {
+ bits<9> offset;
+ let Inst{23} = offset{8};
+ let Inst{22} = 1;
+ let Inst{11-8} = offset{7-4};
+ let Inst{3-0} = offset{3-0};
+ let AsmMatchConverter = "cvtLdExtTWriteBackImm";
+ }
+ def r : AI3ldstidxT<op, 1, (outs GPR:$Rt, GPR:$base_wb),
+ (ins addr_offset_none:$addr, postidx_reg:$Rm),
+ IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, opc,
+ "\t$Rt, $addr, $Rm", "$addr.base = $base_wb", []> {
+ bits<5> Rm;
+ let Inst{23} = Rm{4};
+ let Inst{22} = 0;
+ let Inst{11-8} = 0;
+ let Inst{3-0} = Rm{3-0};
+ let AsmMatchConverter = "cvtLdExtTWriteBackReg";
+ }
}
+
+defm LDRSBT : AI3ldrT<0b1101, "ldrsbt">;
+defm LDRHT : AI3ldrT<0b1011, "ldrht">;
+defm LDRSHT : AI3ldrT<0b1111, "ldrsht">;
}
// Store
@@ -2156,7 +2195,7 @@ def STRD_POST: AI3stdpo<(outs GPR:$base_wb),
}
} // mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1
-// STRT, STRBT, and STRHT are for disassembly only.
+// STRT, STRBT, and STRHT
def STRTr : AI2stridxT<0, 0, (outs GPR:$Rn_wb),
(ins GPR:$Rt, ldst_so_reg:$addr),
@@ -2201,15 +2240,35 @@ def STRBTi : AI2stridxT<1, 0, (outs GPR:$Rn_wb),
let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
}
-
-def STRHT: AI3sthpo<(outs GPR:$base_wb), (ins GPR:$Rt, addrmode3:$addr),
- StMiscFrm, IIC_iStore_bh_ru,
- "strht", "\t$Rt, $addr", "$addr.base = $base_wb",
- [/* For disassembly only; pattern left blank */]> {
- let Inst{21} = 1; // overwrite
- let AsmMatchConverter = "cvtStWriteBackRegAddrMode3";
+multiclass AI3strT<bits<4> op, string opc> {
+ def i : AI3ldstidxT<op, 0, (outs GPR:$base_wb),
+ (ins GPR:$Rt, addr_offset_none:$addr, postidx_imm8:$offset),
+ IndexModePost, StMiscFrm, IIC_iStore_bh_ru, opc,
+ "\t$Rt, $addr, $offset", "$addr.base = $base_wb", []> {
+ bits<9> offset;
+ let Inst{23} = offset{8};
+ let Inst{22} = 1;
+ let Inst{11-8} = offset{7-4};
+ let Inst{3-0} = offset{3-0};
+ let AsmMatchConverter = "cvtStExtTWriteBackImm";
+ }
+ def r : AI3ldstidxT<op, 0, (outs GPR:$base_wb),
+ (ins GPR:$Rt, addr_offset_none:$addr, postidx_reg:$Rm),
+ IndexModePost, StMiscFrm, IIC_iStore_bh_ru, opc,
+ "\t$Rt, $addr, $Rm", "$addr.base = $base_wb", []> {
+ bits<5> Rm;
+ let Inst{23} = Rm{4};
+ let Inst{22} = 0;
+ let Inst{11-8} = 0;
+ let Inst{3-0} = Rm{3-0};
+ let AsmMatchConverter = "cvtStExtTWriteBackReg";
+ }
}
+
+defm STRHT : AI3strT<0b1011, "strht">;
+
+
//===----------------------------------------------------------------------===//
// Load / store multiple Instructions.
//
@@ -3758,8 +3817,8 @@ def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins addr_offset_none:$addr),
"ldrexb", "\t$Rt, $addr", []>;
def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins addr_offset_none:$addr),
NoItinerary, "ldrexh", "\t$Rt, $addr", []>;
-def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins addr_offset_none:$addr), NoItinerary,
- "ldrex", "\t$Rt, $addr", []>;
+def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins addr_offset_none:$addr),
+ NoItinerary, "ldrex", "\t$Rt, $addr", []>;
let hasExtraDefRegAllocReq = 1 in
def LDREXD: AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2),(ins addr_offset_none:$addr),
NoItinerary, "ldrexd", "\t$Rt, $Rt2, $addr", []>;
@@ -3844,7 +3903,7 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
class ACI<dag oops, dag iops, string opc, string asm,
IndexMode im = IndexModeNone>
: InoP<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
- opc, asm, "", [/* For disassembly only; pattern left blank */]> {
+ opc, asm, "", []> {
let Inst{27-25} = 0b110;
}
@@ -3914,8 +3973,9 @@ multiclass LdStCop<bits<4> op31_28, bit load, dag ops, string opc, string cond>{
}
def L_POST : ACI<(outs),
- !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
- !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr",
+ !con((ins nohash_imm:$cop, nohash_imm:$CRd, addr_offset_none:$addr,
+ i32imm:$offset), ops),
+ !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr, $offset",
IndexModePost> {
let Inst{31-28} = op31_28;
let Inst{24} = 0; // P = 0
@@ -4491,3 +4551,14 @@ def : MnemonicAlias<"srsea", "srsdb">;
def : MnemonicAlias<"srsfd", "srsia">;
def : MnemonicAlias<"srsed", "srsib">;
def : MnemonicAlias<"srs", "srsia">;
+
+// LDRSBT/LDRHT/LDRSHT post-index offset if optional.
+// Note that the write-back output register is a dummy operand for MC (it's
+// only meaningful for codegen), so we just pass zero here.
+// FIXME: tblgen not cooperating with argument conversions.
+//def : InstAlias<"ldrsbt${p} $Rt, $addr",
+// (LDRSBTi GPR:$Rt, GPR:$Rt, addr_offset_none:$addr, 0,pred:$p)>;
+//def : InstAlias<"ldrht${p} $Rt, $addr",
+// (LDRHTi GPR:$Rt, GPR:$Rt, addr_offset_none:$addr, 0, pred:$p)>;
+//def : InstAlias<"ldrsht${p} $Rt, $addr",
+// (LDRSHTi GPR:$Rt, GPR:$Rt, addr_offset_none:$addr, 0, pred:$p)>;
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index bd6d1a0c7d..e0c0317920 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -94,18 +94,9 @@ def t_blxtarget : Operand<i32> {
}
}
-def MemModeRegThumbAsmOperand : AsmOperandClass {
- let Name = "MemModeRegThumb";
- let SuperClasses = [];
-}
-
-def MemModeImmThumbAsmOperand : AsmOperandClass {
- let Name = "MemModeImmThumb";
- let SuperClasses = [];
-}
-
// t_addrmode_rr := reg + reg
//
+def t_addrmode_rr_asm_operand : AsmOperandClass { let Name = "MemThumbRR"; }
def t_addrmode_rr : Operand<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> {
let EncoderMethod = "getThumbAddrModeRegRegOpValue";
@@ -119,22 +110,22 @@ def t_addrmode_rrs1 : Operand<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S1", []> {
let EncoderMethod = "getThumbAddrModeRegRegOpValue";
let PrintMethod = "printThumbAddrModeRROperand";
+ let ParserMatchClass = t_addrmode_rr_asm_operand;
let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
- let ParserMatchClass = MemModeRegThumbAsmOperand;
}
def t_addrmode_rrs2 : Operand<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S2", []> {
let EncoderMethod = "getThumbAddrModeRegRegOpValue";
let PrintMethod = "printThumbAddrModeRROperand";
+ let ParserMatchClass = t_addrmode_rr_asm_operand;
let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
- let ParserMatchClass = MemModeRegThumbAsmOperand;
}
def t_addrmode_rrs4 : Operand<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S4", []> {
let EncoderMethod = "getThumbAddrModeRegRegOpValue";
let PrintMethod = "printThumbAddrModeRROperand";
+ let ParserMatchClass = t_addrmode_rr_asm_operand;
let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
- let ParserMatchClass = MemModeRegThumbAsmOperand;
}
// t_addrmode_is4 := reg + imm5 * 4
@@ -144,7 +135,6 @@ def t_addrmode_is4 : Operand<i32>,
let EncoderMethod = "getAddrModeISOpValue";
let PrintMethod = "printThumbAddrModeImm5S4Operand";
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
- let ParserMatchClass = MemModeImmThumbAsmOperand;
}
// t_addrmode_is2 := reg + imm5 * 2
@@ -154,7 +144,6 @@ def t_addrmode_is2 : Operand<i32>,
let EncoderMethod = "getAddrModeISOpValue";
let PrintMethod = "printThumbAddrModeImm5S2Operand";
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
- let ParserMatchClass = MemModeImmThumbAsmOperand;
}
// t_addrmode_is1 := reg + imm5
@@ -164,7 +153,6 @@ def t_addrmode_is1 : Operand<i32>,
let EncoderMethod = "getAddrModeISOpValue";
let PrintMethod = "printThumbAddrModeImm5S1Operand";
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
- let ParserMatchClass = MemModeImmThumbAsmOperand;
}
// t_addrmode_sp := sp + imm8 * 4
@@ -174,14 +162,12 @@ def t_addrmode_sp : Operand<i32>,
let EncoderMethod = "getAddrModeThumbSPOpValue";
let PrintMethod = "printThumbAddrModeSPOperand";
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
- let ParserMatchClass = MemModeImmThumbAsmOperand;
}
// t_addrmode_pc := <label> => pc + imm8 * 4
//
def t_addrmode_pc : Operand<i32> {
let EncoderMethod = "getAddrModePCOpValue";
- let ParserMatchClass = MemModeImmThumbAsmOperand;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index b4ca828b26..b53ca16c18 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -101,7 +101,6 @@ def t2addrmode_imm12 : Operand<i32>,
let PrintMethod = "printAddrModeImm12Operand";
let EncoderMethod = "getAddrModeImm12OpValue";
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
- let ParserMatchClass = MemMode5AsmOperand;
}
// t2ldrlabel := imm12
@@ -117,12 +116,13 @@ def t2adrlabel : Operand<i32> {
// t2addrmode_imm8 := reg +/- imm8
+def MemImm8OffsetAsmOperand : AsmOperandClass { let Name = "MemImm8Offset"; }
def t2addrmode_imm8 : Operand<i32>,
ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
let PrintMethod = "printT2AddrModeImm8Operand";
let EncoderMethod = "getT2AddrModeImm8OpValue";
+ let ParserMatchClass = MemImm8OffsetAsmOperand;
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
- let ParserMatchClass = MemMode5AsmOperand;
}
def t2am_imm8_offset : Operand<i32>,
@@ -130,7 +130,6 @@ def t2am_imm8_offset : Operand<i32>,
[], [SDNPWantRoot]> {
let PrintMethod = "printT2AddrModeImm8OffsetOperand";
let EncoderMethod = "getT2AddrModeImm8OffsetOpValue";
- let ParserMatchClass = MemMode5AsmOperand;
}
// t2addrmode_imm8s4 := reg +/- (imm8 << 2)
@@ -138,7 +137,6 @@ def t2addrmode_imm8s4 : Operand<i32> {
let PrintMethod = "printT2AddrModeImm8s4Operand";
let EncoderMethod = "getT2AddrModeImm8s4OpValue";
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
- let ParserMatchClass = MemMode5AsmOperand;
}
def t2am_imm8s4_offset : Operand<i32> {
@@ -151,7 +149,6 @@ def t2addrmode_so_reg : Operand<i32>,
let PrintMethod = "printT2AddrModeSoRegOperand";
let EncoderMethod = "getT2AddrModeSORegOpValue";
let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm);
- let ParserMatchClass = MemMode5AsmOperand;
}
// t2addrmode_reg := reg
@@ -161,7 +158,6 @@ def t2addrmode_so_reg : Operand<i32>,
def t2addrmode_reg : Operand<i32> {
let PrintMethod = "printAddrMode7Operand";
let MIOperandInfo = (ops GPR);
- let ParserMatchClass = MemMode7AsmOperand;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 5f12b6150d..bc97b032dc 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -51,24 +51,15 @@ class ARMAsmParser : public MCTargetAsmParser {
bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
- bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &,
- ARMII::AddrMode AddrMode);
+ bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
const MCExpr *applyPrefixToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind Variant);
- bool parseMemoryOffsetReg(bool &Negative,
- bool &OffsetRegShifted,
- enum ARM_AM::ShiftOpc &ShiftType,
- const MCExpr *&ShiftAmount,
- const MCExpr *&Offset,
- bool &OffsetIsReg,
- int &OffsetRegNum,
- SMLoc &E);
- bool parseShift(enum ARM_AM::ShiftOpc &St,
- const MCExpr *&ShiftAmount, SMLoc &E);
+ bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
+ unsigned &ShiftAmount);
bool parseDirectiveWord(unsigned Size, SMLoc L);
bool parseDirectiveThumb(SMLoc L);
bool parseDirectiveThumbFunc(SMLoc L);
@@ -110,10 +101,6 @@ class ARMAsmParser : public MCTargetAsmParser {
SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseMSRMaskOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
- OperandMatchResultTy parseMemMode2Operand(
- SmallVectorImpl<MCParsedAsmOperand*>&);
- OperandMatchResultTy parseMemMode3Operand(
- SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
StringRef Op, int Low, int High);
OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
@@ -126,17 +113,21 @@ class ARMAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
+ OperandMatchResultTy parsePostIdxReg(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*> &);
-
+ bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
bool validateInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
@@ -175,6 +166,7 @@ class ARMOperand : public MCParsedAsmOperand {
Immediate,
MemBarrierOpt,
Memory,
+ PostIndexRegister,
MSRMask,
ProcIFlags,
Register,
@@ -228,23 +220,22 @@ 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.
- const MCExpr *Value; ///< Offset value, when !OffsetIsReg.
- } Offset;
- const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
- enum ARM_AM::ShiftOpc ShiftType; // used when OffsetRegShifted is true
- unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true
- unsigned Preindexed : 1;
- unsigned Postindexed : 1;
- unsigned OffsetIsReg : 1;
- unsigned Negative : 1; // only used when OffsetIsReg is true
- unsigned Writeback : 1;
+ // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
+ // was specified.
+ const MCConstantExpr *OffsetImm; // Offset immediate value
+ unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
+ ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
+ unsigned ShiftValue; // shift for OffsetReg.
+ unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
} Mem;
struct {
+ unsigned RegNum;
+ unsigned Imm;
+ } PostIdxReg;
+
+ struct {
bool isASR;
unsigned Imm;
} ShifterImm;
@@ -303,6 +294,9 @@ public:
case Memory:
Mem = o.Mem;
break;
+ case PostIndexRegister:
+ PostIdxReg = o.PostIdxReg;
+ break;
case MSRMask:
MMask = o.MMask;
break;
@@ -378,42 +372,6 @@ public:
return MMask.Val;
}
- /// @name Memory Operand Accessors
- /// @{
- ARMII::AddrMode getMemAddrMode() const {
- return Mem.AddrMode;
- }
- unsigned getMemBaseRegNum() const {
- return Mem.BaseRegNum;
- }
- unsigned getMemOffsetRegNum() const {
- assert(Mem.OffsetIsReg && "Invalid access!");
- return Mem.Offset.RegNum;
- }
- const MCExpr *getMemOffset() const {
- assert(!Mem.OffsetIsReg && "Invalid access!");
- return Mem.Offset.Value;
- }
- unsigned getMemOffsetRegShifted() const {
- assert(Mem.OffsetIsReg && "Invalid access!");
- return Mem.OffsetRegShifted;
- }
- const MCExpr *getMemShiftAmount() const {
- assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!");
- return Mem.ShiftAmount;
- }
- enum ARM_AM::ShiftOpc getMemShiftType() const {
- assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!");
- return Mem.ShiftType;
- }
- bool getMemPreindexed() const { return Mem.Preindexed; }
- bool getMemPostindexed() const { return Mem.Postindexed; }
- bool getMemOffsetIsReg() const { return Mem.OffsetIsReg; }
- bool getMemNegative() const { return Mem.Negative; }
- bool getMemWriteback() const { return Mem.Writeback; }
-
- /// @}
-
bool isCoprocNum() const { return Kind == CoprocNum; }
bool isCoprocReg() const { return Kind == CoprocReg; }
bool isCondCode() const { return Kind == CondCode; }
@@ -540,101 +498,76 @@ public:
bool isToken() const { return Kind == Token; }
bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
bool isMemory() const { return Kind == Memory; }
+ bool isPostIdxReg() const { return Kind == PostIndexRegister; }
bool isShifterImm() const { return Kind == ShifterImmediate; }
bool isRegShiftedReg() const { return Kind == ShiftedRegister; }
bool isRegShiftedImm() const { return Kind == ShiftedImmediate; }
bool isRotImm() const { return Kind == RotateImmediate; }
bool isBitfield() const { return Kind == BitfieldDescriptor; }
- 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)
+ bool isMemNoOffset() const {
+ if (Kind != Memory)
return false;
-
- return true;
+ // No offset of any kind.
+ return Mem.OffsetRegNum == 0 && Mem.OffsetImm == 0;
}
- bool isMemMode3() const {
- if (getMemAddrMode() != ARMII::AddrMode3)
+ bool isAddrMode2() const {
+ if (Kind != Memory)
return false;
-
- if (getMemOffsetIsReg()) {
- if (getMemOffsetRegShifted())
- return false; // No shift with offset reg allowed
- return true;
- }
-
- if (getMemNegative() &&
- !(getMemPostindexed() || getMemPreindexed()))
+ // Check for register offset.
+ if (Mem.OffsetRegNum) return true;
+ // Immediate offset in range [-4095, 4095].
+ if (!Mem.OffsetImm) return true;
+ int64_t Val = Mem.OffsetImm->getValue();
+ return Val > -4096 && Val < 4096;
+ }
+ bool isAddrMode5() const {
+ if (Kind != Memory)
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)
+ // Check for register offset.
+ if (Mem.OffsetRegNum) return false;
+ // Immediate offset in range [-1020, 1020] and a multiple of 4.
+ if (!Mem.OffsetImm) return true;
+ int64_t Val = Mem.OffsetImm->getValue();
+ return Val >= -1020 && Val <= 1020 && ((Val & 3) == 0);
+ }
+ bool isMemRegOffset() const {
+ if (Kind != Memory || !Mem.OffsetRegNum)
return false;
-
return true;
}
- bool isMemMode5() const {
- if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||
- getMemNegative())
+ bool isMemThumbRR() const {
+ // Thumb reg+reg addressing is simple. Just two registers, a base and
+ // an offset. No shifts, negations or any other complicating factors.
+ if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative ||
+ Mem.ShiftType != ARM_AM::no_shift)
return false;
-
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
- if (!CE) return false;
-
- // The offset must be a multiple of 4 in the range 0-1020.
- int64_t Value = CE->getValue();
- return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
- }
- bool isMemMode7() const {
- if (!isMemory() ||
- getMemPreindexed() ||
- getMemPostindexed() ||
- getMemOffsetIsReg() ||
- getMemNegative() ||
- getMemWriteback())
- return false;
-
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
- if (!CE) return false;
-
- if (CE->getValue())
- return false;
-
return true;
}
- bool isMemModeRegThumb() const {
- if (!isMemory() || !getMemOffsetIsReg() || getMemWriteback())
+ bool isMemImm8Offset() const {
+ if (Kind != Memory || Mem.OffsetRegNum != 0)
return false;