forked from OSchip/llvm-project
[M68k] Adopt VarLenCodeEmitter for move instructions
The `move` instruction has one of the most complicate sets of variants, so we're refactoring it first before finishing up rest of the data instructions in a separate patch. Note that since we're introducing more `move` variants, the codegen actually got improved in terms of code size.
This commit is contained in:
parent
f927106e10
commit
18b38ff6c7
|
@ -42,290 +42,176 @@
|
|||
/// -----------------------------------------------------
|
||||
///
|
||||
/// NOTE Move requires EA X version for direct register destination(0)
|
||||
class MxMoveEncoding<MxBead2Bits size,
|
||||
MxEncEA srcEA, MxEncExt srcExt,
|
||||
MxEncEA dstEA, MxEncExt dstExt>
|
||||
: MxEncoding<srcEA.Reg, srcEA.DA, srcEA.Mode, dstEA.DA, dstEA.Mode, dstEA.Reg,
|
||||
size, MxBead2Bits<0b00>,
|
||||
srcExt.Imm, srcExt.B8, srcExt.Scale, srcExt.WL, srcExt.DAReg,
|
||||
dstExt.Imm, dstExt.B8, dstExt.Scale, dstExt.WL, dstExt.DAReg>;
|
||||
|
||||
/// MOVE has alternate size encoding
|
||||
class MxMoveSize<bits<2> value> : MxBead2Bits<value>;
|
||||
// MOVE has a different size encoding.
|
||||
class MxMoveSize<bits<2> value> {
|
||||
bits<2> Value = value;
|
||||
}
|
||||
def MxMoveSize8 : MxMoveSize<0b01>;
|
||||
def MxMoveSize16 : MxMoveSize<0b11>;
|
||||
def MxMoveSize32 : MxMoveSize<0b10>;
|
||||
|
||||
let Defs = [CCR] in
|
||||
class MxMove<string size, dag outs, dag ins, list<dag> pattern, MxEncoding enc>
|
||||
: MxInst<outs, ins, "move."#size#"\t$src, $dst", pattern, enc>;
|
||||
class MxMoveEncoding<MxMoveSize size, MxEncMemOp dst_enc, MxEncMemOp src_enc> {
|
||||
dag Value = (ascend
|
||||
(descend 0b00, size.Value,
|
||||
!cond(
|
||||
!eq(!getdagop(dst_enc.EA), descend): !setdagop(dst_enc.EA, ascend),
|
||||
!eq(!getdagop(dst_enc.EA), ascend): !setdagop(dst_enc.EA, descend)),
|
||||
src_enc.EA),
|
||||
// Source extension
|
||||
src_enc.Supplement,
|
||||
// Destination extension
|
||||
dst_enc.Supplement
|
||||
);
|
||||
}
|
||||
|
||||
class MxMove_RR<MxType DST, MxType SRC, MxMoveEncoding ENC>
|
||||
: MxMove<DST.Prefix, (outs DST.ROp:$dst), (ins SRC.ROp:$src),
|
||||
// Special encoding for Xn
|
||||
class MxMoveEncAddrMode_r<string reg_opnd> : MxEncMemOp {
|
||||
let EA = (descend (descend 0b00, (slice "$"#reg_opnd, 3, 3)),
|
||||
(operand "$"#reg_opnd, 3));
|
||||
}
|
||||
|
||||
multiclass MxMoveOperandEncodings<string opnd_name> {
|
||||
// Dn
|
||||
def MxMove#NAME#OpEnc_d : MxEncAddrMode_d<opnd_name>;
|
||||
// An
|
||||
def MxMove#NAME#OpEnc_a : MxEncAddrMode_a<opnd_name>;
|
||||
// Xn
|
||||
def MxMove#NAME#OpEnc_r : MxMoveEncAddrMode_r<opnd_name>;
|
||||
// (An)+
|
||||
def MxMove#NAME#OpEnc_o : MxEncAddrMode_o<opnd_name>;
|
||||
// -(An)
|
||||
def MxMove#NAME#OpEnc_e : MxEncAddrMode_e<opnd_name>;
|
||||
// (i,PC,Xn)
|
||||
def MxMove#NAME#OpEnc_k : MxEncAddrMode_k<opnd_name>;
|
||||
// (i,PC)
|
||||
def MxMove#NAME#OpEnc_q : MxEncAddrMode_q<opnd_name>;
|
||||
// (i,An,Xn)
|
||||
def MxMove#NAME#OpEnc_f : MxEncAddrMode_f<opnd_name>;
|
||||
// (i,An)
|
||||
def MxMove#NAME#OpEnc_p : MxEncAddrMode_p<opnd_name>;
|
||||
// (ABS).L
|
||||
def MxMove#NAME#OpEnc_b : MxEncAddrMode_abs<opnd_name, /*W/L=*/true>;
|
||||
// (An)
|
||||
def MxMove#NAME#OpEnc_j : MxEncAddrMode_j<opnd_name>;
|
||||
}
|
||||
|
||||
defm Src : MxMoveOperandEncodings<"src">;
|
||||
defm Dst : MxMoveOperandEncodings<"dst">;
|
||||
|
||||
defvar MxMoveSupportedAMs = ["o", "e", "k", "q", "f", "p", "b", "j"];
|
||||
|
||||
let Defs = [CCR] in
|
||||
class MxMove<string size, dag outs, dag ins, list<dag> pattern, MxMoveEncoding enc>
|
||||
: MxInst<outs, ins, "move."#size#"\t$src, $dst", pattern> {
|
||||
let Inst = enc.Value;
|
||||
}
|
||||
|
||||
class MxMove_RR<MxType TYPE, string DST_REG, string SRC_REG,
|
||||
MxMoveEncoding ENC,
|
||||
MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG),
|
||||
MxOpBundle SRC = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#SRC_REG)>
|
||||
: MxMove<TYPE.Prefix,
|
||||
(outs DST.Op:$dst), (ins SRC.Op:$src),
|
||||
[(null_frag)], ENC>;
|
||||
|
||||
let mayStore = 1 in {
|
||||
class MxMove_MR<MxOperand MEMOpd, ComplexPattern MEMPat, MxType REG,
|
||||
MxMoveEncoding ENC>
|
||||
: MxMove<REG.Prefix, (outs), (ins MEMOpd:$dst, REG.ROp:$src),
|
||||
[(store REG.VT:$src, MEMPat:$dst)], ENC>;
|
||||
class MxMove_MR<MxType TYPE, MxOpBundle DST, string SRC_REG, MxMoveEncoding ENC,
|
||||
MxOpBundle SRC = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#SRC_REG)>
|
||||
: MxMove<TYPE.Prefix, (outs), (ins DST.Op:$dst, SRC.Op:$src),
|
||||
[(store TYPE.VT:$src, DST.Pat:$dst)], ENC>;
|
||||
|
||||
class MxMove_MI<MxOperand MEMOpd, ComplexPattern MEMPat, MxType TYPE,
|
||||
MxMoveEncoding ENC>
|
||||
: MxMove<TYPE.Prefix, (outs), (ins MEMOpd:$dst, TYPE.IOp:$src),
|
||||
[(store TYPE.IPat:$src, MEMPat:$dst)], ENC>;
|
||||
class MxMove_MI<MxType TYPE, MxOpBundle DST, MxMoveEncoding ENC,
|
||||
MxImmOpBundle SRC = !cast<MxImmOpBundle>("MxOp"#TYPE.Size#"AddrMode_i")>
|
||||
: MxMove<TYPE.Prefix, (outs), (ins DST.Op:$dst, SRC.Op:$src),
|
||||
[(store SRC.ImmPat:$src, DST.Pat:$dst)], ENC>;
|
||||
} // let mayStore = 1
|
||||
|
||||
class MxMove_RI<MxType DST, MxMoveEncoding ENC>
|
||||
: MxMove<DST.Prefix, (outs DST.ROp:$dst), (ins DST.IOp:$src),
|
||||
[(set DST.VT:$dst, DST.IPat:$src)], ENC>;
|
||||
class MxMove_RI<MxType TYPE, string DST_REG, MxMoveEncoding ENC,
|
||||
MxImmOpBundle SRC = !cast<MxImmOpBundle>("MxOp"#TYPE.Size#"AddrMode_i"),
|
||||
MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG)>
|
||||
: MxMove<TYPE.Prefix, (outs DST.Op:$dst), (ins SRC.Op:$src),
|
||||
[(set TYPE.VT:$dst, SRC.ImmPat:$src)], ENC>;
|
||||
|
||||
|
||||
let mayLoad = 1 in
|
||||
class MxMove_RM<MxType REG, MxOperand MEMOpd, ComplexPattern MEMPat,
|
||||
MxBead2Bits SIZE,
|
||||
MxEncEA SRCEA, MxEncExt SRCEXT,
|
||||
MxEncEA DSTEA, MxEncExt DSTEXT>
|
||||
: MxMove<REG.Prefix, (outs REG.ROp:$dst), (ins MEMOpd:$src),
|
||||
[(set REG.VT:$dst, (REG.Load MEMPat:$src))],
|
||||
MxMoveEncoding<SIZE, SRCEA, SRCEXT, DSTEA, DSTEXT>>;
|
||||
class MxMove_RM<MxType TYPE, string DST_REG, MxOpBundle SRC, MxEncMemOp SRC_ENC,
|
||||
MxMoveSize SIZE_ENC = !cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
|
||||
MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG),
|
||||
MxEncMemOp DST_ENC = !cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_REG)>
|
||||
: MxMove<TYPE.Prefix, (outs DST.Op:$dst), (ins SRC.Op:$src),
|
||||
[(set TYPE.VT:$dst, (TYPE.Load SRC.Pat:$src))],
|
||||
MxMoveEncoding<SIZE_ENC, DST_ENC, SRC_ENC>>;
|
||||
|
||||
multiclass MMxMove_RM<MxType REG, MxMoveSize SIZE, MxEncEA EA_0> {
|
||||
foreach REG = ["r", "a", "d"] in
|
||||
foreach AM = MxMoveSupportedAMs in {
|
||||
foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in
|
||||
def MOV # TYPE.Size # REG # AM # TYPE.Postfix
|
||||
: MxMove_RM<TYPE, REG, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),
|
||||
!cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;
|
||||
} // foreach AM
|
||||
|
||||
// REG <- (An)+
|
||||
def NAME#REG.OOp.Letter#REG.Postfix : MxMove_RM<REG, REG.OOp, REG.OPat,
|
||||
SIZE, MxEncEAo_1, MxExtEmpty, EA_0, MxExtEmpty>;
|
||||
let mayLoad = 1, mayStore = 1 in
|
||||
class MxMove_MM<MxType TYPE, MxOpBundle DST, MxOpBundle SRC,
|
||||
MxEncMemOp DST_ENC, MxEncMemOp SRC_ENC>
|
||||
: MxMove<TYPE.Prefix, (outs), (ins DST.Op:$dst, SRC.Op:$src),
|
||||
[(store (TYPE.Load SRC.Pat:$src), DST.Pat:$dst)],
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
|
||||
DST_ENC, SRC_ENC>>;
|
||||
|
||||
// REG <- -(An)
|
||||
def NAME#REG.EOp.Letter#REG.Postfix : MxMove_RM<REG, REG.EOp, REG.EPat,
|
||||
SIZE, MxEncEAe_1, MxExtEmpty, EA_0, MxExtEmpty>;
|
||||
foreach DST_AM = MxMoveSupportedAMs in
|
||||
foreach SRC_AM = MxMoveSupportedAMs in {
|
||||
foreach TYPE = [MxType8, MxType16, MxType32] in
|
||||
def MOV # TYPE.Size # DST_AM # SRC_AM # TYPE.Postfix
|
||||
: MxMove_MM<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_AM),
|
||||
!cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#SRC_AM),
|
||||
!cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_AM),
|
||||
!cast<MxEncMemOp>("MxMoveSrcOpEnc_"#SRC_AM)>;
|
||||
} // foreach SRC_AM
|
||||
|
||||
// REG <- (i,PC,Xn)
|
||||
def NAME#REG.KOp.Letter#REG.Postfix : MxMove_RM<REG, REG.KOp, REG.KPat,
|
||||
SIZE, MxEncEAk, MxExtBrief_1, EA_0, MxExtEmpty>;
|
||||
|
||||
// REG <- (i,PC)
|
||||
def NAME#REG.QOp.Letter#REG.Postfix : MxMove_RM<REG, REG.QOp, REG.QPat,
|
||||
SIZE, MxEncEAq, MxExtI16_1, EA_0, MxExtEmpty>;
|
||||
|
||||
// REG <- (i,An,Xn)
|
||||
def NAME#REG.FOp.Letter#REG.Postfix : MxMove_RM<REG, REG.FOp, REG.FPat,
|
||||
SIZE, MxEncEAf_1, MxExtBrief_1, EA_0, MxExtEmpty>;
|
||||
|
||||
// REG <- (i,An)
|
||||
def NAME#REG.POp.Letter#REG.Postfix : MxMove_RM<REG, REG.POp, REG.PPat,
|
||||
SIZE, MxEncEAp_1, MxExtI16_1, EA_0, MxExtEmpty>;
|
||||
|
||||
// REG <- (ABS)
|
||||
def NAME#REG.BOp.Letter#REG.Postfix : MxMove_RM<REG, REG.BOp, REG.BPat,
|
||||
SIZE, MxEncEAb, MxExtI32_1, EA_0, MxExtEmpty>;
|
||||
|
||||
// REG <- (An)
|
||||
def NAME#REG.JOp.Letter#REG.Postfix : MxMove_RM<REG, REG.JOp, REG.JPat,
|
||||
SIZE, MxEncEAj_1, MxExtEmpty, EA_0, MxExtEmpty>;
|
||||
}
|
||||
|
||||
let mayLoad = 1, mayStore = 1 in {
|
||||
class MxMove_MM<string SIZE, PatFrag LOAD,
|
||||
MxOperand DSTOpd, ComplexPattern DSTPat,
|
||||
MxOperand SRCOpd, ComplexPattern SRCPat,
|
||||
MxBead2Bits ESIZE,
|
||||
MxEncEA SRCEA, MxEncExt SRCEXT,
|
||||
MxEncEA DSTEA, MxEncExt DSTEXT>
|
||||
: MxMove<SIZE, (outs), (ins DSTOpd:$dst, SRCOpd:$src),
|
||||
[(store (LOAD SRCPat:$src), DSTPat:$dst)],
|
||||
MxMoveEncoding<ESIZE, SRCEA, SRCEXT, DSTEA, DSTEXT>>;
|
||||
} // let mayLoad = 1, mayStore = 1
|
||||
|
||||
multiclass MMxMove_MM<MxType TYPE, MxOperand DSTOpd, ComplexPattern DSTPat,
|
||||
MxMoveSize SIZE, MxEncEA EA_0, MxEncExt EXT_0> {
|
||||
|
||||
// MEM <- (An)+
|
||||
def NAME#TYPE.OOp.Letter#TYPE.Postfix
|
||||
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.OOp, TYPE.OPat,
|
||||
SIZE, MxEncEAo_1, MxExtEmpty, EA_0, EXT_0>;
|
||||
|
||||
// MEM <- -(An)
|
||||
def NAME#TYPE.EOp.Letter#TYPE.Postfix
|
||||
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.EOp, TYPE.EPat,
|
||||
SIZE, MxEncEAe_1, MxExtEmpty, EA_0, EXT_0>;
|
||||
|
||||
// MEM <- (i,An)
|
||||
def NAME#TYPE.POp.Letter#TYPE.Postfix
|
||||
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.POp, TYPE.PPat,
|
||||
SIZE, MxEncEAp_1, MxExtI16_1, EA_0, EXT_0>;
|
||||
|
||||
// MEM <- (i,An,Xn)
|
||||
def NAME#TYPE.FOp.Letter#TYPE.Postfix
|
||||
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.FOp, TYPE.FPat,
|
||||
SIZE, MxEncEAf_1, MxExtBrief_1, EA_0, EXT_0>;
|
||||
|
||||
// MEM <- (i,PC,Xn)
|
||||
def NAME#TYPE.KOp.Letter#TYPE.Postfix
|
||||
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.KOp, TYPE.KPat,
|
||||
SIZE, MxEncEAk, MxExtBrief_1, EA_0, EXT_0>;
|
||||
|
||||
// MEM <- (i,PC)
|
||||
def NAME#TYPE.QOp.Letter#TYPE.Postfix
|
||||
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.QOp, TYPE.QPat,
|
||||
SIZE, MxEncEAq, MxExtI16_1, EA_0, EXT_0>;
|
||||
|
||||
// MEM <- (ABS)
|
||||
def NAME#TYPE.BOp.Letter#TYPE.Postfix
|
||||
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.BOp, TYPE.BPat,
|
||||
SIZE, MxEncEAb, MxExtI32_1, EA_0, EXT_0>;
|
||||
|
||||
// MEM <- (An)
|
||||
def NAME#TYPE.JOp.Letter#TYPE.Postfix
|
||||
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.JOp, TYPE.JPat,
|
||||
SIZE, MxEncEAj_1, MxExtEmpty, EA_0, EXT_0>;
|
||||
}
|
||||
|
||||
def MOV8dd
|
||||
: MxMove_RR<MxType8d, MxType8d,
|
||||
MxMoveEncoding<MxMoveSize8, MxEncEAd_1, MxExtEmpty, MxEncEAd_0, MxExtEmpty>>;
|
||||
|
||||
// M <- R
|
||||
def MOV8fd : MxMove_MR<MxType8.FOp, MxType8.FPat, MxType8d,
|
||||
MxMoveEncoding<MxMoveSize8,
|
||||
/*src*/ MxEncEAd_1, MxExtEmpty,
|
||||
/*dst*/ MxEncEAf_0, MxExtBrief_0>>;
|
||||
|
||||
def MOV8pd : MxMove_MR<MxType8.POp, MxType8.PPat, MxType8d,
|
||||
MxMoveEncoding<MxMoveSize8,
|
||||
/*src*/ MxEncEAd_1, MxExtEmpty,
|
||||
/*dst*/ MxEncEAp_0, MxExtI16_0>>;
|
||||
|
||||
def MOV8ed : MxMove_MR<MxType8.EOp, MxType8.EPat, MxType8d,
|
||||
MxMoveEncoding<MxMoveSize8,
|
||||
/*src*/ MxEncEAd_1, MxExtEmpty,
|
||||
/*dst*/ MxEncEAe_0, MxExtEmpty>>;
|
||||
|
||||
def MOV8od : MxMove_MR<MxType8.OOp, MxType8.OPat, MxType8d,
|
||||
MxMoveEncoding<MxMoveSize8,
|
||||
/*src*/ MxEncEAd_1, MxExtEmpty,
|
||||
/*dst*/ MxEncEAo_0, MxExtEmpty>>;
|
||||
|
||||
def MOV8bd : MxMove_MR<MxType8.BOp, MxType8.BPat, MxType8d,
|
||||
MxMoveEncoding<MxMoveSize8,
|
||||
/*src*/ MxEncEAd_1, MxExtEmpty,
|
||||
/*dst*/ MxEncEAb, MxExtI32_0>>;
|
||||
|
||||
def MOV8jd : MxMove_MR<MxType8.JOp, MxType8.JPat, MxType8d,
|
||||
MxMoveEncoding<MxMoveSize8,
|
||||
/*src*/ MxEncEAd_1, MxExtEmpty,
|
||||
/*dst*/ MxEncEAj_0, MxExtEmpty>>;
|
||||
foreach DST_REG = ["r", "a"] in {
|
||||
foreach SRC_REG = ["r", "a"] in
|
||||
foreach TYPE = [MxType16, MxType32] in
|
||||
def MOV # TYPE.Size # DST_REG # SRC_REG # TYPE.Postfix
|
||||
: MxMove_RR<TYPE, DST_REG, SRC_REG,
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
|
||||
!cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_REG),
|
||||
!cast<MxEncMemOp>("MxMoveSrcOpEnc_"#SRC_REG)>>;
|
||||
} // foreach DST_REG
|
||||
foreach TYPE = [MxType8, MxType16, MxType32] in
|
||||
def MOV # TYPE.Size # dd # TYPE.Postfix
|
||||
: MxMove_RR<TYPE, "d", "d",
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
|
||||
MxMoveDstOpEnc_d, MxMoveSrcOpEnc_d>>;
|
||||
|
||||
|
||||
// R <- I
|
||||
def MOV8di : MxMove_RI<MxType8d,
|
||||
MxMoveEncoding<MxMoveSize8, MxEncEAi, MxExtI8_1, MxEncEAd_0, MxExtEmpty>>;
|
||||
foreach REG = ["r", "a", "d"] in
|
||||
foreach AM = MxMoveSupportedAMs in {
|
||||
foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in
|
||||
def MOV # TYPE.Size # AM # REG # TYPE.Postfix
|
||||
: MxMove_MR<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM), REG,
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
|
||||
!cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM),
|
||||
!cast<MxEncMemOp>("MxMoveSrcOpEnc_"#REG)>>;
|
||||
} // foreach AM
|
||||
|
||||
foreach S = [16, 32] in {
|
||||
foreach D = [ "r", "a" ] in {
|
||||
foreach REG = ["r", "a", "d"] in {
|
||||
foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in
|
||||
def MOV # TYPE.Size # REG # i # TYPE.Postfix
|
||||
: MxMove_RI<TYPE, REG,
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
|
||||
!cast<MxEncMemOp>("MxMoveDstOpEnc_"#REG),
|
||||
MxEncAddrMode_i<"src", TYPE.Size>>>;
|
||||
} // foreach REG
|
||||
|
||||
foreach O = [ "r", "a" ] in {
|
||||
def MOV#S#D#O : MxMove_RR<
|
||||
!cast<MxType>("MxType"#S#D),
|
||||
!cast<MxType>("MxType"#S#O),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
|
||||
!cast<MxEncEA>("MxEncEA"#D#"_0_reflected"), MxExtEmpty>>;
|
||||
}
|
||||
|
||||
// M <- R
|
||||
def MOV#S#"f"#D : MxMove_MR<
|
||||
!cast<MxType>("MxType"#S).FOp,
|
||||
!cast<MxType>("MxType"#S).FPat,
|
||||
!cast<MxType>("MxType"#S#D),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
|
||||
MxEncEAf_0, MxExtBrief_0>>;
|
||||
|
||||
def MOV#S#"p"#D : MxMove_MR<
|
||||
!cast<MxType>("MxType"#S).POp,
|
||||
!cast<MxType>("MxType"#S).PPat,
|
||||
!cast<MxType>("MxType"#S#D),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
|
||||
MxEncEAp_0, MxExtI16_0>>;
|
||||
|
||||
def MOV#S#"e"#D : MxMove_MR<
|
||||
!cast<MxType>("MxType"#S).EOp,
|
||||
!cast<MxType>("MxType"#S).EPat,
|
||||
!cast<MxType>("MxType"#S#D),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
|
||||
MxEncEAe_0, MxExtEmpty>>;
|
||||
|
||||
def MOV#S#"o"#D : MxMove_MR<
|
||||
!cast<MxType>("MxType"#S).OOp,
|
||||
!cast<MxType>("MxType"#S).OPat,
|
||||
!cast<MxType>("MxType"#S#D),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
|
||||
MxEncEAo_0, MxExtEmpty>>;
|
||||
|
||||
def MOV#S#"b"#D : MxMove_MR<
|
||||
!cast<MxType>("MxType"#S).BOp,
|
||||
!cast<MxType>("MxType"#S).BPat,
|
||||
!cast<MxType>("MxType"#S#D),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
|
||||
MxEncEAb, MxExtI32_0>>;
|
||||
|
||||
def MOV#S#"j"#D : MxMove_MR<
|
||||
!cast<MxType>("MxType"#S).JOp,
|
||||
!cast<MxType>("MxType"#S).JPat,
|
||||
!cast<MxType>("MxType"#S#D),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
|
||||
MxEncEAj_0, MxExtEmpty>>;
|
||||
|
||||
|
||||
// R <- I
|
||||
def MOV#S#D#"i" : MxMove_RI<
|
||||
!cast<MxType>("MxType"#S#D),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
|
||||
!cast<MxEncEA>("MxEncEA"#D#"_0_reflected"), MxExtEmpty>>;
|
||||
}
|
||||
}
|
||||
|
||||
// M <- I
|
||||
foreach S = [8, 16, 32] in {
|
||||
def MOV#S#"f"#"i" : MxMove_MI<
|
||||
!cast<MxType>("MxType"#S).FOp,
|
||||
!cast<MxType>("MxType"#S).FPat,
|
||||
!cast<MxType>("MxType"#S),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
|
||||
MxEncEAf_0, MxExtBrief_0>>;
|
||||
|
||||
def MOV#S#"p"#"i" : MxMove_MI<
|
||||
!cast<MxType>("MxType"#S).POp,
|
||||
!cast<MxType>("MxType"#S).PPat,
|
||||
!cast<MxType>("MxType"#S),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
|
||||
MxEncEAp_0, MxExtI16_0>>;
|
||||
|
||||
def MOV#S#"b"#"i" : MxMove_MI<
|
||||
!cast<MxType>("MxType"#S).BOp,
|
||||
!cast<MxType>("MxType"#S).BPat,
|
||||
!cast<MxType>("MxType"#S),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
|
||||
MxEncEAb, MxExtI32_0>>;
|
||||
|
||||
def MOV#S#"j"#"i" : MxMove_MI<
|
||||
!cast<MxType>("MxType"#S).JOp,
|
||||
!cast<MxType>("MxType"#S).JPat,
|
||||
!cast<MxType>("MxType"#S),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
|
||||
MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
|
||||
MxEncEAj_0, MxExtEmpty>>;
|
||||
}
|
||||
foreach AM = MxMoveSupportedAMs in {
|
||||
foreach TYPE = [MxType8, MxType16, MxType32] in
|
||||
def MOV # TYPE.Size # AM # i # TYPE.Postfix
|
||||
: MxMove_MI<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),
|
||||
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
|
||||
!cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM),
|
||||
MxEncAddrMode_i<"src", TYPE.Size>>>;
|
||||
} // foreach AM
|
||||
|
||||
// Store ABS(basically pointer) as Immdiate to Mem
|
||||
def : Pat<(store MxType32.BPat :$src, MxType32.PPat :$dst),
|
||||
|
@ -340,65 +226,15 @@ def : Pat<(store MxType32.BPat :$src, MxType32.BPat :$dst),
|
|||
def : Pat<(store MxType32.BPat :$src, MxType32.JPat :$dst),
|
||||
(MOV32ji MxType32.JOp :$dst, MxType32.IOp :$src)>;
|
||||
|
||||
// R <- M
|
||||
defm MOV8d : MMxMove_RM<MxType8d, MxMoveSize8, MxEncEAd_0>;
|
||||
|
||||
defm MOV16r : MMxMove_RM<MxType16r, MxMoveSize16, MxEncEAr_0_reflected>;
|
||||
defm MOV16a : MMxMove_RM<MxType16a, MxMoveSize16, MxEncEAa_0>;
|
||||
|
||||
defm MOV32r : MMxMove_RM<MxType32r, MxMoveSize32, MxEncEAr_0_reflected>;
|
||||
defm MOV32a : MMxMove_RM<MxType32a, MxMoveSize32, MxEncEAa_0>;
|
||||
|
||||
let Pattern = [(null_frag)] in {
|
||||
defm MOV16r : MMxMove_RM<MxType16r_TC, MxMoveSize16, MxEncEAr_0_reflected>;
|
||||
defm MOV16a : MMxMove_RM<MxType16a_TC, MxMoveSize16, MxEncEAa_0>;
|
||||
|
||||
defm MOV32r : MMxMove_RM<MxType32r_TC, MxMoveSize32, MxEncEAr_0_reflected>;
|
||||
defm MOV32a : MMxMove_RM<MxType32a_TC, MxMoveSize32, MxEncEAa_0>;
|
||||
} // Pattern
|
||||
|
||||
// M <- M
|
||||
defm MOV8p : MMxMove_MM<MxType8, MxType8.POp, MxType8.PPat,
|
||||
MxMoveSize8, MxEncEAp_0, MxExtI16_0>;
|
||||
defm MOV16p : MMxMove_MM<MxType16, MxType16.POp, MxType16.PPat,
|
||||
MxMoveSize16, MxEncEAp_0, MxExtI16_0>;
|
||||
defm MOV32p : MMxMove_MM<MxType32, MxType32.POp, MxType32.PPat,
|
||||
MxMoveSize32, MxEncEAp_0, MxExtI16_0>;
|
||||
|
||||
defm MOV8f : MMxMove_MM<MxType8, MxType8.FOp, MxType8.FPat,
|
||||
MxMoveSize8, MxEncEAf_0, MxExtBrief_0>;
|
||||
defm MOV16f : MMxMove_MM<MxType16, MxType16.FOp, MxType16.FPat,
|
||||
MxMoveSize16, MxEncEAf_0, MxExtBrief_0>;
|
||||
defm MOV32f : MMxMove_MM<MxType32, MxType32.FOp, MxType32.FPat,
|
||||
MxMoveSize32, MxEncEAf_0, MxExtBrief_0>;
|
||||
|
||||
defm MOV8b : MMxMove_MM<MxType8, MxType8.BOp, MxType8.BPat,
|
||||
MxMoveSize8, MxEncEAb, MxExtI32_0>;
|
||||
defm MOV16b : MMxMove_MM<MxType16, MxType16.BOp, MxType16.BPat,
|
||||
MxMoveSize16, MxEncEAb, MxExtI32_0>;
|
||||
defm MOV32b : MMxMove_MM<MxType32, MxType32.BOp, MxType32.BPat,
|
||||
MxMoveSize32, MxEncEAb, MxExtI32_0>;
|
||||
|
||||
defm MOV8e : MMxMove_MM<MxType8, MxType8.EOp, MxType8.EPat,
|
||||
MxMoveSize8, MxEncEAe_0, MxExtEmpty>;
|
||||
defm MOV16e : MMxMove_MM<MxType16, MxType16.EOp, MxType16.EPat,
|
||||
MxMoveSize16, MxEncEAe_0, MxExtEmpty>;
|
||||
defm MOV32e : MMxMove_MM<MxType32, MxType32.EOp, MxType32.EPat,
|
||||
MxMoveSize32, MxEncEAe_0, MxExtEmpty>;
|
||||
|
||||
defm MOV8o : MMxMove_MM<MxType8, MxType8.OOp, MxType8.OPat,
|
||||
MxMoveSize8, MxEncEAo_0, MxExtEmpty>;
|
||||
defm MOV16o : MMxMove_MM<MxType16, MxType16.OOp, MxType16.OPat,
|
||||
MxMoveSize16, MxEncEAo_0, MxExtEmpty>;
|
||||
defm MOV32o : MMxMove_MM<MxType32, MxType32.OOp, MxType32.OPat,
|
||||
MxMoveSize32, MxEncEAo_0, MxExtEmpty>;
|
||||
|
||||
defm MOV8j : MMxMove_MM<MxType8, MxType8.JOp, MxType8.JPat,
|
||||
MxMoveSize8, MxEncEAj_0, MxExtEmpty>;
|
||||
defm MOV16j : MMxMove_MM<MxType16, MxType16.JOp, MxType16.JPat,
|
||||
MxMoveSize16, MxEncEAj_0, MxExtEmpty>;
|
||||
defm MOV32j : MMxMove_MM<MxType32, MxType32.JOp, MxType32.JPat,
|
||||
MxMoveSize32, MxEncEAj_0, MxExtEmpty>;
|
||||
foreach REG = ["r", "a"] in
|
||||
foreach AM = MxMoveSupportedAMs in {
|
||||
foreach TYPE = [MxType16, MxType32] in
|
||||
def MOV # TYPE.Size # REG # AM # _TC
|
||||
: MxMove_RM<TYPE, REG, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),
|
||||
!cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;
|
||||
} // foreach AM
|
||||
} // let Pattern
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MOVEM
|
||||
|
|
|
@ -263,6 +263,16 @@ class MxEncBriefExt<string reg_opnd, string disp_opnd,
|
|||
);
|
||||
}
|
||||
|
||||
class MxEncAddrMode_d<string reg_opnd> : MxEncMemOp {
|
||||
let EA = (descend /*MODE*/0b000,
|
||||
/*REGISTER*/(operand "$"#reg_opnd, 3));
|
||||
}
|
||||
|
||||
class MxEncAddrMode_a<string reg_opnd> : MxEncMemOp {
|
||||
let EA = (descend /*MODE*/0b001,
|
||||
/*REGISTER*/(operand "$"#reg_opnd, 3));
|
||||
}
|
||||
|
||||
class MxEncAddrMode_r<string reg_opnd> : MxEncMemOp {
|
||||
let EA = (descend /*MODE without the last bit*/0b00,
|
||||
/*REGISTER with D/A bit*/(operand "$"#reg_opnd, 4));
|
||||
|
@ -327,7 +337,11 @@ class MxEncAddrMode_i<string opnd_name, int size> : MxEncMemOp {
|
|||
// abs.L -> size_w_l = true
|
||||
class MxEncAddrMode_abs<string opnd_name, bit size_w_l = false> : MxEncMemOp {
|
||||
let EA = (descend /*MODE*/0b111,
|
||||
/*REGISTER*/0b00, size_w_l);
|
||||
// Wrap the REGISTER part in another dag to make sure
|
||||
// the dag assigned to EA only has two arguments. Such
|
||||
// that it's easier for MOV instructions to reverse
|
||||
// on its destination part.
|
||||
/*REGISTER*/(descend 0b00, size_w_l));
|
||||
|
||||
// Absolute address
|
||||
let Supplement = !if(size_w_l,
|
||||
|
|
|
@ -639,6 +639,74 @@ class MxType<ValueType vt, string prefix, string postfix,
|
|||
PatFrag Load = load;
|
||||
}
|
||||
|
||||
// Provides an alternative way to access the MxOperand and
|
||||
// patterns w.r.t a specific addressing mode.
|
||||
class MxOpBundle<int size, MxOperand op, ComplexPattern pat> {
|
||||
int Size = size;
|
||||
MxOperand Op = op;
|
||||
ComplexPattern Pat = pat;
|
||||
}
|
||||
|
||||
class MxImmOpBundle<int size, MxOperand op, PatFrag pat>
|
||||
: MxOpBundle<size, op, ?> {
|
||||
PatFrag ImmPat = pat;
|
||||
}
|
||||
|
||||
// TODO: We can use MxOp<S>AddrMode_<AM> in more places to
|
||||
// replace MxType-based operand factoring.
|
||||
foreach size = [8, 16, 32] in {
|
||||
// Dn
|
||||
def MxOp#size#AddrMode_d
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxDRD"#size), ?>;
|
||||
|
||||
// (An)
|
||||
def MxOp#size#AddrMode_j
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxARI"#size), MxCP_ARI>;
|
||||
|
||||
// (An)+
|
||||
def MxOp#size#AddrMode_o
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxARIPI"#size), MxCP_ARIPI>;
|
||||
|
||||
// -(An)
|
||||
def MxOp#size#AddrMode_e
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxARIPD"#size), MxCP_ARIPD>;
|
||||
|
||||
// (i,An)
|
||||
def MxOp#size#AddrMode_p
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxARID"#size), MxCP_ARID>;
|
||||
|
||||
// (i,An,Xn)
|
||||
def MxOp#size#AddrMode_f
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxARII"#size), MxCP_ARII>;
|
||||
|
||||
// (ABS).L
|
||||
def MxOp#size#AddrMode_b
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxAL"#size), MxCP_AL>;
|
||||
|
||||
// (i,PC)
|
||||
def MxOp#size#AddrMode_q
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxPCD"#size), MxCP_PCD>;
|
||||
|
||||
// (i,PC,Xn)
|
||||
def MxOp#size#AddrMode_k
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxPCI"#size), MxCP_PCI>;
|
||||
|
||||
// #imm
|
||||
def MxOp#size#AddrMode_i
|
||||
: MxImmOpBundle<size, !cast<MxOperand>("Mxi"#size#"imm"),
|
||||
!cast<PatFrag>("MximmSExt"#size)>;
|
||||
} // foreach size = [8, 16, 32]
|
||||
|
||||
foreach size = [16, 32] in {
|
||||
// An
|
||||
def MxOp#size#AddrMode_a
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxARD"#size), ?>;
|
||||
|
||||
// Xn
|
||||
def MxOp#size#AddrMode_r
|
||||
: MxOpBundle<size, !cast<MxOperand>("MxXRD"#size), ?>;
|
||||
} // foreach size = [16, 32]
|
||||
|
||||
class MxType8Class<string rLet, MxOperand reg>
|
||||
: MxType<i8, "b", "", rLet, reg,
|
||||
MxARI8, MxCP_ARI,
|
||||
|
|
|
@ -102,9 +102,8 @@ define void @test5() nounwind {
|
|||
; CHECK-LABEL: test5:
|
||||
; CHECK: ; %bb.0: ; %entry
|
||||
; CHECK-NEXT: lea (dst6,%pc), %a0
|
||||
; CHECK-NEXT: lea (ptr6,%pc), %a1
|
||||
; CHECK-NEXT: move.l %a0, (%a1)
|
||||
; CHECK-NEXT: move.l (src6,%pc), (%a0)
|
||||
; CHECK-NEXT: move.l %a0, (ptr6,%pc)
|
||||
; CHECK-NEXT: move.l (src6,%pc), (dst6,%pc)
|
||||
; CHECK-NEXT: rts
|
||||
entry:
|
||||
store i32* @dst6, i32** @ptr6
|
||||
|
|
|
@ -11,9 +11,8 @@ define void @test0() nounwind {
|
|||
; CHECK-LABEL: test0:
|
||||
; CHECK: ; %bb.0: ; %entry
|
||||
; CHECK-NEXT: lea (dst,%pc), %a0
|
||||
; CHECK-NEXT: lea (ptr,%pc), %a1
|
||||
; CHECK-NEXT: move.l %a0, (%a1)
|
||||
; CHECK-NEXT: move.l (src,%pc), (%a0)
|
||||
; CHECK-NEXT: move.l %a0, (ptr,%pc)
|
||||
; CHECK-NEXT: move.l (src,%pc), (dst,%pc)
|
||||
; CHECK-NEXT: rts
|
||||
entry:
|
||||
store i32* @dst, i32** @ptr
|
||||
|
@ -30,9 +29,8 @@ define void @test1() nounwind {
|
|||
; CHECK-LABEL: test1:
|
||||
; CHECK: ; %bb.0: ; %entry
|
||||
; CHECK-NEXT: lea (dst2,%pc), %a0
|
||||
; CHECK-NEXT: lea (ptr2,%pc), %a1
|
||||
; CHECK-NEXT: move.l %a0, (%a1)
|
||||
; CHECK-NEXT: move.l (src2,%pc), (%a0)
|
||||
; CHECK-NEXT: move.l %a0, (ptr2,%pc)
|
||||
; CHECK-NEXT: move.l (src2,%pc), (dst2,%pc)
|
||||
; CHECK-NEXT: rts
|
||||
entry:
|
||||
store i32* @dst2, i32** @ptr2
|
||||
|
@ -65,8 +63,7 @@ define void @test3() nounwind {
|
|||
; CHECK-NEXT: suba.l #4, %sp
|
||||
; CHECK-NEXT: jsr afoo@PLT
|
||||
; CHECK-NEXT: move.l %d0, %a0
|
||||
; CHECK-NEXT: lea (pfoo,%pc), %a1
|
||||
; CHECK-NEXT: move.l %a0, (%a1)
|
||||
; CHECK-NEXT: move.l %a0, (pfoo,%pc)
|
||||
; CHECK-NEXT: jsr (%a0)
|
||||
; CHECK-NEXT: adda.l #4, %sp
|
||||
; CHECK-NEXT: rts
|
||||
|
@ -100,9 +97,8 @@ define void @test5() nounwind {
|
|||
; CHECK-LABEL: test5:
|
||||
; CHECK: ; %bb.0: ; %entry
|
||||
; CHECK-NEXT: lea (dst6,%pc), %a0
|
||||
; CHECK-NEXT: lea (ptr6,%pc), %a1
|
||||
; CHECK-NEXT: move.l %a0, (%a1)
|
||||
; CHECK-NEXT: move.l (src6,%pc), (%a0)
|
||||
; CHECK-NEXT: move.l %a0, (ptr6,%pc)
|
||||
; CHECK-NEXT: move.l (src6,%pc), (dst6,%pc)
|
||||
; CHECK-NEXT: rts
|
||||
entry:
|
||||
store i32* @dst6, i32** @ptr6
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
# RUN: llvm-mc -disassemble -triple m68k %s | FileCheck %s
|
||||
# Disable this particular test until migration to the new code emitter is
|
||||
# finished.
|
||||
# XFAIL: *
|
||||
|
||||
# CHECK: move.l %a1, %a0
|
||||
0x20 0x49
|
||||
|
|
Loading…
Reference in New Issue