forked from OSchip/llvm-project
[ARC] Add more load/store variants.
On ARC ISA, general format of load instruction is this: LD<zz><.x><.aa><.di> a, [b,c] And general format of store is this: ST<zz><.aa><.di> c, [b,s9] Where: <zz> is data size field and can be one of <empty> (bits 00) - Word (32-bit), default behavior B (bits 01) - Byte H (bits 10) - Half-word (16-bit) <.x> is data extend mode: <empty> (bit 0) - If size is not Word(32-bit), then data is zero extended X (bit 1) - If size is not Word(32-bit), then data is sign extended <.aa> is address write-back mode: <empty> (bits 00) - no write-back .AW (bits 01) - Preincrement, base register updated pre memory transaction .AB (bits 10) - Postincrement, base register updated post memory transaction <.di> is cache bypass mode: <empty> (bit 0) - Cached memory access, default mode .DI (bit 1) - Non-cached data memory access This patch adds these load/store instruction variants to the ARC backend. Patch By Denis Antrushin! <denis@synopsys.com> Differential Revision: https://reviews.llvm.org/D58980 llvm-svn: 356200
This commit is contained in:
parent
51fe000d8a
commit
9fd1848823
|
@ -55,6 +55,44 @@ def GPR32Reduced : Operand<iAny> {
|
|||
let DecoderMethod = "DecodeGBR32ShortRegister";
|
||||
}
|
||||
|
||||
// Helper classes for load/store instructions
|
||||
class DataSizeMode<bits<2> mode, string instSfx, string asmSfx> {
|
||||
bits<2> Value = mode;
|
||||
string InstSuffix = instSfx;
|
||||
string AsmSuffix = asmSfx;
|
||||
}
|
||||
class ExtMode<bit mode, string instSfx, string asmSfx> {
|
||||
bit Value = mode;
|
||||
string InstSuffix = instSfx;
|
||||
string AsmSuffix = asmSfx;
|
||||
}
|
||||
|
||||
class AddrMode<bits<2> mode, string instSfx, string asmSfx> {
|
||||
bits<2> Value = mode;
|
||||
string InstSuffix = instSfx;
|
||||
string AsmSuffix = asmSfx;
|
||||
}
|
||||
|
||||
class CacheMode<bit mode, string instSfx, string asmSfx> {
|
||||
bit Value = mode;
|
||||
string InstSuffix = instSfx;
|
||||
string AsmSuffix = asmSfx;
|
||||
}
|
||||
|
||||
def ByteSM : DataSizeMode<0b01, "B", "b">;
|
||||
def HalfSM : DataSizeMode<0b10, "H", "h">;
|
||||
def WordSM : DataSizeMode<0b00, "", "">;
|
||||
|
||||
def NoEM : ExtMode<0, "", "">;
|
||||
def SignedEM : ExtMode<1, "_X", ".x">;
|
||||
|
||||
def NoAM : AddrMode<0b00, "", "">;
|
||||
def PreIncAM : AddrMode<0b01, "_AW", ".aw">;
|
||||
def PostIncAM : AddrMode<0b10, "_AB", ".ab">;
|
||||
|
||||
def NoCC : CacheMode<0b0, "", "">;
|
||||
def UncachedCC : CacheMode<0b1, "_DI", ".di">;
|
||||
|
||||
class InstARC<int sz, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: Instruction, Encoding64 {
|
||||
|
||||
|
@ -64,6 +102,18 @@ class InstARC<int sz, dag outs, dag ins, string asmstr, list<dag> pattern>
|
|||
let AsmString = asmstr;
|
||||
let Pattern = pattern;
|
||||
let Size = sz;
|
||||
|
||||
// Load/Store instruction properties
|
||||
DataSizeMode ZZ = WordSM;
|
||||
ExtMode X = NoEM;
|
||||
AddrMode AA = NoAM;
|
||||
CacheMode DI = NoCC;
|
||||
|
||||
// Field used for relation models
|
||||
string BaseOpcode = "";
|
||||
|
||||
//TSFlags
|
||||
let TSFlags{1-0} = AA.Value;
|
||||
}
|
||||
|
||||
// ARC pseudo instructions format
|
||||
|
@ -354,6 +404,8 @@ class F32_LD_RS9<bit x, bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
|
|||
let Inst{8-7} = zz;
|
||||
let Inst{6} = x;
|
||||
let Inst{5-0} = A;
|
||||
|
||||
let BaseOpcode = "ld_rs9";
|
||||
}
|
||||
|
||||
class F32_LD_ADDR<bit x, bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
|
||||
|
@ -363,6 +415,8 @@ class F32_LD_ADDR<bit x, bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
|
|||
|
||||
let B = addr{14-9};
|
||||
let S9 = addr{8-0};
|
||||
|
||||
let BaseOpcode = "ld_rs9";
|
||||
}
|
||||
|
||||
|
||||
|
@ -387,6 +441,8 @@ class F32_LD_LIMM<bit x, bit di, bits<2> zz, dag outs, dag ins,
|
|||
let Inst{6} = x;
|
||||
let Inst{5-0} = A;
|
||||
let DecoderMethod = "DecodeLdLImmInstruction";
|
||||
|
||||
let BaseOpcode = "ld_limm";
|
||||
}
|
||||
|
||||
// Register + LImm load. The 32-bit immediate address is in Inst[63-32].
|
||||
|
@ -415,6 +471,8 @@ class F32_LD_RLIMM<bit x, bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
|
|||
let Inst{11-6} = LImmReg;
|
||||
let Inst{5-0} = A;
|
||||
let DecoderMethod = "DecodeLdRLImmInstruction";
|
||||
|
||||
let BaseOpcode = "ld_rlimm";
|
||||
}
|
||||
|
||||
// Register + S9 Store. (B + S9)
|
||||
|
@ -437,6 +495,8 @@ class F32_ST_RS9<bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
|
|||
let Inst{4-3} = aa;
|
||||
let Inst{2-1} = zz;
|
||||
let Inst{0} = 0;
|
||||
|
||||
let BaseOpcode = "st_rs9";
|
||||
}
|
||||
|
||||
class F32_ST_ADDR<bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
|
||||
|
@ -446,6 +506,8 @@ class F32_ST_ADDR<bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
|
|||
|
||||
let B = addr{14-9};
|
||||
let S9 = addr{8-0};
|
||||
|
||||
let BaseOpcode = "st_rs9";
|
||||
}
|
||||
|
||||
// LImm Store.
|
||||
|
@ -469,6 +531,8 @@ class F32_ST_LIMM<bit di, bits<2> zz, dag outs, dag ins,
|
|||
let Inst{2-1} = zz;
|
||||
let Inst{0} = 0;
|
||||
let DecoderMethod = "DecodeStLImmInstruction";
|
||||
|
||||
let BaseOpcode = "st_limm";
|
||||
}
|
||||
|
||||
// Compact Move/Load.
|
||||
|
|
|
@ -27,6 +27,19 @@ using namespace llvm;
|
|||
#include "ARCGenInstrInfo.inc"
|
||||
|
||||
#define DEBUG_TYPE "arc-inst-info"
|
||||
|
||||
enum AddrIncType {
|
||||
NoAddInc = 0,
|
||||
PreInc = 1,
|
||||
PostInc = 2,
|
||||
Scaled = 3
|
||||
};
|
||||
|
||||
enum TSFlagsConstants {
|
||||
TSF_AddrModeOff = 0,
|
||||
TSF_AddModeMask = 3
|
||||
};
|
||||
|
||||
// Pin the vtable to this file.
|
||||
void ARCInstrInfo::anchor() {}
|
||||
|
||||
|
@ -395,3 +408,35 @@ unsigned ARCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
|
|||
}
|
||||
return MI.getDesc().getSize();
|
||||
}
|
||||
|
||||
bool ARCInstrInfo::isPostIncrement(const MachineInstr &MI) const {
|
||||
const MCInstrDesc &MID = MI.getDesc();
|
||||
const uint64_t F = MID.TSFlags;
|
||||
return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PostInc;
|
||||
}
|
||||
|
||||
bool ARCInstrInfo::isPreIncrement(const MachineInstr &MI) const {
|
||||
const MCInstrDesc &MID = MI.getDesc();
|
||||
const uint64_t F = MID.TSFlags;
|
||||
return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PreInc;
|
||||
}
|
||||
|
||||
bool ARCInstrInfo::getBaseAndOffsetPosition(const MachineInstr &MI,
|
||||
unsigned &BasePos,
|
||||
unsigned &OffsetPos) const {
|
||||
if (!MI.mayLoad() && !MI.mayStore())
|
||||
return false;
|
||||
|
||||
BasePos = 1;
|
||||
OffsetPos = 2;
|
||||
|
||||
if (isPostIncrement(MI) || isPreIncrement(MI)) {
|
||||
BasePos++;
|
||||
OffsetPos++;
|
||||
}
|
||||
|
||||
if (!MI.getOperand(BasePos).isReg() || !MI.getOperand(OffsetPos).isImm())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -81,6 +81,16 @@ public:
|
|||
bool
|
||||
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
|
||||
|
||||
|
||||
bool isPostIncrement(const MachineInstr &MI) const override;
|
||||
|
||||
// ARC-specific
|
||||
bool isPreIncrement(const MachineInstr &MI) const;
|
||||
|
||||
virtual bool getBaseAndOffsetPosition(const MachineInstr &MI,
|
||||
unsigned &BasePos,
|
||||
unsigned &OffsetPos) const override;
|
||||
|
||||
// Emit code before MBBI to load immediate value into physical register Reg.
|
||||
// Returns an iterator to the new instruction.
|
||||
MachineBasicBlock::iterator loadImmediate(MachineBasicBlock &MBB,
|
||||
|
|
|
@ -787,50 +787,47 @@ let isReturn = 1, isTerminator = 1 in {
|
|||
// Load/Store instructions.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Filter class for load/store mappings
|
||||
class ArcLdStRel;
|
||||
|
||||
// Load instruction variants:
|
||||
// Control bits: x, aa, di, zz
|
||||
// x - sign extend.
|
||||
// aa - incrementing mode. (N/A for LIMM).
|
||||
// di - uncached.
|
||||
// zz - data size.
|
||||
multiclass ArcLdInst<bits<2> zz, string asmop> {
|
||||
let mayLoad = 1 in {
|
||||
def _rs9 : F32_LD_ADDR<0, 0b00, 0, zz,
|
||||
(outs GPR32:$A), (ins MEMrs9:$addr),
|
||||
!strconcat(asmop, "\t$A, [$addr]"), []>;
|
||||
multiclass ArcLdInst<DataSizeMode zz, ExtMode x, CacheMode di, string asmop> {
|
||||
let mayLoad = 1, ZZ = zz, X = x, DI = di in {
|
||||
def _rs9: F32_LD_ADDR<x.Value, NoAM.Value, di.Value, zz.Value,
|
||||
(outs GPR32:$A), (ins MEMrs9:$addr),
|
||||
!strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
|
||||
|
||||
def _limm : F32_LD_LIMM<0, 0, zz,
|
||||
(outs GPR32:$A), (ins MEMii:$addr),
|
||||
!strconcat(asmop, "\t$A, [$addr]"), []>;
|
||||
def _limm: F32_LD_LIMM<x.Value, di.Value, zz.Value,
|
||||
(outs GPR32:$A), (ins MEMii:$addr),
|
||||
!strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
|
||||
|
||||
def _rlimm : F32_LD_RLIMM<0, 0b00, 0, zz,
|
||||
(outs GPR32:$A), (ins MEMrlimm:$addr),
|
||||
!strconcat(asmop, "\t$A, [$addr]"), []>;
|
||||
def _rlimm: F32_LD_RLIMM<x.Value, NoAM.Value, di.Value, zz.Value,
|
||||
(outs GPR32:$A), (ins MEMrlimm:$addr),
|
||||
!strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
|
||||
|
||||
def _X_rs9 : F32_LD_ADDR<1, 0b00, 0, zz,
|
||||
(outs GPR32:$A), (ins MEMrs9:$addr),
|
||||
!strconcat(asmop, ".x\t$A, [$addr]"), []>;
|
||||
|
||||
def _X_limm : F32_LD_LIMM<1, 0, zz,
|
||||
(outs GPR32:$A), (ins MEMii:$addr),
|
||||
!strconcat(asmop, ".x\t$A, [$addr]"), []>;
|
||||
|
||||
def _X_rlimm : F32_LD_RLIMM<1, 0b00, 0, zz,
|
||||
(outs GPR32:$A), (ins MEMrlimm:$addr),
|
||||
!strconcat(asmop, ".x\t$A, [$addr]"), []>;
|
||||
|
||||
def _AB_rs9 : F32_LD_RS9<0, 0b10, 0, zz,
|
||||
(outs GPR32:$addrout, GPR32:$A),
|
||||
(ins GPR32:$B, immS<9>:$S9),
|
||||
!strconcat(asmop, ".ab\t$A, [$B,$S9]"), []>
|
||||
{ let Constraints = "$addrout = $B"; }
|
||||
foreach aa = [PreIncAM, PostIncAM] in {
|
||||
def aa.InstSuffix#_rs9: F32_LD_RS9<x.Value, aa.Value, di.Value, zz.Value,
|
||||
(outs GPR32:$A, GPR32:$addrout),
|
||||
(ins GPR32:$B, immS<9>:$S9),
|
||||
asmop#aa.AsmSuffix#"\t$A, [$B,$S9]", []>, ArcLdStRel
|
||||
{ let Constraints = "$addrout = $B"; let AA = aa; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach di = [NoCC, UncachedCC] in {
|
||||
defm LD#di.InstSuffix : ArcLdInst<WordSM, NoEM, di, "ld"#di.AsmSuffix>;
|
||||
foreach zz = [ByteSM, HalfSM] in {
|
||||
foreach x = [NoEM, SignedEM] in {
|
||||
defm LD#zz.InstSuffix#x.InstSuffix#di.InstSuffix : ArcLdInst<zz, x, di, "ld"#zz.AsmSuffix#x.AsmSuffix#di.AsmSuffix>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load instruction definitions.
|
||||
defm LD : ArcLdInst<0b00, "ld">;
|
||||
defm LDH : ArcLdInst<0b10, "ldh">;
|
||||
defm LDB : ArcLdInst<0b01, "ldb">;
|
||||
|
||||
// Load instruction patterns.
|
||||
// 32-bit loads.
|
||||
|
@ -872,25 +869,32 @@ def : Pat<(sextloadi8 AddrModeS9:$addr),(LDB_X_rs9 AddrModeS9:$addr)>;
|
|||
// aa - incrementing mode. (N/A for LIMM).
|
||||
// di - uncached.
|
||||
// zz - data size.
|
||||
multiclass ArcStInst<bits<2> zz, string asmop> {
|
||||
let mayStore = 1 in {
|
||||
def _rs9 : F32_ST_ADDR<0b00, 0, zz, (outs), (ins GPR32:$C, MEMrs9:$addr),
|
||||
!strconcat(asmop, "\t$C, [$addr]"), []>;
|
||||
multiclass ArcStInst<DataSizeMode zz, CacheMode di, string asmop> {
|
||||
let mayStore = 1, ZZ = zz, DI = di in {
|
||||
def _rs9: F32_ST_ADDR<NoAM.Value, di.Value, zz.Value,
|
||||
(outs), (ins GPR32:$C, MEMrs9:$addr),
|
||||
!strconcat(asmop, "\t$C, [$addr]"), []>, ArcLdStRel;
|
||||
|
||||
def _limm : F32_ST_LIMM<0, zz, (outs), (ins GPR32:$C, MEMii:$addr),
|
||||
!strconcat(asmop, "\t$C, [$addr]"), []>;
|
||||
def _limm: F32_ST_LIMM<di.Value, zz.Value,
|
||||
(outs), (ins GPR32:$C, MEMii:$addr),
|
||||
!strconcat(asmop, "\t$C, [$addr]"), []>, ArcLdStRel;
|
||||
|
||||
def _AW_rs9 : F32_ST_RS9<0b01, 0, zz, (outs GPR32:$addrout),
|
||||
(ins GPR32:$C, GPR32:$B, immS<9>:$S9),
|
||||
!strconcat(asmop, ".aw\t$C, [$B,$S9]"), []>
|
||||
{ let Constraints = "$addrout = $B"; }
|
||||
|
||||
foreach aa = [PreIncAM, PostIncAM] in {
|
||||
def aa.InstSuffix#_rs9: F32_ST_RS9<aa.Value, di.Value, zz.Value,
|
||||
(outs GPR32:$addrout),
|
||||
(ins GPR32:$C, GPR32:$B, immS<9>:$S9),
|
||||
asmop#aa.AsmSuffix#"\t$C, [$B,$S9]", []>, ArcLdStRel
|
||||
{ let Constraints = "$addrout = $B"; let AA = aa; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store instruction definitions.
|
||||
defm ST : ArcStInst<0b00, "st">;
|
||||
defm STH : ArcStInst<0b10, "sth">;
|
||||
defm STB : ArcStInst<0b01, "stb">;
|
||||
foreach di = [NoCC, UncachedCC] in {
|
||||
foreach zz = [ByteSM, HalfSM, WordSM] in {
|
||||
defm ST#zz.InstSuffix#di.InstSuffix : ArcStInst<zz, di, "st"#zz.AsmSuffix#di.AsmSuffix>;
|
||||
}
|
||||
}
|
||||
|
||||
// Store instruction patterns.
|
||||
// 32-bit stores
|
||||
|
@ -911,3 +915,10 @@ def : Pat<(truncstorei8 i32:$C, AddrModeS9:$addr),
|
|||
def : Pat<(truncstorei8 i32:$C, AddrModeImm:$addr),
|
||||
(STB_limm i32:$C, AddrModeImm:$addr)>;
|
||||
|
||||
def getPostIncOpcode : InstrMapping {
|
||||
let FilterClass = "ArcLdStRel";
|
||||
let RowFields = [ "BaseOpcode", "ZZ", "DI", "X"];
|
||||
let ColFields = [ "AA" ];
|
||||
let KeyCol = [ "NoAM" ];
|
||||
let ValueCols = [["PostIncAM"]];
|
||||
}
|
||||
|
|
|
@ -45,3 +45,50 @@
|
|||
# CHECK: st %r7, [63920]
|
||||
0x00 0x1e 0xc0 0x71 0x00 0x00 0xb0 0xf9
|
||||
|
||||
# CHECK: ldb.ab %r1, [%r0,1]
|
||||
0x01 0x10 0x81 0x04
|
||||
|
||||
# CHECK: stb.ab %r2, [%r0,1]
|
||||
0x01 0x18 0x92 0x00
|
||||
|
||||
# CHECK: ldh.ab %r3, [%r0,12]
|
||||
0x0C 0x10 0x03 0x05
|
||||
|
||||
# CHECK: sth.ab %r4, [%r0,18]
|
||||
0x12 0x18 0x14 0x01
|
||||
|
||||
# CHECK: ld.ab %r5, [%r2,128]
|
||||
0x80 0x12 0x05 0x04
|
||||
|
||||
# CHECK: st.ab %r6, [%r2,64]
|
||||
0x40 0x1A 0x90 0x01
|
||||
|
||||
# CHECK: ldb.aw %r7, [%r0,1]
|
||||
0x01 0x10 0x87 0x02
|
||||
|
||||
# CHECK: stb.aw %r8, [%r0,1]
|
||||
0x01 0x18 0x0A 0x02
|
||||
|
||||
# CHECK: ldh.aw %r3, [%r0,12]
|
||||
0x0C 0x10 0x03 0x03
|
||||
|
||||
# CHECK: sth.aw %r3, [%r0,18]
|
||||
0x12 0x18 0xCC 0x00
|
||||
|
||||
# CHECK: ld.aw %r6, [%r2,128]
|
||||
0x80 0x12 0x06 0x02
|
||||
|
||||
# CHECK: st.aw %r6, [%r2,64]
|
||||
0x40 0x1A 0x88 0x01
|
||||
|
||||
# CHECK: ld.aw %r6, [%r2,128]
|
||||
0x80 0x12 0x06 0x02
|
||||
|
||||
# CHECK: st.aw %r6, [%r2,64]
|
||||
0x40 0x1A 0x88 0x01
|
||||
|
||||
# CHECK: ldb.x.di.aw %r0, [%r8,8]
|
||||
0x08 0x10 0xC0 0x1A
|
||||
|
||||
# CHECK: stb.di.ab %r0, [%r9,64]
|
||||
0x40 0x19 0x32 0x10
|
||||
|
|
Loading…
Reference in New Issue