mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-25 04:39:51 +00:00
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
This commit is contained in:
parent
762797d1af
commit
7ce057983e
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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)>;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -127,7 +127,7 @@ static unsigned decodeARMInstruction(uint32_t &insn) {
|
||||
case 2:
|
||||
switch (slice(insn, 7, 4)) {
|
||||
case 11:
|
||||
return ARM::STRHT;
|
||||
return slice(insn, 22, 22) ? ARM::STRHTi : ARM::STRHTr;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
@ -135,11 +135,11 @@ static unsigned decodeARMInstruction(uint32_t &insn) {
|
||||
case 3:
|
||||
switch (slice(insn, 7, 4)) {
|
||||
case 11:
|
||||
return ARM::LDRHT;
|
||||
return slice(insn, 22, 22) ? ARM::LDRHTi : ARM::LDRHTr;
|
||||
case 13:
|
||||
return ARM::LDRSBT;
|
||||
return slice(insn, 22, 22) ? ARM::LDRSBTi : ARM::LDRSBTr;
|
||||
case 15:
|
||||
return ARM::LDRSHT;
|
||||
return slice(insn, 22, 22) ? ARM::LDRSHTi : ARM::LDRSHTr;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
|
@ -1393,7 +1393,7 @@ static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
|
||||
if (Opcode == ARM::LDRBi12 || Opcode == ARM::LDRi12 ||
|
||||
Opcode == ARM::STRBi12 || Opcode == ARM::STRi12) {
|
||||
// Disassemble the 12-bit immediate offset, which is the second operand in
|
||||
// $addrmode_imm12 => (ops GPR:$base, i32imm:$offsimm).
|
||||
// $addrmode_imm12 => (ops GPR:$base, i32imm:$offsimm).
|
||||
int Offset = AddrOpcode == ARM_AM::add ? 1 * Imm12 : -1 * Imm12;
|
||||
MI.addOperand(MCOperand::CreateImm(Offset));
|
||||
} else {
|
||||
@ -1512,34 +1512,43 @@ static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
|
||||
|
||||
// For reg/reg form, base reg is followed by +/- reg.
|
||||
// For immediate form, it is followed by +/- imm8.
|
||||
// See also ARMAddressingModes.h (Addressing Mode #3).
|
||||
if (OpIdx + 1 >= NumOps)
|
||||
return false;
|
||||
|
||||
assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) &&
|
||||
(OpInfo[OpIdx+1].RegClass < 0) &&
|
||||
"Expect 1 reg operand followed by 1 imm operand");
|
||||
|
||||
ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
|
||||
unsigned IndexMode =
|
||||
(MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
|
||||
(MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
|
||||
ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
|
||||
if (getAM3IBit(insn) == 1) {
|
||||
MI.addOperand(MCOperand::CreateReg(0));
|
||||
// FIXME: Conditional while in the midst of refactoring addrmode3. Will
|
||||
// go away entirely when the rest are converted.
|
||||
if (Opcode != ARM::STRHTi && Opcode != ARM::LDRSBTi &&
|
||||
Opcode != ARM::LDRHTi && Opcode != ARM::LDRSHTi) {
|
||||
MI.addOperand(MCOperand::CreateReg(0));
|
||||
++OpIdx;
|
||||
}
|
||||
|
||||
// Disassemble the 8-bit immediate offset.
|
||||
// Disassemble the 8-bit immediate offset (postidx_imm8).
|
||||
unsigned Imm4H = (insn >> ARMII::ImmHiShift) & 0xF;
|
||||
unsigned Imm4L = insn & 0xF;
|
||||
unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L,
|
||||
IndexMode);
|
||||
unsigned Offset;
|
||||
// FIXME: Remove the 'else' once done w/ addrmode3 refactor.
|
||||
if (Opcode == ARM::STRHTi || Opcode == ARM::LDRSBTi ||
|
||||
Opcode == ARM::LDRHTi || Opcode == ARM::LDRSHTi)
|
||||
Offset = (Imm4H << 4) | Imm4L | (getUBit(insn) << 8);
|
||||
else
|
||||
Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L,
|
||||
IndexMode);
|
||||
|
||||
MI.addOperand(MCOperand::CreateImm(Offset));
|
||||
++OpIdx;
|
||||
} else {
|
||||
// Disassemble the offset reg (Rm).
|
||||
unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0);
|
||||
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
|
||||
decodeRm(insn))));
|
||||
unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0, IndexMode);
|
||||
MI.addOperand(MCOperand::CreateImm(Offset));
|
||||
OpIdx += 2;
|
||||
}
|
||||
OpIdx += 2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
|
||||
O << '[' << getRegisterName(MO1.getReg());
|
||||
|
||||
if (MO2.getReg()) {
|
||||
O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
|
||||
O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
|
||||
<< getRegisterName(MO2.getReg()) << ']';
|
||||
return;
|
||||
}
|
||||
@ -363,8 +363,8 @@ void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
if (MO1.getReg()) {
|
||||
O << (char)ARM_AM::getAM3Op(MO2.getImm())
|
||||
<< getRegisterName(MO1.getReg());
|
||||
O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
|
||||
<< getRegisterName(MO1.getReg());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -374,6 +374,14 @@ void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
|
||||
<< ImmOffs;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI,
|
||||
unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO = MI->getOperand(OpNum);
|
||||
unsigned Imm = MO.getImm();
|
||||
O << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
|
||||
|
@ -49,11 +49,12 @@ public:
|
||||
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 printAM3PostIndexOp(const MCInst *MI, unsigned Op, raw_ostream &O);
|
||||
void printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,raw_ostream &O);
|
||||
void printPostIdxImm8Operand(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);
|
||||
|
@ -31,7 +31,8 @@ namespace ARM_AM {
|
||||
};
|
||||
|
||||
enum AddrOpc {
|
||||
add = '+', sub = '-'
|
||||
sub = 0,
|
||||
add
|
||||
};
|
||||
|
||||
static inline const char *getAddrOpcStr(AddrOpc Op) {
|
||||
|
@ -184,6 +184,10 @@ public:
|
||||
uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
/// getPostIdxRegOpValue - Return encoding for postidx_reg operands.
|
||||
uint32_t getPostIdxRegOpValue(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;
|
||||
@ -801,6 +805,18 @@ getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
return Binary | (isAdd << 12) | (isReg << 13);
|
||||
}
|
||||
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
// {4} isAdd
|
||||
// {3-0} Rm
|
||||
const MCOperand &MO = MI.getOperand(OpIdx);
|
||||
const MCOperand &MO1 = MI.getOperand(OpIdx+1);
|
||||
unsigned Imm = MO1.getImm();
|
||||
bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
|
||||
return getARMRegisterNumbering(MO.getReg()) | (isAdd << 4);
|
||||
}
|
||||
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
|
@ -1,12 +1,12 @@
|
||||
@ 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], 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], 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], 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], r2 @ encoding: [0xb2,0x10,0xa0,0xe0]
|
||||
@ CHECK: strht r1, [r0], #4 @ encoding: [0xb4,0x10,0xe0,0xe0]
|
||||
ldrsbt r1, [r0], r2
|
||||
ldrsbt r1, [r0], #4
|
||||
|
@ -1,6 +1,8 @@
|
||||
@ RUN: llvm-mc -triple thumbv7-unknown-unknown -show-encoding %s > %t
|
||||
@ RUN: FileCheck < %t %s
|
||||
|
||||
@ FIXME: This test is completely bogus. Replace it with real tests.
|
||||
@ XFAIL: *
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
|
@ -45,8 +45,11 @@
|
||||
# CHECK: isb
|
||||
0x6f 0xf0 0x7f 0xf5
|
||||
|
||||
# CHECK: ldclvc p5, cr15, [r8], #-0
|
||||
0x00 0xf5 0x78 0x7c
|
||||
# FIXME: LDC encoding information is incorrect. Re-enable this along with more
|
||||
# robust testing for other values when we get it fleshed out and working
|
||||
# properly.
|
||||
# CHECKx: ldclvc p5, cr15, [r8], #-0
|
||||
#0x00 0xf5 0x78 0x7c
|
||||
|
||||
# CHECK: ldr r0, [r2], #15
|
||||
0x0f 0x00 0x92 0xe4
|
||||
|
@ -613,6 +613,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||
IMM("shr_imm32");
|
||||
IMM("shr_imm64");
|
||||
IMM("t2ldrlabel");
|
||||
IMM("postidx_imm8");
|
||||
|
||||
MISC("brtarget", "kOperandTypeARMBranchTarget"); // ?
|
||||
MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ?
|
||||
@ -639,9 +640,10 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||
MISC("it_pred", "kOperandTypeARMPredicate"); // I
|
||||
MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I
|
||||
MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I
|
||||
MISC("postidx_reg", "kOperandTypeARMAddrMode3Offset"); // R, I
|
||||
MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I
|
||||
MISC("am2offset_reg", "kOperandTypeARMAddrMode2Offset"); // R, I
|
||||
MISC("am2offset_imm", "kOperandTypeARMAddrMode2Offset"); // R, I
|
||||
MISC("am2offset_reg", "kOperandTypeARMAddrMode2Offset"); // R, I
|
||||
MISC("am2offset_imm", "kOperandTypeARMAddrMode2Offset"); // R, I
|
||||
MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I
|
||||
MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I
|
||||
MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I
|
||||
|
Loading…
Reference in New Issue
Block a user