//== M68kInstrData.td - M68k Data Movement Instructions -*- tablegen --===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file describes the Motorola 680x0 data movement instructions which are /// the basic means of transferring and storing addresses and data. Here is the /// current status of the file: /// /// Machine: /// /// EXG [ ] FMOVE [ ] FSMOVE [ ] FDMOVE [ ] FMOVEM [ ] /// LEA [~] PEA [ ] MOVE [~] MOVE16 [ ] MOVEA [ ] /// MOVEM [ ] MOVEP [ ] MOVEQ [ ] LINK [ ] UNLK [ ] /// /// Pseudo: /// /// MOVSX [x] MOVZX [x] MOVX [x] /// /// Map: /// /// [ ] - was not touched at all /// [!] - requires extarnal stuff implemented /// [~] - in progress but usable /// [x] - done /// //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // MOVE //===----------------------------------------------------------------------===// /// ----------------------------------------------------- /// F E | D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0 /// ----------------------------------------------------- /// | | DESTINATION | SOURCE /// 0 0 | SIZE | REG | MODE | MODE | REG /// ----------------------------------------------------- /// /// NOTE Move requires EA X version for direct register destination(0) class MxMoveEncoding : MxEncoding, 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 value> : MxBead2Bits; def MxMoveSize8 : MxMoveSize<0b01>; def MxMoveSize16 : MxMoveSize<0b11>; def MxMoveSize32 : MxMoveSize<0b10>; let Defs = [CCR] in class MxMove pattern, MxEncoding enc> : MxInst; class MxMove_RR : MxMove; let mayStore = 1 in { class MxMove_MR : MxMove; class MxMove_MI : MxMove; } // let mayStore = 1 class MxMove_RI : MxMove; let mayLoad = 1 in class MxMove_RM : MxMove>; multiclass MMxMove_RM { // REG <- (An)+ def NAME#REG.OOp.Letter#REG.Postfix : MxMove_RM; // REG <- -(An) def NAME#REG.EOp.Letter#REG.Postfix : MxMove_RM; // REG <- (i,PC,Xn) def NAME#REG.KOp.Letter#REG.Postfix : MxMove_RM; // REG <- (i,PC) def NAME#REG.QOp.Letter#REG.Postfix : MxMove_RM; // REG <- (i,An,Xn) def NAME#REG.FOp.Letter#REG.Postfix : MxMove_RM; // REG <- (i,An) def NAME#REG.POp.Letter#REG.Postfix : MxMove_RM; // REG <- (ABS) def NAME#REG.BOp.Letter#REG.Postfix : MxMove_RM; // REG <- (An) def NAME#REG.JOp.Letter#REG.Postfix : MxMove_RM; } let mayLoad = 1, mayStore = 1 in { class MxMove_MM : MxMove>; } // let mayLoad = 1, mayStore = 1 multiclass MMxMove_MM { // MEM <- (An)+ def NAME#TYPE.OOp.Letter#TYPE.Postfix : MxMove_MM; // MEM <- -(An) def NAME#TYPE.EOp.Letter#TYPE.Postfix : MxMove_MM; // MEM <- (i,An) def NAME#TYPE.POp.Letter#TYPE.Postfix : MxMove_MM; // MEM <- (i,An,Xn) def NAME#TYPE.FOp.Letter#TYPE.Postfix : MxMove_MM; // MEM <- (i,PC,Xn) def NAME#TYPE.KOp.Letter#TYPE.Postfix : MxMove_MM; // MEM <- (i,PC) def NAME#TYPE.QOp.Letter#TYPE.Postfix : MxMove_MM; // MEM <- (ABS) def NAME#TYPE.BOp.Letter#TYPE.Postfix : MxMove_MM; // MEM <- (An) def NAME#TYPE.JOp.Letter#TYPE.Postfix : MxMove_MM; } def MOV8dd : MxMove_RR>; // M <- R def MOV8fd : MxMove_MR>; def MOV8pd : MxMove_MR>; def MOV8ed : MxMove_MR>; def MOV8od : MxMove_MR>; def MOV8bd : MxMove_MR>; def MOV8jd : MxMove_MR>; // R <- I def MOV8di : MxMove_RI>; foreach S = [16, 32] in { foreach D = [ "r", "a" ] in { foreach O = [ "r", "a" ] in { def MOV#S#D#O : MxMove_RR< !cast("MxType"#S#D), !cast("MxType"#S#O), MxMoveEncoding("MxMoveSize"#S), !cast("MxEncEA"#D#"_1"), MxExtEmpty, !cast("MxEncEA"#D#"_0_reflected"), MxExtEmpty>>; } // M <- R def MOV#S#"f"#D : MxMove_MR< !cast("MxType"#S).FOp, !cast("MxType"#S).FPat, !cast("MxType"#S#D), MxMoveEncoding("MxMoveSize"#S), !cast("MxEncEA"#D#"_1"), MxExtEmpty, MxEncEAf_0, MxExtBrief_0>>; def MOV#S#"p"#D : MxMove_MR< !cast("MxType"#S).POp, !cast("MxType"#S).PPat, !cast("MxType"#S#D), MxMoveEncoding("MxMoveSize"#S), !cast("MxEncEA"#D#"_1"), MxExtEmpty, MxEncEAp_0, MxExtI16_0>>; def MOV#S#"e"#D : MxMove_MR< !cast("MxType"#S).EOp, !cast("MxType"#S).EPat, !cast("MxType"#S#D), MxMoveEncoding("MxMoveSize"#S), !cast("MxEncEA"#D#"_1"), MxExtEmpty, MxEncEAe_0, MxExtEmpty>>; def MOV#S#"o"#D : MxMove_MR< !cast("MxType"#S).OOp, !cast("MxType"#S).OPat, !cast("MxType"#S#D), MxMoveEncoding("MxMoveSize"#S), !cast("MxEncEA"#D#"_1"), MxExtEmpty, MxEncEAo_0, MxExtEmpty>>; def MOV#S#"b"#D : MxMove_MR< !cast("MxType"#S).BOp, !cast("MxType"#S).BPat, !cast("MxType"#S#D), MxMoveEncoding("MxMoveSize"#S), !cast("MxEncEA"#D#"_1"), MxExtEmpty, MxEncEAb, MxExtI32_0>>; def MOV#S#"j"#D : MxMove_MR< !cast("MxType"#S).JOp, !cast("MxType"#S).JPat, !cast("MxType"#S#D), MxMoveEncoding("MxMoveSize"#S), !cast("MxEncEA"#D#"_1"), MxExtEmpty, MxEncEAj_0, MxExtEmpty>>; // R <- I def MOV#S#D#"i" : MxMove_RI< !cast("MxType"#S#D), MxMoveEncoding("MxMoveSize"#S), MxEncEAi, !cast("MxExtI"#S#"_1"), !cast("MxEncEA"#D#"_0_reflected"), MxExtEmpty>>; } } // M <- I foreach S = [8, 16, 32] in { def MOV#S#"f"#"i" : MxMove_MI< !cast("MxType"#S).FOp, !cast("MxType"#S).FPat, !cast("MxType"#S), MxMoveEncoding("MxMoveSize"#S), MxEncEAi, !cast("MxExtI"#S#"_1"), MxEncEAf_0, MxExtBrief_0>>; def MOV#S#"p"#"i" : MxMove_MI< !cast("MxType"#S).POp, !cast("MxType"#S).PPat, !cast("MxType"#S), MxMoveEncoding("MxMoveSize"#S), MxEncEAi, !cast("MxExtI"#S#"_1"), MxEncEAp_0, MxExtI16_0>>; def MOV#S#"b"#"i" : MxMove_MI< !cast("MxType"#S).BOp, !cast("MxType"#S).BPat, !cast("MxType"#S), MxMoveEncoding("MxMoveSize"#S), MxEncEAi, !cast("MxExtI"#S#"_1"), MxEncEAb, MxExtI32_0>>; def MOV#S#"j"#"i" : MxMove_MI< !cast("MxType"#S).JOp, !cast("MxType"#S).JPat, !cast("MxType"#S), MxMoveEncoding("MxMoveSize"#S), MxEncEAi, !cast("MxExtI"#S#"_1"), MxEncEAj_0, MxExtEmpty>>; } // Store ABS(basically pointer) as Immdiate to Mem def : Pat<(store MxType32.BPat :$src, MxType32.PPat :$dst), (MOV32pi MxType32.POp :$dst, MxType32.IOp :$src)>; def : Pat<(store MxType32.BPat :$src, MxType32.FPat :$dst), (MOV32fi MxType32.FOp :$dst, MxType32.IOp :$src)>; def : Pat<(store MxType32.BPat :$src, MxType32.BPat :$dst), (MOV32bi MxType32.BOp :$dst, MxType32.IOp :$src)>; def : Pat<(store MxType32.BPat :$src, MxType32.JPat :$dst), (MOV32ji MxType32.JOp :$dst, MxType32.IOp :$src)>; // R <- M defm MOV8d : MMxMove_RM; defm MOV16r : MMxMove_RM; defm MOV16a : MMxMove_RM; defm MOV32r : MMxMove_RM; defm MOV32a : MMxMove_RM; let Pattern = [(null_frag)] in { defm MOV16r : MMxMove_RM; defm MOV16a : MMxMove_RM; defm MOV32r : MMxMove_RM; defm MOV32a : MMxMove_RM; } // Pattern // M <- M defm MOV8p : MMxMove_MM; defm MOV16p : MMxMove_MM; defm MOV32p : MMxMove_MM; defm MOV8f : MMxMove_MM; defm MOV16f : MMxMove_MM; defm MOV32f : MMxMove_MM; defm MOV8b : MMxMove_MM; defm MOV16b : MMxMove_MM; defm MOV32b : MMxMove_MM; defm MOV8e : MMxMove_MM; defm MOV16e : MMxMove_MM; defm MOV32e : MMxMove_MM; defm MOV8o : MMxMove_MM; defm MOV16o : MMxMove_MM; defm MOV32o : MMxMove_MM; defm MOV8j : MMxMove_MM; defm MOV16j : MMxMove_MM; defm MOV32j : MMxMove_MM; //===----------------------------------------------------------------------===// // MOVEM // // The mask is already pre-processed by the save/restore spill hook //===----------------------------------------------------------------------===// // Direction def MxMOVEM_MR : MxBead1Bit<0>; def MxMOVEM_RM : MxBead1Bit<1>; // Size def MxMOVEM_W : MxBead1Bit<0>; def MxMOVEM_L : MxBead1Bit<1>; /// ---------------+-------------+-------------+--------- /// F E D C B | A | 9 8 7 | 6 | 5 4 3 | 2 1 0 /// ---------------+---+---------+---+---------+--------- /// 0 1 0 0 1 | D | 0 0 1 | S | MODE | REG /// ---------------+---+---------+---+---------+--------- /// REGISTER LIST MASK /// ----------------------------------------------------- /// D - direction(RM,MR) /// S - size(W,L) class MxMOVEMEncoding : MxEncoding, DIR, MxBead1Bit<1>, MxBead4Bits<0b0100>, IMM, EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>; let mayStore = 1 in class MxMOVEM_MR : MxInst<(outs), (ins MEMOp:$dst, MxMoveMask:$mask), "movem."#TYPE.Prefix#"\t$mask, $dst", [], MxMOVEMEncoding>>; let mayLoad = 1 in class MxMOVEM_RM : MxInst<(outs), (ins MxMoveMask:$mask, MEMOp:$src), "movem."#TYPE.Prefix#"\t$src, $mask", [], MxMOVEMEncoding>>; def MOVM32jm : MxMOVEM_MR; def MOVM32pm : MxMOVEM_MR; def MOVM32mj : MxMOVEM_RM; def MOVM32mp : MxMOVEM_RM; // Pseudo versions. These a required by virtual register spill/restore since // the mask requires real register to encode. These instruction will be expanded // into real MOVEM after RA finishes. let mayStore = 1 in class MxMOVEM_MR_Pseudo : MxPseudo<(outs), (ins MEMOp:$dst, TYPE.ROp:$reg)>; let mayLoad = 1 in class MxMOVEM_RM_Pseudo : MxPseudo<(outs TYPE.ROp:$dst), (ins MEMOp:$src)>; // Mem <- Reg def MOVM8jm_P : MxMOVEM_MR_Pseudo; def MOVM16jm_P : MxMOVEM_MR_Pseudo; def MOVM32jm_P : MxMOVEM_MR_Pseudo; def MOVM8pm_P : MxMOVEM_MR_Pseudo; def MOVM16pm_P : MxMOVEM_MR_Pseudo; def MOVM32pm_P : MxMOVEM_MR_Pseudo; // Reg <- Mem def MOVM8mj_P : MxMOVEM_RM_Pseudo; def MOVM16mj_P : MxMOVEM_RM_Pseudo; def MOVM32mj_P : MxMOVEM_RM_Pseudo; def MOVM8mp_P : MxMOVEM_RM_Pseudo; def MOVM16mp_P : MxMOVEM_RM_Pseudo; def MOVM32mp_P : MxMOVEM_RM_Pseudo; //===----------------------------------------------------------------------===// // MOVE to/from SR/CCR // // A special care must be taken working with to/from CCR since it is basically // word-size SR register truncated for user mode thus it only supports word-size // instructions. Plus the original M68000 does not support moves from CCR. So in // order to use CCR effectively one MUST use proper byte-size pseudo instructi- // ons that will be resolved sometime after RA pass. //===----------------------------------------------------------------------===// /// -------------------------------------------------- /// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0 /// -------------------------------------------------- /// | EFFECTIVE ADDRESS /// 0 1 0 0 0 1 0 0 1 1 | MODE | REG /// -------------------------------------------------- let Defs = [CCR] in class MxMoveToCCR : MxInst<(outs CCRC:$dst), INS, "move.w\t$src, $dst", [], MxEncoding, MxBead4Bits<0b0001>, MxBead2Bits<0b01>, EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>; class MxMoveToCCRPseudo : MxPseudo<(outs CCRC:$dst), INS>; let mayLoad = 1 in { def MOV16cp : MxMoveToCCR<(ins MxType16d.POp:$src), MxEncEAp_1, MxExtI16_1>; def MOV8cp : MxMoveToCCRPseudo<(ins MxType8d.POp:$src)>; } // let mayLoad = 1 def MOV16cd : MxMoveToCCR<(ins MxType16d.ROp:$src), MxEncEAd_1, MxExtEmpty>; def MOV8cd : MxMoveToCCRPseudo<(ins MxType8d.ROp:$src)>; /// Move from CCR /// -------------------------------------------------- /// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0 /// -------------------------------------------------- /// | EFFECTIVE ADDRESS /// 0 1 0 0 0 0 1 0 1 1 | MODE | REG /// -------------------------------------------------- let Uses = [CCR] in class MxMoveFromCCR : MxInst, MxBead4Bits<0b0000>, MxBead2Bits<0b01>, EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>, Requires<[ IsM68010 ]>; class MxMoveFromCCRPseudo : MxPseudo<(outs), INS>; let mayStore = 1 in { def MOV16pc : MxMoveFromCCR<(outs), (ins MxType16d.POp:$dst, CCRC:$src), MxEncEAp_0, MxExtI16_0>; def MOV8pc : MxMoveFromCCRPseudo<(ins MxType8d.POp:$dst, CCRC:$src)>; } // let mayStore = 1 def MOV16dc : MxMoveFromCCR<(outs MxType16d.ROp:$dst), (ins CCRC:$src), MxEncEAd_0, MxExtEmpty>; def MOV8dc : MxMoveFromCCRPseudo<(ins MxType8d.ROp:$dst, CCRC:$src)>; //===----------------------------------------------------------------------===// // LEA //===----------------------------------------------------------------------===// /// ---------------------------------------------------- /// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0 /// ---------------------------------------------------- /// 0 1 0 0 | DST REG | 1 1 1 | MODE | REG /// ---------------------------------------------------- class MxLEA : MxInst<(outs MxARD32:$dst), (ins SRCOpd:$src), "lea\t$src, $dst", [(set i32:$dst, SRCPat:$src)], MxEncoding, MxBeadReg<0>, MxBead4Bits<0x4>, EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>; def LEA32p : MxLEA; def LEA32f : MxLEA; def LEA32q : MxLEA; def LEA32b : MxLEA; //===----------------------------------------------------------------------===// // Pseudos //===----------------------------------------------------------------------===// /// Pushe/Pop to/from SP for simplicity let Uses = [SP], Defs = [SP], hasSideEffects = 0 in { // SP <- SP - ; (SP) <- Dn let mayStore = 1 in { def PUSH8d : MxPseudo<(outs), (ins DR8:$reg)>; def PUSH16d : MxPseudo<(outs), (ins DR16:$reg)>; def PUSH32r : MxPseudo<(outs), (ins XR32:$reg)>; } // let mayStore = 1 // Dn <- (SP); SP <- SP + let mayLoad = 1 in { def POP8d : MxPseudo<(outs DR8:$reg), (ins)>; def POP16d : MxPseudo<(outs DR16:$reg), (ins)>; def POP32r : MxPseudo<(outs XR32:$reg), (ins)>; } // let mayLoad = 1 } // let Uses/Defs = [SP], hasSideEffects = 0 let Defs = [CCR] in { class MxPseudoMove_RR PAT = []> : MxPseudo<(outs DST.ROp:$dst), (ins SRC.ROp:$src), PAT>; class MxPseudoMove_RM PAT = []> : MxPseudo<(outs DST.ROp:$dst), (ins SRCOpd:$src), PAT>; } /// This group of Pseudos is analogues to the real x86 extending moves, but /// since M68k does not have those we need to emulate. These instructions /// will be expanded right after RA completed because we need to know precisely /// what registers are allocated for the operands and if they overlap we just /// extend the value if the registers are completely different we need to move /// first. foreach EXT = ["S", "Z"] in { let hasSideEffects = 0 in { def MOV#EXT#Xd16d8 : MxPseudoMove_RR; def MOV#EXT#Xd32d8 : MxPseudoMove_RR; def MOV#EXT#Xd32d16 : MxPseudoMove_RR; let mayLoad = 1 in { def MOV#EXT#Xd16j8 : MxPseudoMove_RM; def MOV#EXT#Xd32j8 : MxPseudoMove_RM; def MOV#EXT#Xd32j16 : MxPseudoMove_RM; def MOV#EXT#Xd16p8 : MxPseudoMove_RM; def MOV#EXT#Xd32p8 : MxPseudoMove_RM; def MOV#EXT#Xd32p16 : MxPseudoMove_RM; def MOV#EXT#Xd16f8 : MxPseudoMove_RM; def MOV#EXT#Xd32f8 : MxPseudoMove_RM; def MOV#EXT#Xd32f16 : MxPseudoMove_RM; } } } /// This group of instructions is similar to the group above but DOES NOT do /// any value extension, they just load a smaller register into the lower part /// of another register if operands' real registers are different or does /// nothing if they are the same. def MOVXd16d8 : MxPseudoMove_RR; def MOVXd32d8 : MxPseudoMove_RR; def MOVXd32d16 : MxPseudoMove_RR; //===----------------------------------------------------------------------===// // Extend/Truncate Patterns //===----------------------------------------------------------------------===// // i16 <- sext i8 def: Pat<(i16 (sext i8:$src)), (EXTRACT_SUBREG (MOVSXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>; def: Pat<(MxSExtLoadi16i8 MxCP_ARI:$src), (EXTRACT_SUBREG (MOVSXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>; def: Pat<(MxSExtLoadi16i8 MxCP_ARID:$src), (EXTRACT_SUBREG (MOVSXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>; def: Pat<(MxSExtLoadi16i8 MxCP_ARII:$src), (EXTRACT_SUBREG (MOVSXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>; // i32 <- sext i8 def: Pat<(i32 (sext i8:$src)), (MOVSXd32d8 MxDRD8:$src)>; def: Pat<(MxSExtLoadi32i8 MxCP_ARI :$src), (MOVSXd32j8 MxARI8 :$src)>; def: Pat<(MxSExtLoadi32i8 MxCP_ARID:$src), (MOVSXd32p8 MxARID8:$src)>; def: Pat<(MxSExtLoadi32i8 MxCP_ARII:$src), (MOVSXd32f8 MxARII8:$src)>; // i32 <- sext i16 def: Pat<(i32 (sext i16:$src)), (MOVSXd32d16 MxDRD16:$src)>; def: Pat<(MxSExtLoadi32i16 MxCP_ARI :$src), (MOVSXd32j16 MxARI16 :$src)>; def: Pat<(MxSExtLoadi32i16 MxCP_ARID:$src), (MOVSXd32p16 MxARID16:$src)>; def: Pat<(MxSExtLoadi32i16 MxCP_ARII:$src), (MOVSXd32f16 MxARII16:$src)>; // i16 <- zext i8 def: Pat<(i16 (zext i8:$src)), (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>; def: Pat<(MxZExtLoadi16i8 MxCP_ARI:$src), (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>; def: Pat<(MxZExtLoadi16i8 MxCP_ARID:$src), (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>; def: Pat<(MxZExtLoadi16i8 MxCP_ARII:$src), (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>; // i32 <- zext i8 def: Pat<(i32 (zext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>; def: Pat<(MxZExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>; def: Pat<(MxZExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>; def: Pat<(MxZExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>; // i32 <- zext i16 def: Pat<(i32 (zext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>; def: Pat<(MxZExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>; def: Pat<(MxZExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>; def: Pat<(MxZExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>; // i16 <- anyext i8 def: Pat<(i16 (anyext i8:$src)), (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>; def: Pat<(MxExtLoadi16i8 MxCP_ARI:$src), (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>; def: Pat<(MxExtLoadi16i8 MxCP_ARID:$src), (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>; def: Pat<(MxExtLoadi16i8 MxCP_ARII:$src), (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>; // i32 <- anyext i8 def: Pat<(i32 (anyext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>; def: Pat<(MxExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>; def: Pat<(MxExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>; def: Pat<(MxExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>; // i32 <- anyext i16 def: Pat<(i32 (anyext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>; def: Pat<(MxExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>; def: Pat<(MxExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>; def: Pat<(MxExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>; // trunc patterns def : Pat<(i16 (trunc i32:$src)), (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex16Lo)>; def : Pat<(i8 (trunc i32:$src)), (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex8Lo)>; def : Pat<(i8 (trunc i16:$src)), (EXTRACT_SUBREG MxXRD16:$src, MxSubRegIndex8Lo)>;