Index: llvm/lib/Target/M68k/CMakeLists.txt =================================================================== --- llvm/lib/Target/M68k/CMakeLists.txt +++ llvm/lib/Target/M68k/CMakeLists.txt @@ -8,6 +8,7 @@ tablegen(LLVM M68kGenInstrInfo.inc -gen-instr-info) tablegen(LLVM M68kGenSubtargetInfo.inc -gen-subtarget) tablegen(LLVM M68kGenMCCodeBeads.inc -gen-code-beads) +tablegen(LLVM M68kGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM M68kGenMCPseudoLowering.inc -gen-pseudo-lowering) tablegen(LLVM M68kGenDAGISel.inc -gen-dag-isel) tablegen(LLVM M68kGenCallingConv.inc -gen-callingconv) Index: llvm/lib/Target/M68k/M68kInstrArithmetic.td =================================================================== --- llvm/lib/Target/M68k/M68kInstrArithmetic.td +++ llvm/lib/Target/M68k/M68kInstrArithmetic.td @@ -28,58 +28,31 @@ //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// -// Encoding +// OPMODE Encoding //===----------------------------------------------------------------------===// +class MxOpModeEncoding encoding> { + bits<3> Value = encoding; +} -/// Encoding for Normal forms -/// ---------------------------------------------------- -/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0 -/// ---------------------------------------------------- -/// | | | EFFECTIVE ADDRESS -/// x x x x | REG | OP MODE | MODE | REG -/// ---------------------------------------------------- -class MxArithEncoding - : MxEncoding; - -/// Encoding for Extended forms -/// ------------------------------------------------------ -/// F E D C | B A 9 | 8 | 7 6 | 5 4 | 3 | 2 1 0 -/// ------------------------------------------------------ -/// x x x x | REG Rx | 1 | SIZE | 0 0 | M | REG Ry -/// ------------------------------------------------------ -/// Rx - destination -/// Ry - source -/// M - address mode switch -class MxArithXEncoding - : MxEncoding, SIZE, MxBead1Bit<0b1>, DST, CMD>; - -/// Encoding for Immediate forms -/// --------------------------------------------------- -/// F E D C B A 9 8 | 7 6 | 5 4 3 | 2 1 0 -/// --------------------------------------------------- -/// | | EFFECTIVE ADDRESS -/// x x x x x x x x | SIZE | MODE | REG -/// --------------------------------------------------- -/// 16-BIT WORD DATA | 8-BIT BYTE DATA -/// --------------------------------------------------- -/// 32-BIT LONG DATA -/// --------------------------------------------------- -/// NOTE It is used to store an immediate to memory, imm-to-reg are handled with -/// normal version -class MxArithImmEncoding - : MxEncoding, - // Source - SRC_EXT.Imm, SRC_EXT.B8, SRC_EXT.Scale, - SRC_EXT.WL, SRC_EXT.DAReg, - // Destination - DST_EXT.Imm, DST_EXT.B8, DST_EXT.Scale, - DST_EXT.WL, DST_EXT.DAReg>; +// op EA, Dn +def MxOpMode8_d_EA : MxOpModeEncoding<0b000>; +def MxOpMode16_d_EA : MxOpModeEncoding<0b001>; +def MxOpMode32_d_EA : MxOpModeEncoding<0b010>; + +// op Dn, EA +def MxOpMode8_EA_d : MxOpModeEncoding<0b100>; +def MxOpMode16_EA_d : MxOpModeEncoding<0b101>; +def MxOpMode32_EA_d : MxOpModeEncoding<0b110>; + +// op EA, An +def MxOpMode16_a_EA : MxOpModeEncoding<0b011>; +def MxOpMode32_a_EA : MxOpModeEncoding<0b111>; +//===----------------------------------------------------------------------===// +// Encoding +//===----------------------------------------------------------------------===// + //===----------------------------------------------------------------------===// // Add/Sub //===----------------------------------------------------------------------===// @@ -88,16 +61,18 @@ let Constraints = "$src = $dst" in { // $reg, $ccr <- $reg op $reg -class MxBiArOp_RFRR_xEA CMD, MxBead REG> +class MxBiArOp_R_RR_xEA CMD> : MxInst<(outs DST_TYPE.ROp:$dst), (ins DST_TYPE.ROp:$src, SRC_TYPE.ROp:$opd), MN#"."#DST_TYPE.Prefix#"\t$opd, $dst", - [(set DST_TYPE.VT:$dst, CCR, (NODE DST_TYPE.VT:$src, SRC_TYPE.VT:$opd))], - MxArithEncoding, - !cast("MxOpMode"#DST_TYPE.Size#DST_TYPE.RLet#"EA"), - REG, - !cast("MxEncEA"#SRC_TYPE.RLet#"_2"), - MxExtEmpty>>; + [(set DST_TYPE.VT:$dst, CCR, (NODE DST_TYPE.VT:$src, SRC_TYPE.VT:$opd))]> { + let Inst = (descend + CMD, (operand "$dst", 3), + !cast("MxOpMode"#DST_TYPE.Size#"_"#DST_TYPE.RLet#"_EA").Value, + (descend /*MODE without last bit*/0b00, + /*REGISTER prefixed with D/A bit*/(operand "$opd", 4)) + ); +} /// This Op is similar to the one above except it uses reversed opmode, some /// commands(e.g. eor) do not support dEA or rEA modes and require EAd for @@ -105,177 +80,187 @@ /// NOTE when using dd commands it is irrelevant which opmode to use(as it seems) /// but some opcodes support address register and some do not which creates this /// mess. -class MxBiArOp_RFRR_EAd CMD> +class MxBiArOp_R_RR_EAd CMD> : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd), MN#"."#TYPE.Prefix#"\t$opd, $dst", - [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd))], - MxArithEncoding, - !cast("MxOpMode"#TYPE.Size#"EAd"), - MxBeadDReg<2>, MxEncEAd_0, MxExtEmpty>>; + [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd))]> { + let Inst = (descend + CMD, (operand "$opd", 3), + !cast("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value, + /*Destination can only be a data register*/ + /*MODE*/0b000, + /*REGISTER*/(operand "$dst", 3)); +} // $reg <- $reg op $imm -class MxBiArOp_RFRI_xEA CMD> +class MxBiArOp_R_RI_xEA CMD> : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd), MN#"."#TYPE.Prefix#"\t$opd, $dst", - [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))], - MxArithEncoding, - !cast("MxOpMode"#TYPE.Size#TYPE.RLet#"EA"), - MxBeadDReg<0>, MxEncEAi, - !cast("MxExtI"#TYPE.Size#"_2")>>; + [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> { + let Inst = (ascend + (descend CMD, (operand "$dst", 3), + !cast("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value, + MxEncAddrMode_i<"opd", TYPE.Size>.EA), + MxEncAddrMode_i<"opd", TYPE.Size>.Supplement + ); +} // Again, there are two ways to write an immediate to Dn register either dEA // opmode or using *I encoding, and again some instrucitons also support address // registers some do not. -class MxBiArOp_RFRI CMD> +class MxBiArOp_R_RI CMD> : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd), MN#"i."#TYPE.Prefix#"\t$opd, $dst", - [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))], - MxArithImmEncoding, !cast("MxEncSize"#TYPE.Size), - !cast("MxEncEA"#TYPE.RLet#"_0"), MxExtEmpty, - !cast("MxExtI"#TYPE.Size#"_2")>>; + [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> { + let Inst = (ascend + (descend 0b0000, CMD, + !cast("MxNewEncSize"#TYPE.Size).Value, + // The destination cannot be address register, so it's always + // the MODE for data register direct mode. + /*MODE*/0b000, + /*REGISTER*/(operand "$dst", 3)), + // Source (i.e. immediate value) encoding + MxEncAddrMode_i<"opd", TYPE.Size>.Supplement + ); +} let mayLoad = 1 in -class MxBiArOp_RFRM CMD, MxEncEA EA, MxEncExt EXT> +class MxBiArOp_R_RM CMD, MxEncMemOp SRC_ENC> : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, OPD:$opd), MN#"."#TYPE.Prefix#"\t$opd, $dst", - [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, (TYPE.Load PAT:$opd)))], - MxArithEncoding, - !cast("MxOpMode"#TYPE.Size#TYPE.RLet#"EA"), - MxBeadDReg<0>, EA, EXT>>; - + [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, (TYPE.Load PAT:$opd)))]> { + let Inst = (ascend + (descend CMD, (operand "$dst", 3), + !cast("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value, + SRC_ENC.EA), + SRC_ENC.Supplement + ); +} } // Constraints let mayLoad = 1, mayStore = 1 in { // FIXME MxBiArOp_FMR/FMI cannot consume CCR from MxAdd/MxSub which leads for // MxAdd to survive the match and subsequent mismatch. -class MxBiArOp_FMR CMD, MxEncEA EA, MxEncExt EXT> +class MxBiArOp_MR CMD, MxEncMemOp DST_ENC> : MxInst<(outs), (ins MEMOpd:$dst, TYPE.ROp:$opd), - MN#"."#TYPE.Prefix#"\t$opd, $dst", - [], - MxArithEncoding, - !cast("MxOpMode"#TYPE.Size#"EA"#TYPE.RLet), - MxBeadDReg<1>, EA, EXT>>; - -class MxBiArOp_FMI CMD, MxEncEA MEMEA, MxEncExt MEMExt> + MN#"."#TYPE.Prefix#"\t$opd, $dst", []> { + let Inst = (ascend + (descend CMD, (operand "$opd", 3), + !cast("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value, + DST_ENC.EA), + DST_ENC.Supplement + ); +} + +class MxBiArOp_MI CMD, MxEncMemOp DST_ENC> : MxInst<(outs), (ins MEMOpd:$dst, TYPE.IOp:$opd), - MN#"."#TYPE.Prefix#"\t$opd, $dst", - [], - MxArithImmEncoding, - !cast("MxEncSize"#TYPE.Size), - MEMEA, MEMExt, - !cast("MxExtI"#TYPE.Size#"_1")>>; + MN#"."#TYPE.Prefix#"\t$opd, $dst", []> { + let Inst = (ascend + (descend 0b0000, CMD, + !cast("MxNewEncSize"#TYPE.Size).Value, + DST_ENC.EA), + // Source (i.e. immediate value) encoding + MxEncAddrMode_i<"opd", TYPE.Size>.Supplement, + // Destination encoding + DST_ENC.Supplement + ); +} } // mayLoad, mayStore } // Defs = [CCR] multiclass MxBiArOp_DF CMD, bits<4> CMDI> { - // op $mem, $reg - def NAME#"8dk" : MxBiArOp_RFRM; - def NAME#"16dk" : MxBiArOp_RFRM; - def NAME#"32dk" : MxBiArOp_RFRM; - - def NAME#"8dq" : MxBiArOp_RFRM; - def NAME#"16dq" : MxBiArOp_RFRM; - def NAME#"32dq" : MxBiArOp_RFRM; - - def NAME#"8dp" : MxBiArOp_RFRM; - def NAME#"16dp" : MxBiArOp_RFRM; - def NAME#"32dp" : MxBiArOp_RFRM; - - def NAME#"8df" : MxBiArOp_RFRM; - def NAME#"16df" : MxBiArOp_RFRM; - def NAME#"32df" : MxBiArOp_RFRM; - - def NAME#"8dj" : MxBiArOp_RFRM; - def NAME#"16dj" : MxBiArOp_RFRM; - def NAME#"32dj" : MxBiArOp_RFRM; - - // op $imm, $reg - def NAME#"8di" : MxBiArOp_RFRI_xEA; - def NAME#"16di" : MxBiArOp_RFRI_xEA; - def NAME#"32di" : MxBiArOp_RFRI_xEA; - - // op $reg, $mem - def NAME#"8pd" : MxBiArOp_FMR; - def NAME#"16pd" : MxBiArOp_FMR; - def NAME#"32pd" : MxBiArOp_FMR; - - def NAME#"8fd" : MxBiArOp_FMR; - def NAME#"16fd" : MxBiArOp_FMR; - def NAME#"32fd" : MxBiArOp_FMR; - - def NAME#"8jd" : MxBiArOp_FMR; - def NAME#"16jd" : MxBiArOp_FMR; - def NAME#"32jd" : MxBiArOp_FMR; - - // op $imm, $mem - def NAME#"8pi" : MxBiArOp_FMI; - def NAME#"16pi" : MxBiArOp_FMI; - def NAME#"32pi" : MxBiArOp_FMI; - - def NAME#"8fi" : MxBiArOp_FMI; - def NAME#"16fi" : MxBiArOp_FMI; - def NAME#"32fi" : MxBiArOp_FMI; - - def NAME#"8ji" : MxBiArOp_FMI; - def NAME#"16ji" : MxBiArOp_FMI; - def NAME#"32ji" : MxBiArOp_FMI; - - def NAME#"16dr" : MxBiArOp_RFRR_xEA>; - def NAME#"32dr" : MxBiArOp_RFRR_xEA>; - - let isCommutable = isComm in { - - def NAME#"8dd" : MxBiArOp_RFRR_xEA>; - def NAME#"16dd" : MxBiArOp_RFRR_xEA>; - def NAME#"32dd" : MxBiArOp_RFRR_xEA>; - - } // isComm + foreach SZ = [8, 16, 32] in { + // op $mem, $reg + def NAME#SZ#"dk" : MxBiArOp_R_RM("MxType"#SZ#"d"), + !cast("MxType"#SZ).KOp, + !cast("MxType"#SZ).KPat, + CMD, MxEncAddrMode_k<"opd">>; + + def NAME#SZ#"dq" : MxBiArOp_R_RM("MxType"#SZ#"d"), + !cast("MxType"#SZ).QOp, + !cast("MxType"#SZ).QPat, + CMD, MxEncAddrMode_q<"opd">>; + + def NAME#SZ#"dp" : MxBiArOp_R_RM("MxType"#SZ#"d"), + !cast("MxType"#SZ).POp, + !cast("MxType"#SZ).PPat, + CMD, MxEncAddrMode_p<"opd">>; + + def NAME#SZ#"df" : MxBiArOp_R_RM("MxType"#SZ#"d"), + !cast("MxType"#SZ).FOp, + !cast("MxType"#SZ).FPat, + CMD, MxEncAddrMode_f<"opd">>; + + def NAME#SZ#"dj" : MxBiArOp_R_RM("MxType"#SZ#"d"), + !cast("MxType"#SZ).JOp, + !cast("MxType"#SZ).JPat, + CMD, MxEncAddrMode_j<"opd">>; + // op $imm, $reg + def NAME#SZ#"di" : MxBiArOp_R_RI_xEA("MxType"#SZ#"d"), + CMD>; + // op $reg, $mem + def NAME#SZ#"pd" : MxBiArOp_MR("MxType"#SZ#"d"), + !cast("MxType"#SZ).POp, + !cast("MxType"#SZ).PPat, + CMD, MxEncAddrMode_p<"dst">>; + + def NAME#SZ#"fd" : MxBiArOp_MR("MxType"#SZ#"d"), + !cast("MxType"#SZ).FOp, + !cast("MxType"#SZ).FPat, + CMD, MxEncAddrMode_f<"dst">>; + + def NAME#SZ#"jd" : MxBiArOp_MR("MxType"#SZ#"d"), + !cast("MxType"#SZ).JOp, + !cast("MxType"#SZ).JPat, + CMD, MxEncAddrMode_j<"dst">>; + // op $imm, $mem + def NAME#SZ#"pi" : MxBiArOp_MI("MxType"#SZ), + !cast("MxType"#SZ).POp, + !cast("MxType"#SZ).PPat, + CMDI, MxEncAddrMode_p<"dst">>; + + def NAME#SZ#"fi" : MxBiArOp_MI("MxType"#SZ), + !cast("MxType"#SZ).FOp, + !cast("MxType"#SZ).FPat, + CMDI, MxEncAddrMode_f<"dst">>; + + def NAME#SZ#"ji" : MxBiArOp_MI("MxType"#SZ), + !cast("MxType"#SZ).JOp, + !cast("MxType"#SZ).JPat, + CMDI, MxEncAddrMode_j<"dst">>; + // op $reg, $reg + let isCommutable = isComm in + def NAME#SZ#"dd" : MxBiArOp_R_RR_xEA("MxType"#SZ#"d"), + !cast("MxType"#SZ#"d"), + CMD>; + } // foreach SZ + + foreach SZ = [16, 32] in + def NAME#SZ#"dr" : MxBiArOp_R_RR_xEA("MxType"#SZ#"d"), + !cast("MxType"#SZ#"r"), + CMD>; } // MxBiArOp_DF @@ -287,20 +272,19 @@ multiclass MxBiArOp_AF CMD, bits<4> CMDI> { - def NAME#"32ak" : MxBiArOp_RFRM; - def NAME#"32aq" : MxBiArOp_RFRM; - def NAME#"32af" : MxBiArOp_RFRM; - def NAME#"32ap" : MxBiArOp_RFRM; - def NAME#"32aj" : MxBiArOp_RFRM; - def NAME#"32ai" : MxBiArOp_RFRI_xEA; - - def NAME#"32ar" : MxBiArOp_RFRR_xEA>; + def NAME#"32ak" : MxBiArOp_R_RM>; + def NAME#"32aq" : MxBiArOp_R_RM>; + def NAME#"32af" : MxBiArOp_R_RM>; + def NAME#"32ap" : MxBiArOp_R_RM>; + def NAME#"32aj" : MxBiArOp_R_RM>; + def NAME#"32ai" : MxBiArOp_R_RI_xEA; + + def NAME#"32ar" : MxBiArOp_R_RR_xEA; } // MxBiArOp_AF @@ -316,25 +300,31 @@ let Constraints = "$src = $dst" in { // $reg, ccr <- $reg op $reg op ccr -class MxBiArOp_RFRRF CMD> +class MxBiArOp_R_RRX CMD> : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd), MN#"."#TYPE.Prefix#"\t$opd, $dst", - [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd, CCR))], - MxArithXEncoding, - !cast("MxEncSize"#TYPE.Size), - MxBead1Bit<0>, MxBeadDReg<2>, MxBeadDReg<0>>>; - + [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd, CCR))]> { + let Inst = (descend CMD, + // Destination register + (operand "$dst", 3), + 0b1, + // SIZE + !cond(!eq(TYPE.Size, 8): 0b00, + !eq(TYPE.Size, 16): 0b01, + !eq(TYPE.Size, 32): 0b10), + 0b00, /*R/M*/0b0, + // Source register + (operand "$opd", 3) + ); +} } // Constraints } // Uses, Defs multiclass MxBiArOp_RFF CMD> { let isCommutable = isComm in { - - def NAME#"8dd" : MxBiArOp_RFRRF; - def NAME#"16dd" : MxBiArOp_RFRRF; - def NAME#"32dd" : MxBiArOp_RFRRF; - + foreach SZ = [8, 16, 32] in + def NAME#SZ#"dd" : MxBiArOp_R_RRX("MxType"#SZ#"d"), CMD>; } // isComm } // MxBiArOp_RFF @@ -352,19 +342,16 @@ defm OR : MxBiArOp_DF<"or", MxOr, 1, 0x8, 0x0>; multiclass MxBiArOp_DF_EAd CMD, bits<4> CMDI> { - - let isCommutable = 1 in { - - def NAME#"8dd" : MxBiArOp_RFRR_EAd; - def NAME#"16dd" : MxBiArOp_RFRR_EAd; - def NAME#"32dd" : MxBiArOp_RFRR_EAd; - - } // isCommutable = 1 - - def NAME#"8di" : MxBiArOp_RFRI; - def NAME#"16di" : MxBiArOp_RFRI; - def NAME#"32di" : MxBiArOp_RFRI; - + foreach SZ = [8, 16, 32] in { + let isCommutable = 1 in + def NAME#SZ#"dd" : MxBiArOp_R_RR_EAd("MxType"#SZ#"d"), + CMD>; + + def NAME#SZ#"di" : MxBiArOp_R_RI("MxType"#SZ#"d"), + CMDI>; + } // foreach SZ } // MxBiArOp_DF_EAd defm XOR : MxBiArOp_DF_EAd<"eor", MxXor, 0xB, 0xA>; @@ -375,84 +362,112 @@ //===----------------------------------------------------------------------===// let Defs = [CCR] in { -class MxCmp_RR> +class MxCmp_RR : MxInst<(outs), (ins LHS_TYPE.ROp:$lhs, RHS_TYPE.ROp:$rhs), "cmp."#RHS_TYPE.Prefix#"\t$lhs, $rhs", - [(set CCR, (MxCmp LHS_TYPE.VT:$lhs, RHS_TYPE.VT:$rhs))], - MxArithEncoding, - !cast("MxOpMode"#RHS_TYPE.Size#RHS_TYPE.RLet#"EA"), - REG, - !cast("MxEncEA"#LHS_TYPE.RLet#"_0"), - MxExtEmpty>>; + [(set CCR, (MxCmp LHS_TYPE.VT:$lhs, RHS_TYPE.VT:$rhs))]> { + let Inst = (descend 0b1011, + // REGISTER + (operand "$rhs", 3), + // OPMODE + !cast("MxOpMode"#RHS_TYPE.Size#"_"#RHS_TYPE.RLet#"_EA").Value, + // MODE without last bit + 0b00, + // REGISTER prefixed by D/A bit + (operand "$lhs", 4) + ); +} class MxCmp_RI : MxInst<(outs), (ins TYPE.IOp:$imm, TYPE.ROp:$reg), "cmpi."#TYPE.Prefix#"\t$imm, $reg", - [(set CCR, (MxCmp TYPE.IPat:$imm, TYPE.VT:$reg))], - MxArithImmEncoding, - !cast("MxEncSize"#TYPE.Size), - MxEncEAd_1, MxExtEmpty, - !cast("MxExtI"#TYPE.Size#"_0")>>; + [(set CCR, (MxCmp TYPE.IPat:$imm, TYPE.VT:$reg))]> { + let Inst = (ascend + (descend 0b00001100, + !cast("MxNewEncSize"#TYPE.Size).Value, + // The destination cannot be address register, so it's always + // the MODE for data register direct mode. + /*MODE*/0b000, + /*REGISTER*/(operand "$reg", 3)), + // Source (i.e. immediate value) encoding + MxEncAddrMode_i<"imm", TYPE.Size>.Supplement + ); +} let mayLoad = 1 in { class MxCmp_MI + MxEncMemOp MEM_ENC> : MxInst<(outs), (ins TYPE.IOp:$imm, MEMOpd:$mem), "cmpi."#TYPE.Prefix#"\t$imm, $mem", - [(set CCR, (MxCmp TYPE.IPat:$imm, (load MEMPat:$mem)))], - MxArithImmEncoding, - !cast("MxEncSize"#TYPE.Size), - EA, EXT, - !cast("MxExtI"#TYPE.Size#"_0")>>; + [(set CCR, (MxCmp TYPE.IPat:$imm, (load MEMPat:$mem)))]> { + let Inst = (ascend + (descend 0b00001100, + !cast("MxNewEncSize"#TYPE.Size).Value, + MEM_ENC.EA), + // Source (i.e. immediate value) encoding + MxEncAddrMode_i<"imm", TYPE.Size>.Supplement, + // Destination (i.e. memory operand) encoding + MEM_ENC.Supplement + ); +} +// FIXME: What about abs.W? class MxCmp_BI : MxInst<(outs), (ins TYPE.IOp:$imm, MxAL32:$abs), "cmpi."#TYPE.Prefix#"\t$imm, $abs", [(set CCR, (MxCmp TYPE.IPat:$imm, - (load (i32 (MxWrapper tglobaladdr:$abs)))))], - MxArithImmEncoding, - !cast("MxEncSize"#TYPE.Size), - MxEncEAb, MxExtI32_1, - !cast("MxExtI"#TYPE.Size#"_0")>>; + (load (i32 (MxWrapper tglobaladdr:$abs)))))]> { + defvar AbsEncoding = MxEncAddrMode_abs<"abs", true>; + let Inst = (ascend + (descend 0b00001100, + !cast("MxNewEncSize"#TYPE.Size).Value, + AbsEncoding.EA), + // Source (i.e. immediate value) encoding + MxEncAddrMode_i<"imm", TYPE.Size>.Supplement, + // Destination (i.e. memory operand) encoding + AbsEncoding.Supplement + ); +} class MxCmp_RM + MxEncMemOp MEM_ENC> : MxInst<(outs), (ins TYPE.ROp:$reg, MEMOpd:$mem), "cmp."#TYPE.Prefix#"\t$mem, $reg", - [(set CCR, (MxCmp (load MEMPat:$mem), TYPE.ROp:$reg))], - MxArithEncoding, - !cast("MxOpMode"#TYPE.Size#"dEA"), - MxBeadDReg<0>, EA, EXT>>; + [(set CCR, (MxCmp (load MEMPat:$mem), TYPE.ROp:$reg))]> { + let Inst = (ascend + (descend 0b1011, + // REGISTER + (operand "$reg", 3), + // OPMODE + !cast("MxOpMode"#TYPE.Size#"_d_EA").Value, + MEM_ENC.EA), + MEM_ENC.Supplement + ); +} } // let mayLoad = 1 } // let Defs = [CCR] multiclass MMxCmp_RM { - def NAME#TYPE.KOp.Letter : MxCmp_RM; - def NAME#TYPE.QOp.Letter : MxCmp_RM; - def NAME#TYPE.POp.Letter : MxCmp_RM; - def NAME#TYPE.FOp.Letter : MxCmp_RM; - def NAME#TYPE.JOp.Letter : MxCmp_RM; + def NAME#TYPE.KOp.Letter : MxCmp_RM>; + def NAME#TYPE.QOp.Letter : MxCmp_RM>; + def NAME#TYPE.POp.Letter : MxCmp_RM>; + def NAME#TYPE.FOp.Letter : MxCmp_RM>; + def NAME#TYPE.JOp.Letter : MxCmp_RM>; } multiclass MMxCmp_MI { - def NAME#TYPE.KOp.Letter#"i" : MxCmp_MI; - def NAME#TYPE.QOp.Letter#"i" : MxCmp_MI; - def NAME#TYPE.POp.Letter#"i" : MxCmp_MI; - def NAME#TYPE.FOp.Letter#"i" : MxCmp_MI; - def NAME#TYPE.JOp.Letter#"i" : MxCmp_MI; + def NAME#TYPE.KOp.Letter#"i" : MxCmp_MI>; + def NAME#TYPE.QOp.Letter#"i" : MxCmp_MI>; + def NAME#TYPE.POp.Letter#"i" : MxCmp_MI>; + def NAME#TYPE.FOp.Letter#"i" : MxCmp_MI>; + def NAME#TYPE.JOp.Letter#"i" : MxCmp_MI>; } foreach S = [8, 16, 32] in { @@ -481,25 +496,31 @@ // EXT //===----------------------------------------------------------------------===// -def MxExtOpmode_wb : MxBead3Bits<0b010>; -def MxExtOpmode_lw : MxBead3Bits<0b011>; -def MxExtOpmode_lb : MxBead3Bits<0b111>; - /// --------------------------------------------------- /// F E D C B A 9 | 8 7 6 | 5 4 3 | 2 1 0 /// --------------------------------------------------- /// 0 1 0 0 1 0 0 | OPMODE | 0 0 0 | REG /// --------------------------------------------------- -class MxExtEncoding - : MxEncoding, MxBead3Bits<0b000>, OPMODE, - MxBead3Bits<0b100>, MxBead4Bits<0b0100>>; - let Defs = [CCR] in let Constraints = "$src = $dst" in class MxExt : MxInst<(outs TO.ROp:$dst), (ins TO.ROp:$src), - "ext."#TO.Prefix#"\t$src", [], - MxExtEncoding("MxExtOpmode_"#TO.Prefix#FROM.Prefix)>>; + "ext."#TO.Prefix#"\t$src", []> { + let Inst = (descend 0b0100100, + // OPMODE + !cond( + // byte -> word + !and(!eq(FROM.Size, 8), !eq(TO.Size, 16)): 0b010, + // word -> long + !and(!eq(FROM.Size, 16), !eq(TO.Size, 32)): 0b011, + // byte -> long + !and(!eq(FROM.Size, 8), !eq(TO.Size, 32)): 0b111 + ), + 0b000, + // REGISTER + (operand "$src", 3) + ); +} def EXT16 : MxExt; def EXT32 : MxExt; @@ -514,9 +535,6 @@ // DIV/MUL //===----------------------------------------------------------------------===// -def MxSDiMuOpmode : MxBead3Bits<0b111>; -def MxUDiMuOpmode : MxBead3Bits<0b011>; - /// Word operation: /// ---------------------------------------------------- /// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0 @@ -524,40 +542,45 @@ /// | | | EFFECTIVE ADDRESS /// x x x x | REG | OP MODE | MODE | REG /// ---------------------------------------------------- -class MxDiMuEncoding - : MxEncoding, CMD, - EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>; - let Defs = [CCR] in { let Constraints = "$src = $dst" in { -// $reg <- $reg op $reg -class MxDiMuOp_DD CMD, MxBead3Bits OPMODE, +// $dreg <- $dreg op $dreg +class MxDiMuOp_DD CMD, bit SIGNED = false, MxOperand DST, MxOperand OPD> - : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", [], - MxDiMuEncoding, OPMODE, MxEncEAd_2, MxExtEmpty>>; + : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> { + let Inst = (descend CMD, + // REGISTER + (operand "$dst", 3), + !if(SIGNED, 0b111, 0b011), + /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3) + ); +} // $reg <- $reg op $imm -class MxDiMuOp_DI CMD, MxBead3Bits OPMODE, +class MxDiMuOp_DI CMD, bit SIGNED = false, MxOperand DST, MxOperand OPD> - : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", [], - MxDiMuEncoding, OPMODE, MxEncEAi, MxExtI16_2>>; + : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> { + // FIXME: Support immediates with different widths. + defvar ImmEnc = MxEncAddrMode_i<"opd", 16>; + let Inst = (ascend + (descend CMD, + // REGISTER + (operand "$dst", 3), + !if(SIGNED, 0b111, 0b011), ImmEnc.EA), + ImmEnc.Supplement + ); +} } // let Constraints } // Defs = [CCR] multiclass MxDiMuOp CMD, bit isComm = 0> { - let isCommutable = isComm in { - def "S"#NAME#"d32d16" : MxDiMuOp_DD; - def "U"#NAME#"d32d16" : MxDiMuOp_DD; + def "S"#NAME#"d32d16" : MxDiMuOp_DD; + def "U"#NAME#"d32d16" : MxDiMuOp_DD; } - def "S"#NAME#"d32i16" : MxDiMuOp_DI; - def "U"#NAME#"d32i16" : MxDiMuOp_DI; - + def "S"#NAME#"d32i16" : MxDiMuOp_DI; + def "U"#NAME#"d32i16" : MxDiMuOp_DI; } defm DIV : MxDiMuOp<"div", 0x8>; @@ -700,29 +723,35 @@ /// | | | EFFECTIVE ADDRESS /// 0 1 0 0 | x x x x | SIZE | MODE | REG /// ------------+------------+------+---------+--------- -class MxNEGEncoding - : MxEncoding, - EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>; - let Defs = [CCR] in { let Constraints = "$src = $dst" in { class MxNeg_D : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src), "neg."#TYPE.Prefix#"\t$dst", - [(set TYPE.VT:$dst, (ineg TYPE.VT:$src))], - MxNEGEncoding, - !cast("MxEncSize"#TYPE.Size), - MxEncEAd_0, MxExtEmpty>>; + [(set TYPE.VT:$dst, (ineg TYPE.VT:$src))]> { + let Inst = (descend 0b01000100, + /*SIZE*/!cast("MxNewEncSize"#TYPE.Size).Value, + //MODE without last bit + 0b00, + //REGISTER prefixed by D/A bit + (operand "$dst", 4) + ); +} let Uses = [CCR] in { class MxNegX_D : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src), "negx."#TYPE.Prefix#"\t$dst", - [(set TYPE.VT:$dst, (MxSubX 0, TYPE.VT:$src, CCR))], - MxNEGEncoding, - !cast("MxEncSize"#TYPE.Size), - MxEncEAd_0, MxExtEmpty>>; + [(set TYPE.VT:$dst, (MxSubX 0, TYPE.VT:$src, CCR))]> { + let Inst = (descend 0b01000000, + /*SIZE*/!cast("MxNewEncSize"#TYPE.Size).Value, + //MODE without last bit + 0b00, + //REGISTER prefixed by D/A bit + (operand "$dst", 4) + ); +} } } // let Constraints Index: llvm/lib/Target/M68k/M68kInstrFormats.td =================================================================== --- llvm/lib/Target/M68k/M68kInstrFormats.td +++ llvm/lib/Target/M68k/M68kInstrFormats.td @@ -200,6 +200,11 @@ MxBead DA = da; } +class MxEncMemOp { + dag EA = (ascend); + dag Supplement = (ascend); +} + // FIXME: Is there a way to factorize the addressing mode suffix (i.e. // 'r', 'd', 'a' etc.) and use something like multiclass to replace? def MxEncEAr_0: MxEncEA, MxBead2Bits<0b00>>; @@ -237,6 +242,93 @@ def MxEncEAk : MxEncEA, MxBead2Bits<0b11>, MxBead1Bit<1>>; def MxEncEAi : MxEncEA, MxBead2Bits<0b11>, MxBead1Bit<1>>; +class MxEncBriefExt { + dag Value = (descend + // D/A + REGISTER + (operand "$"#reg_opnd, 4), + // W/L + size_w_l, + // SCALE + !cond( + !eq(scale, 1) : 0b00, + !eq(scale, 2) : 0b01, + !eq(scale, 4) : 0b10, + !eq(scale, 8) : 0b11 + ), + 0b0, + // Displacement + (operand "$"#disp_opnd, 8) + ); +} + +class MxEncAddrMode_k : MxEncMemOp { + let EA = (descend /*MODE*/0b111, + /*REGISTER*/0b011); + + let Supplement = MxEncBriefExt.Value; +} + +class MxEncAddrMode_q : MxEncMemOp { + let EA = (descend /*MODE*/0b111, + /*REGISTER*/0b010); + + // 16-bit Displacement + let Supplement = (operand "$"#opnd_name, 16); +} + +class MxEncAddrMode_p : MxEncMemOp { + let EA = (descend /*MODE*/0b101, + /*REGISTER*/(operand "$"#opnd_name#".reg", 3)); + + // 16-bit Displacement + let Supplement = (operand "$"#opnd_name#".disp", 16); +} + +class MxEncAddrMode_f : MxEncMemOp { + let EA = (descend /*MODE*/0b110, + /*REGISTER*/(operand "$"#opnd_name#".reg", 3)); + + let Supplement = MxEncBriefExt.Value; +} + +class MxEncAddrMode_j : MxEncMemOp { + let EA = (descend /*MODE*/0b010, + /*REGISTER*/(operand "$"#reg_opnd, 3)); +} + +class MxEncAddrMode_i : MxEncMemOp { + let EA = (descend /*MODE*/0b111, + /*REGISTER*/0b100); + + // Immediate + let Supplement = + !cond( + !eq(size, 8) : (descend 0b00000000, (operand "$"#opnd_name, 8)), + !eq(size, 16) : (operand "$"#opnd_name, 16), + !eq(size, 32) : (ascend (slice "$"#opnd_name, 31, 16), + (slice "$"#opnd_name, 15, 0)) + ); +} + +// abs.W -> size_w_l = false +// abs.L -> size_w_l = true +class MxEncAddrMode_abs : MxEncMemOp { + let EA = (descend /*MODE*/0b111, + /*REGISTER*/0b00, size_w_l); + + // Absolute address + let Supplement = !if(size_w_l, + // abs.L + (ascend (slice "$"#opnd_name, 31, 16), + (slice "$"#opnd_name, 15, 0)), + // abs.W + (operand "$"#opnd_name, 16) + ); +} + // Allows you to specify each bit of opcode class MxEncOpMode { MxBead B0 = b0; @@ -332,6 +424,16 @@ def MxEncSize32 : MxEncSize<0b10>; def MxEncSize64 : MxEncSize<0b11>; +// TODO: Remove "New" in the name after the codebead-based +// representation is deprecated. +class MxNewEncSize value> { + bits<2> Value = value; +} +def MxNewEncSize8 : MxNewEncSize<0b00>; +def MxNewEncSize16 : MxNewEncSize<0b01>; +def MxNewEncSize32 : MxNewEncSize<0b10>; +def MxNewEncSize64 : MxNewEncSize<0b11>; + // M68k INSTRUCTION. Most instructions specify the location of an operand by // using the effective address field in the operation word. The effective address // is composed of two 3-bit fields: the mode field and the register field. The @@ -357,6 +459,7 @@ // Byte stream field bits<192> Beads = beads.Value; + dag Inst = (ascend); // Number of bytes let Size = 0; Index: llvm/lib/Target/M68k/M68kInstrInfo.td =================================================================== --- llvm/lib/Target/M68k/M68kInstrInfo.td +++ llvm/lib/Target/M68k/M68kInstrInfo.td @@ -291,13 +291,13 @@ // extension word. The reference is classified as a data reference with the // exception of the jump and jump-to-subroutine instructions. def MxARID : MxOpClass<"ARID">; -def MxARID8 : MxMemOp<(ops i16imm, AR32), MxSize8, "p", "printARID8Mem", MxARID>; -def MxARID16 : MxMemOp<(ops i16imm, AR32), MxSize16, "p", "printARID16Mem", MxARID>; -def MxARID32 : MxMemOp<(ops i16imm, AR32), MxSize32, "p", "printARID32Mem", MxARID>; +def MxARID8 : MxMemOp<(ops i16imm:$disp, AR32:$reg), MxSize8, "p", "printARID8Mem", MxARID>; +def MxARID16 : MxMemOp<(ops i16imm:$disp, AR32:$reg), MxSize16, "p", "printARID16Mem", MxARID>; +def MxARID32 : MxMemOp<(ops i16imm:$disp, AR32:$reg), MxSize32, "p", "printARID32Mem", MxARID>; -def MxARID8_TC : MxMemOp<(ops i16imm, AR32_TC), MxSize8, "p", "printARID8Mem", MxARID>; -def MxARID16_TC : MxMemOp<(ops i16imm, AR32_TC), MxSize16, "p", "printARID16Mem", MxARID>; -def MxARID32_TC : MxMemOp<(ops i16imm, AR32_TC), MxSize32, "p", "printARID32Mem", MxARID>; +def MxARID8_TC : MxMemOp<(ops i16imm:$disp, AR32_TC:$reg), MxSize8, "p", "printARID8Mem", MxARID>; +def MxARID16_TC : MxMemOp<(ops i16imm:$disp, AR32_TC:$reg), MxSize16, "p", "printARID16Mem", MxARID>; +def MxARID32_TC : MxMemOp<(ops i16imm:$disp, AR32_TC:$reg), MxSize32, "p", "printARID32Mem", MxARID>; // ADDRESS REGISTER INDIRECT WITH INDEX. This addressing mode requires one word // of extension. The address of the operand is the sum of the address in the @@ -306,13 +306,19 @@ // The reference is classified as a data reference with the exception of the // jump and jump-to-subroutine instructions def MxARII : MxOpClass<"ARII">; -def MxARII8 : MxMemOp<(ops i8imm, AR32, XR32), MxSize8, "f", "printARII8Mem", MxARII>; -def MxARII16 : MxMemOp<(ops i8imm, AR32, XR32), MxSize16, "f", "printARII16Mem", MxARII>; -def MxARII32 : MxMemOp<(ops i8imm, AR32, XR32), MxSize32, "f", "printARII32Mem", MxARII>; - -def MxARII8_TC : MxMemOp<(ops i8imm, AR32_TC, XR32_TC), MxSize8, "f", "printARII8Mem", MxARII>; -def MxARII16_TC : MxMemOp<(ops i8imm, AR32_TC, XR32_TC), MxSize16, "f", "printARII16Mem", MxARII>; -def MxARII32_TC : MxMemOp<(ops i8imm, AR32_TC, XR32_TC), MxSize32, "f", "printARII32Mem", MxARII>; +def MxARII8 : MxMemOp<(ops i8imm:$disp, AR32:$reg, XR32:$index), + MxSize8, "f", "printARII8Mem", MxARII>; +def MxARII16 : MxMemOp<(ops i8imm:$disp, AR32:$reg, XR32:$index), + MxSize16, "f", "printARII16Mem", MxARII>; +def MxARII32 : MxMemOp<(ops i8imm:$disp, AR32:$reg, XR32:$index), + MxSize32, "f", "printARII32Mem", MxARII>; + +def MxARII8_TC : MxMemOp<(ops i8imm:$disp, AR32_TC:$reg, XR32_TC:$index), + MxSize8, "f", "printARII8Mem", MxARII>; +def MxARII16_TC : MxMemOp<(ops i8imm:$disp, AR32_TC:$reg, XR32_TC:$index), + MxSize16, "f", "printARII16Mem", MxARII>; +def MxARII32_TC : MxMemOp<(ops i8imm:$disp, AR32_TC:$reg, XR32_TC:$index), + MxSize32, "f", "printARII32Mem", MxARII>; // ABSOLUTE SHORT ADDRESS. This addressing mode requires one word of extension. // The address of the operand is the extension word. The 16-bit address is sign @@ -360,9 +366,9 @@ // word, and the contents of the index register. The value in the program // counter is the address of the extension word. This reference is classified as // a program reference. -def MxPCI8 : MxMemOp<(ops i8imm, XR32), MxSize8, "k", "printPCI8Mem", MxPCI>; -def MxPCI16 : MxMemOp<(ops i8imm, XR32), MxSize16, "k", "printPCI16Mem", MxPCI>; -def MxPCI32 : MxMemOp<(ops i8imm, XR32), MxSize32, "k", "printPCI32Mem", MxPCI>; +def MxPCI8 : MxMemOp<(ops i8imm:$disp, XR32:$index), MxSize8, "k", "printPCI8Mem", MxPCI>; +def MxPCI16 : MxMemOp<(ops i8imm:$disp, XR32:$index), MxSize16, "k", "printPCI16Mem", MxPCI>; +def MxPCI32 : MxMemOp<(ops i8imm:$disp, XR32:$index), MxSize32, "k", "printPCI32Mem", MxPCI>; } // OPERAND_PCREL def MxImm : AsmOperandClass { Index: llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp =================================================================== --- llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp +++ llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp @@ -39,6 +39,15 @@ const MCInstrInfo &MCII; MCContext &Ctx; + void getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl &Fixups, + APInt &Inst, APInt &Scratch, + const MCSubtargetInfo &STI) const; + + void getMachineOpValue(const MCInst &MI, const MCOperand &Op, + APInt &Value, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + public: M68kMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) : MCII(mcii), Ctx(ctx) {} @@ -72,6 +81,30 @@ } // end anonymous namespace +#include "M68kGenMCCodeEmitter.inc" + +void M68kMCCodeEmitter::getMachineOpValue(const MCInst &MI, + const MCOperand &Op, + APInt &Value, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + assert(Op.isValid()); + + // Register + if (Op.isReg()) { + unsigned RegNum = Op.getReg(); + const auto *RI = Ctx.getRegisterInfo(); + uint32_t Val = RI->getEncodingValue(RegNum); + // Setup the D/A bit + if (M68kII::isAddressRegister(RegNum)) + Val |= 0b1000; + Value |= Val; + } + // Immediate + else if (Op.isImm()) + Value |= static_cast(Op.getImm()); +} + unsigned M68kMCCodeEmitter::encodeBits(unsigned ThisByte, uint8_t Bead, const MCInst &MI, const MCInstrDesc &Desc, @@ -321,6 +354,26 @@ LLVM_DEBUG(dbgs() << "EncodeInstruction: " << MCII.getName(Opcode) << "(" << Opcode << ")\n"); + // Try using the new method first. + APInt EncodedInst(16, 0U); + APInt Scratch(16, 0U); + getBinaryCodeForInstr(MI, Fixups, EncodedInst, Scratch, STI); + if (EncodedInst.getBitWidth()) { + LLVM_DEBUG(dbgs() << "Instruction " << MCII.getName(Opcode) << "(" + << Opcode << ") is using the new code emitter\n"); + ArrayRef Data(EncodedInst.getRawData(), + EncodedInst.getNumWords()); + int64_t InstSize = EncodedInst.getBitWidth(); + for (uint64_t Word : Data) { + for (int i = 0; i < 4 && InstSize > 0; ++i, InstSize -= 16) { + support::endian::write(OS, static_cast(Word), + support::big); + Word >>= 16; + } + } + return; + } + const uint8_t *Beads = getGenInstrBeads(MI); if (!Beads || !*Beads) { llvm_unreachable("*** Instruction does not have Beads defined"); Index: llvm/test/CodeGen/M68k/Control/cmp.ll =================================================================== --- llvm/test/CodeGen/M68k/Control/cmp.ll +++ llvm/test/CodeGen/M68k/Control/cmp.ll @@ -297,7 +297,7 @@ ; CHECK-NEXT: move.l (16,%sp), %a0 ; CHECK-NEXT: move.b (15,%sp), %d2 ; CHECK-NEXT: and.l #255, %d2 -; CHECK-NEXT: add.l %d2, %d1 +; CHECK-NEXT: add.l %d1, %d2 ; CHECK-NEXT: sne (%a0) ; CHECK-NEXT: cmpi.l #0, %d0 ; CHECK-NEXT: lea (d,%pc), %a0