Skip to content

Commit 9fd1848

Browse files
committed
[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! <[email protected]> Differential Revision: https://reviews.llvm.org/D58980 llvm-svn: 356200
1 parent 51fe000 commit 9fd1848

File tree

5 files changed

+229
-52
lines changed

5 files changed

+229
-52
lines changed

llvm/lib/Target/ARC/ARCInstrFormats.td

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,44 @@ def GPR32Reduced : Operand<iAny> {
5555
let DecoderMethod = "DecodeGBR32ShortRegister";
5656
}
5757

58+
// Helper classes for load/store instructions
59+
class DataSizeMode<bits<2> mode, string instSfx, string asmSfx> {
60+
bits<2> Value = mode;
61+
string InstSuffix = instSfx;
62+
string AsmSuffix = asmSfx;
63+
}
64+
class ExtMode<bit mode, string instSfx, string asmSfx> {
65+
bit Value = mode;
66+
string InstSuffix = instSfx;
67+
string AsmSuffix = asmSfx;
68+
}
69+
70+
class AddrMode<bits<2> mode, string instSfx, string asmSfx> {
71+
bits<2> Value = mode;
72+
string InstSuffix = instSfx;
73+
string AsmSuffix = asmSfx;
74+
}
75+
76+
class CacheMode<bit mode, string instSfx, string asmSfx> {
77+
bit Value = mode;
78+
string InstSuffix = instSfx;
79+
string AsmSuffix = asmSfx;
80+
}
81+
82+
def ByteSM : DataSizeMode<0b01, "B", "b">;
83+
def HalfSM : DataSizeMode<0b10, "H", "h">;
84+
def WordSM : DataSizeMode<0b00, "", "">;
85+
86+
def NoEM : ExtMode<0, "", "">;
87+
def SignedEM : ExtMode<1, "_X", ".x">;
88+
89+
def NoAM : AddrMode<0b00, "", "">;
90+
def PreIncAM : AddrMode<0b01, "_AW", ".aw">;
91+
def PostIncAM : AddrMode<0b10, "_AB", ".ab">;
92+
93+
def NoCC : CacheMode<0b0, "", "">;
94+
def UncachedCC : CacheMode<0b1, "_DI", ".di">;
95+
5896
class InstARC<int sz, dag outs, dag ins, string asmstr, list<dag> pattern>
5997
: Instruction, Encoding64 {
6098

@@ -64,6 +102,18 @@ class InstARC<int sz, dag outs, dag ins, string asmstr, list<dag> pattern>
64102
let AsmString = asmstr;
65103
let Pattern = pattern;
66104
let Size = sz;
105+
106+
// Load/Store instruction properties
107+
DataSizeMode ZZ = WordSM;
108+
ExtMode X = NoEM;
109+
AddrMode AA = NoAM;
110+
CacheMode DI = NoCC;
111+
112+
// Field used for relation models
113+
string BaseOpcode = "";
114+
115+
//TSFlags
116+
let TSFlags{1-0} = AA.Value;
67117
}
68118

69119
// 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,
354404
let Inst{8-7} = zz;
355405
let Inst{6} = x;
356406
let Inst{5-0} = A;
407+
408+
let BaseOpcode = "ld_rs9";
357409
}
358410

359411
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,
363415

364416
let B = addr{14-9};
365417
let S9 = addr{8-0};
418+
419+
let BaseOpcode = "ld_rs9";
366420
}
367421

368422

@@ -387,6 +441,8 @@ class F32_LD_LIMM<bit x, bit di, bits<2> zz, dag outs, dag ins,
387441
let Inst{6} = x;
388442
let Inst{5-0} = A;
389443
let DecoderMethod = "DecodeLdLImmInstruction";
444+
445+
let BaseOpcode = "ld_limm";
390446
}
391447

392448
// 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,
415471
let Inst{11-6} = LImmReg;
416472
let Inst{5-0} = A;
417473
let DecoderMethod = "DecodeLdRLImmInstruction";
474+
475+
let BaseOpcode = "ld_rlimm";
418476
}
419477

420478
// 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,
437495
let Inst{4-3} = aa;
438496
let Inst{2-1} = zz;
439497
let Inst{0} = 0;
498+
499+
let BaseOpcode = "st_rs9";
440500
}
441501

442502
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,
446506

447507
let B = addr{14-9};
448508
let S9 = addr{8-0};
509+
510+
let BaseOpcode = "st_rs9";
449511
}
450512

451513
// LImm Store.
@@ -469,6 +531,8 @@ class F32_ST_LIMM<bit di, bits<2> zz, dag outs, dag ins,
469531
let Inst{2-1} = zz;
470532
let Inst{0} = 0;
471533
let DecoderMethod = "DecodeStLImmInstruction";
534+
535+
let BaseOpcode = "st_limm";
472536
}
473537

474538
// Compact Move/Load.

llvm/lib/Target/ARC/ARCInstrInfo.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@ using namespace llvm;
2727
#include "ARCGenInstrInfo.inc"
2828

2929
#define DEBUG_TYPE "arc-inst-info"
30+
31+
enum AddrIncType {
32+
NoAddInc = 0,
33+
PreInc = 1,
34+
PostInc = 2,
35+
Scaled = 3
36+
};
37+
38+
enum TSFlagsConstants {
39+
TSF_AddrModeOff = 0,
40+
TSF_AddModeMask = 3
41+
};
42+
3043
// Pin the vtable to this file.
3144
void ARCInstrInfo::anchor() {}
3245

@@ -395,3 +408,35 @@ unsigned ARCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
395408
}
396409
return MI.getDesc().getSize();
397410
}
411+
412+
bool ARCInstrInfo::isPostIncrement(const MachineInstr &MI) const {
413+
const MCInstrDesc &MID = MI.getDesc();
414+
const uint64_t F = MID.TSFlags;
415+
return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PostInc;
416+
}
417+
418+
bool ARCInstrInfo::isPreIncrement(const MachineInstr &MI) const {
419+
const MCInstrDesc &MID = MI.getDesc();
420+
const uint64_t F = MID.TSFlags;
421+
return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PreInc;
422+
}
423+
424+
bool ARCInstrInfo::getBaseAndOffsetPosition(const MachineInstr &MI,
425+
unsigned &BasePos,
426+
unsigned &OffsetPos) const {
427+
if (!MI.mayLoad() && !MI.mayStore())
428+
return false;
429+
430+
BasePos = 1;
431+
OffsetPos = 2;
432+
433+
if (isPostIncrement(MI) || isPreIncrement(MI)) {
434+
BasePos++;
435+
OffsetPos++;
436+
}
437+
438+
if (!MI.getOperand(BasePos).isReg() || !MI.getOperand(OffsetPos).isImm())
439+
return false;
440+
441+
return true;
442+
}

llvm/lib/Target/ARC/ARCInstrInfo.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ class ARCInstrInfo : public ARCGenInstrInfo {
8181
bool
8282
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
8383

84+
85+
bool isPostIncrement(const MachineInstr &MI) const override;
86+
87+
// ARC-specific
88+
bool isPreIncrement(const MachineInstr &MI) const;
89+
90+
virtual bool getBaseAndOffsetPosition(const MachineInstr &MI,
91+
unsigned &BasePos,
92+
unsigned &OffsetPos) const override;
93+
8494
// Emit code before MBBI to load immediate value into physical register Reg.
8595
// Returns an iterator to the new instruction.
8696
MachineBasicBlock::iterator loadImmediate(MachineBasicBlock &MBB,

llvm/lib/Target/ARC/ARCInstrInfo.td

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -787,50 +787,47 @@ let isReturn = 1, isTerminator = 1 in {
787787
// Load/Store instructions.
788788
//----------------------------------------------------------------------------
789789

790+
// Filter class for load/store mappings
791+
class ArcLdStRel;
792+
790793
// Load instruction variants:
791794
// Control bits: x, aa, di, zz
792795
// x - sign extend.
793796
// aa - incrementing mode. (N/A for LIMM).
794797
// di - uncached.
795798
// zz - data size.
796-
multiclass ArcLdInst<bits<2> zz, string asmop> {
797-
let mayLoad = 1 in {
798-
def _rs9 : F32_LD_ADDR<0, 0b00, 0, zz,
799-
(outs GPR32:$A), (ins MEMrs9:$addr),
800-
!strconcat(asmop, "\t$A, [$addr]"), []>;
801-
802-
def _limm : F32_LD_LIMM<0, 0, zz,
803-
(outs GPR32:$A), (ins MEMii:$addr),
804-
!strconcat(asmop, "\t$A, [$addr]"), []>;
805-
806-
def _rlimm : F32_LD_RLIMM<0, 0b00, 0, zz,
807-
(outs GPR32:$A), (ins MEMrlimm:$addr),
808-
!strconcat(asmop, "\t$A, [$addr]"), []>;
809-
810-
def _X_rs9 : F32_LD_ADDR<1, 0b00, 0, zz,
811-
(outs GPR32:$A), (ins MEMrs9:$addr),
812-
!strconcat(asmop, ".x\t$A, [$addr]"), []>;
813-
814-
def _X_limm : F32_LD_LIMM<1, 0, zz,
815-
(outs GPR32:$A), (ins MEMii:$addr),
816-
!strconcat(asmop, ".x\t$A, [$addr]"), []>;
817-
818-
def _X_rlimm : F32_LD_RLIMM<1, 0b00, 0, zz,
819-
(outs GPR32:$A), (ins MEMrlimm:$addr),
820-
!strconcat(asmop, ".x\t$A, [$addr]"), []>;
821-
822-
def _AB_rs9 : F32_LD_RS9<0, 0b10, 0, zz,
823-
(outs GPR32:$addrout, GPR32:$A),
824-
(ins GPR32:$B, immS<9>:$S9),
825-
!strconcat(asmop, ".ab\t$A, [$B,$S9]"), []>
826-
{ let Constraints = "$addrout = $B"; }
799+
multiclass ArcLdInst<DataSizeMode zz, ExtMode x, CacheMode di, string asmop> {
800+
let mayLoad = 1, ZZ = zz, X = x, DI = di in {
801+
def _rs9: F32_LD_ADDR<x.Value, NoAM.Value, di.Value, zz.Value,
802+
(outs GPR32:$A), (ins MEMrs9:$addr),
803+
!strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
804+
805+
def _limm: F32_LD_LIMM<x.Value, di.Value, zz.Value,
806+
(outs GPR32:$A), (ins MEMii:$addr),
807+
!strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
808+
809+
def _rlimm: F32_LD_RLIMM<x.Value, NoAM.Value, di.Value, zz.Value,
810+
(outs GPR32:$A), (ins MEMrlimm:$addr),
811+
!strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
812+
813+
foreach aa = [PreIncAM, PostIncAM] in {
814+
def aa.InstSuffix#_rs9: F32_LD_RS9<x.Value, aa.Value, di.Value, zz.Value,
815+
(outs GPR32:$A, GPR32:$addrout),
816+
(ins GPR32:$B, immS<9>:$S9),
817+
asmop#aa.AsmSuffix#"\t$A, [$B,$S9]", []>, ArcLdStRel
818+
{ let Constraints = "$addrout = $B"; let AA = aa; }
819+
}
820+
}
821+
}
822+
823+
foreach di = [NoCC, UncachedCC] in {
824+
defm LD#di.InstSuffix : ArcLdInst<WordSM, NoEM, di, "ld"#di.AsmSuffix>;
825+
foreach zz = [ByteSM, HalfSM] in {
826+
foreach x = [NoEM, SignedEM] in {
827+
defm LD#zz.InstSuffix#x.InstSuffix#di.InstSuffix : ArcLdInst<zz, x, di, "ld"#zz.AsmSuffix#x.AsmSuffix#di.AsmSuffix>;
828+
}
827829
}
828830
}
829-
830-
// Load instruction definitions.
831-
defm LD : ArcLdInst<0b00, "ld">;
832-
defm LDH : ArcLdInst<0b10, "ldh">;
833-
defm LDB : ArcLdInst<0b01, "ldb">;
834831

835832
// Load instruction patterns.
836833
// 32-bit loads.
@@ -872,25 +869,32 @@ def : Pat<(sextloadi8 AddrModeS9:$addr),(LDB_X_rs9 AddrModeS9:$addr)>;
872869
// aa - incrementing mode. (N/A for LIMM).
873870
// di - uncached.
874871
// zz - data size.
875-
multiclass ArcStInst<bits<2> zz, string asmop> {
876-
let mayStore = 1 in {
877-
def _rs9 : F32_ST_ADDR<0b00, 0, zz, (outs), (ins GPR32:$C, MEMrs9:$addr),
878-
!strconcat(asmop, "\t$C, [$addr]"), []>;
879-
880-
def _limm : F32_ST_LIMM<0, zz, (outs), (ins GPR32:$C, MEMii:$addr),
881-
!strconcat(asmop, "\t$C, [$addr]"), []>;
882-
883-
def _AW_rs9 : F32_ST_RS9<0b01, 0, zz, (outs GPR32:$addrout),
884-
(ins GPR32:$C, GPR32:$B, immS<9>:$S9),
885-
!strconcat(asmop, ".aw\t$C, [$B,$S9]"), []>
886-
{ let Constraints = "$addrout = $B"; }
872+
multiclass ArcStInst<DataSizeMode zz, CacheMode di, string asmop> {
873+
let mayStore = 1, ZZ = zz, DI = di in {
874+
def _rs9: F32_ST_ADDR<NoAM.Value, di.Value, zz.Value,
875+
(outs), (ins GPR32:$C, MEMrs9:$addr),
876+
!strconcat(asmop, "\t$C, [$addr]"), []>, ArcLdStRel;
877+
878+
def _limm: F32_ST_LIMM<di.Value, zz.Value,
879+
(outs), (ins GPR32:$C, MEMii:$addr),
880+
!strconcat(asmop, "\t$C, [$addr]"), []>, ArcLdStRel;
881+
882+
883+
foreach aa = [PreIncAM, PostIncAM] in {
884+
def aa.InstSuffix#_rs9: F32_ST_RS9<aa.Value, di.Value, zz.Value,
885+
(outs GPR32:$addrout),
886+
(ins GPR32:$C, GPR32:$B, immS<9>:$S9),
887+
asmop#aa.AsmSuffix#"\t$C, [$B,$S9]", []>, ArcLdStRel
888+
{ let Constraints = "$addrout = $B"; let AA = aa; }
889+
}
887890
}
888891
}
889892

890-
// Store instruction definitions.
891-
defm ST : ArcStInst<0b00, "st">;
892-
defm STH : ArcStInst<0b10, "sth">;
893-
defm STB : ArcStInst<0b01, "stb">;
893+
foreach di = [NoCC, UncachedCC] in {
894+
foreach zz = [ByteSM, HalfSM, WordSM] in {
895+
defm ST#zz.InstSuffix#di.InstSuffix : ArcStInst<zz, di, "st"#zz.AsmSuffix#di.AsmSuffix>;
896+
}
897+
}
894898

895899
// Store instruction patterns.
896900
// 32-bit stores
@@ -911,3 +915,10 @@ def : Pat<(truncstorei8 i32:$C, AddrModeS9:$addr),
911915
def : Pat<(truncstorei8 i32:$C, AddrModeImm:$addr),
912916
(STB_limm i32:$C, AddrModeImm:$addr)>;
913917

918+
def getPostIncOpcode : InstrMapping {
919+
let FilterClass = "ArcLdStRel";
920+
let RowFields = [ "BaseOpcode", "ZZ", "DI", "X"];
921+
let ColFields = [ "AA" ];
922+
let KeyCol = [ "NoAM" ];
923+
let ValueCols = [["PostIncAM"]];
924+
}

llvm/test/MC/Disassembler/ARC/ldst.txt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,50 @@
4545
# CHECK: st %r7, [63920]
4646
0x00 0x1e 0xc0 0x71 0x00 0x00 0xb0 0xf9
4747

48+
# CHECK: ldb.ab %r1, [%r0,1]
49+
0x01 0x10 0x81 0x04
50+
51+
# CHECK: stb.ab %r2, [%r0,1]
52+
0x01 0x18 0x92 0x00
53+
54+
# CHECK: ldh.ab %r3, [%r0,12]
55+
0x0C 0x10 0x03 0x05
56+
57+
# CHECK: sth.ab %r4, [%r0,18]
58+
0x12 0x18 0x14 0x01
59+
60+
# CHECK: ld.ab %r5, [%r2,128]
61+
0x80 0x12 0x05 0x04
62+
63+
# CHECK: st.ab %r6, [%r2,64]
64+
0x40 0x1A 0x90 0x01
65+
66+
# CHECK: ldb.aw %r7, [%r0,1]
67+
0x01 0x10 0x87 0x02
68+
69+
# CHECK: stb.aw %r8, [%r0,1]
70+
0x01 0x18 0x0A 0x02
71+
72+
# CHECK: ldh.aw %r3, [%r0,12]
73+
0x0C 0x10 0x03 0x03
74+
75+
# CHECK: sth.aw %r3, [%r0,18]
76+
0x12 0x18 0xCC 0x00
77+
78+
# CHECK: ld.aw %r6, [%r2,128]
79+
0x80 0x12 0x06 0x02
80+
81+
# CHECK: st.aw %r6, [%r2,64]
82+
0x40 0x1A 0x88 0x01
83+
84+
# CHECK: ld.aw %r6, [%r2,128]
85+
0x80 0x12 0x06 0x02
86+
87+
# CHECK: st.aw %r6, [%r2,64]
88+
0x40 0x1A 0x88 0x01
89+
90+
# CHECK: ldb.x.di.aw %r0, [%r8,8]
91+
0x08 0x10 0xC0 0x1A
92+
93+
# CHECK: stb.di.ab %r0, [%r9,64]
94+
0x40 0x19 0x32 0x10

0 commit comments

Comments
 (0)