Index: llvm/trunk/lib/Target/ARC/ARCInstrFormats.td =================================================================== --- llvm/trunk/lib/Target/ARC/ARCInstrFormats.td +++ llvm/trunk/lib/Target/ARC/ARCInstrFormats.td @@ -55,6 +55,44 @@ let DecoderMethod = "DecodeGBR32ShortRegister"; } +// Helper classes for load/store instructions +class DataSizeMode mode, string instSfx, string asmSfx> { + bits<2> Value = mode; + string InstSuffix = instSfx; + string AsmSuffix = asmSfx; +} +class ExtMode { + bit Value = mode; + string InstSuffix = instSfx; + string AsmSuffix = asmSfx; +} + +class AddrMode mode, string instSfx, string asmSfx> { + bits<2> Value = mode; + string InstSuffix = instSfx; + string AsmSuffix = asmSfx; +} + +class CacheMode { + 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 pattern> : Instruction, Encoding64 { @@ -64,6 +102,18 @@ 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 @@ let Inst{8-7} = zz; let Inst{6} = x; let Inst{5-0} = A; + + let BaseOpcode = "ld_rs9"; } class F32_LD_ADDR aa, bit di, bits<2> zz, dag outs, dag ins, @@ -363,6 +415,8 @@ let B = addr{14-9}; let S9 = addr{8-0}; + + let BaseOpcode = "ld_rs9"; } @@ -387,6 +441,8 @@ 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 @@ 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 @@ let Inst{4-3} = aa; let Inst{2-1} = zz; let Inst{0} = 0; + + let BaseOpcode = "st_rs9"; } class F32_ST_ADDR aa, bit di, bits<2> zz, dag outs, dag ins, @@ -446,6 +506,8 @@ let B = addr{14-9}; let S9 = addr{8-0}; + + let BaseOpcode = "st_rs9"; } // LImm Store. @@ -469,6 +531,8 @@ let Inst{2-1} = zz; let Inst{0} = 0; let DecoderMethod = "DecodeStLImmInstruction"; + + let BaseOpcode = "st_limm"; } // Compact Move/Load. Index: llvm/trunk/lib/Target/ARC/ARCInstrInfo.h =================================================================== --- llvm/trunk/lib/Target/ARC/ARCInstrInfo.h +++ llvm/trunk/lib/Target/ARC/ARCInstrInfo.h @@ -81,6 +81,16 @@ bool reverseBranchCondition(SmallVectorImpl &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, Index: llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp =================================================================== --- llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp +++ llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp @@ -27,6 +27,19 @@ #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 @@ } 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; +} Index: llvm/trunk/lib/Target/ARC/ARCInstrInfo.td =================================================================== --- llvm/trunk/lib/Target/ARC/ARCInstrInfo.td +++ llvm/trunk/lib/Target/ARC/ARCInstrInfo.td @@ -787,50 +787,47 @@ // 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 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]"), []>; - - def _limm : F32_LD_LIMM<0, 0, zz, - (outs GPR32:$A), (ins MEMii:$addr), - !strconcat(asmop, "\t$A, [$addr]"), []>; - - def _rlimm : F32_LD_RLIMM<0, 0b00, 0, zz, - (outs GPR32:$A), (ins MEMrlimm:$addr), - !strconcat(asmop, "\t$A, [$addr]"), []>; - - 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"; } +multiclass ArcLdInst { + let mayLoad = 1, ZZ = zz, X = x, DI = di in { + def _rs9: F32_LD_ADDR, ArcLdStRel; + + def _limm: F32_LD_LIMM, ArcLdStRel; + + def _rlimm: F32_LD_RLIMM, ArcLdStRel; + + foreach aa = [PreIncAM, PostIncAM] in { + def aa.InstSuffix#_rs9: F32_LD_RS9:$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; + foreach zz = [ByteSM, HalfSM] in { + foreach x = [NoEM, SignedEM] in { + defm LD#zz.InstSuffix#x.InstSuffix#di.InstSuffix : ArcLdInst; + } } } - -// 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 @@ // aa - incrementing mode. (N/A for LIMM). // di - uncached. // zz - data size. -multiclass ArcStInst 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]"), []>; - - def _limm : F32_ST_LIMM<0, zz, (outs), (ins GPR32:$C, MEMii:$addr), - !strconcat(asmop, "\t$C, [$addr]"), []>; - - 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"; } +multiclass ArcStInst { + let mayStore = 1, ZZ = zz, DI = di in { + def _rs9: F32_ST_ADDR, ArcLdStRel; + + def _limm: F32_ST_LIMM, ArcLdStRel; + + + foreach aa = [PreIncAM, PostIncAM] in { + def aa.InstSuffix#_rs9: F32_ST_RS9:$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; + } +} // Store instruction patterns. // 32-bit stores @@ -911,3 +915,10 @@ 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"]]; +} Index: llvm/trunk/test/MC/Disassembler/ARC/ldst.txt =================================================================== --- llvm/trunk/test/MC/Disassembler/ARC/ldst.txt +++ llvm/trunk/test/MC/Disassembler/ARC/ldst.txt @@ -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