brintos

brintos / llvm-project-archived public Read only

0
0
Text · 32.3 KiB · c5b7ae3 Raw
825 lines · plain
1//===-- M68kInstrData.td - M68k Data Movement Instructions -*- tablegen -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file describes the Motorola 680x0 data movement instructions which are11/// the basic means of transferring and storing addresses and data. Here is the12/// current status of the file:13///14///  Machine:15///16///     EXG   [ ]     FMOVE [ ]     FSMOVE [ ]     FDMOVE [ ]     FMOVEM [ ]17///     LEA   [~]     PEA   [ ]     MOVE   [~]     MOVE16 [ ]     MOVEA  [ ]18///     MOVEM [ ]     MOVEP [ ]     MOVEQ  [ ]     LINK   [~]     UNLK   [~]19///20///  Pseudo:21///22///     MOVI  [x]     MOVSX [x]     MOVZX [x]     MOVX   [x]23///24///  Map:25///26///   [ ] - was not touched at all27///   [!] - requires extarnal stuff implemented28///   [~] - in progress but usable29///   [x] - done30///31//===----------------------------------------------------------------------===//32 33//===----------------------------------------------------------------------===//34// MOVE35//===----------------------------------------------------------------------===//36 37/// -----------------------------------------------------38///  F  E | D  C | B  A  9 | 8  7  6 | 5  4  3 | 2  1  039/// -----------------------------------------------------40///       |      |    DESTINATION    |       SOURCE41///  0  0 | SIZE |   REG   |   MODE  |   MODE  |   REG42/// -----------------------------------------------------43///44/// NOTE Move requires EA X version for direct register destination(0)45 46// MOVE has a different size encoding.47class MxMoveSize<bits<2> value> {48  bits<2> Value = value;49}50def MxMoveSize8  : MxMoveSize<0b01>;51def MxMoveSize16 : MxMoveSize<0b11>;52def MxMoveSize32 : MxMoveSize<0b10>;53 54class MxMoveEncoding<MxMoveSize size, MxEncMemOp dst_enc, MxEncMemOp src_enc> {55  dag Value = (ascend56    (descend 0b00, size.Value,57             !cond(58               !eq(!getdagop(dst_enc.EA), descend): !setdagop(dst_enc.EA, ascend),59               !eq(!getdagop(dst_enc.EA), ascend): !setdagop(dst_enc.EA, descend)),60             src_enc.EA),61    // Source extension62    src_enc.Supplement,63    // Destination extension64    dst_enc.Supplement65  );66}67 68// Special encoding for Xn69class MxMoveEncAddrMode_r<string reg_opnd> : MxEncMemOp {70  let EA = (descend (descend 0b00, (slice "$"#reg_opnd, 3, 3)),71                    (operand "$"#reg_opnd, 3));72}73 74// TODO: Generalize and adopt this utility in other .td files as well.75multiclass MxMoveOperandEncodings<string opnd_name> {76  // Dn77  def MxMove#NAME#OpEnc_d : MxEncAddrMode_d<opnd_name>;78  // An79  def MxMove#NAME#OpEnc_a : MxEncAddrMode_a<opnd_name>;80  // Xn81  def MxMove#NAME#OpEnc_r : MxMoveEncAddrMode_r<opnd_name>;82  // (An)+83  def MxMove#NAME#OpEnc_o : MxEncAddrMode_o<opnd_name>;84  // -(An)85  def MxMove#NAME#OpEnc_e : MxEncAddrMode_e<opnd_name>;86  // (i,PC,Xn)87  def MxMove#NAME#OpEnc_k : MxEncAddrMode_k<opnd_name>;88  // (i,PC)89  def MxMove#NAME#OpEnc_q : MxEncAddrMode_q<opnd_name>;90  // (i,An,Xn)91  def MxMove#NAME#OpEnc_f : MxEncAddrMode_f<opnd_name>;92  // (i,An)93  def MxMove#NAME#OpEnc_p : MxEncAddrMode_p<opnd_name>;94  // (ABS).L95  def MxMove#NAME#OpEnc_b : MxEncAddrMode_abs<opnd_name, /*W/L=*/true>;96  // (An)97  def MxMove#NAME#OpEnc_j : MxEncAddrMode_j<opnd_name>;98}99 100defm Src : MxMoveOperandEncodings<"src">;101defm Dst : MxMoveOperandEncodings<"dst">;102 103defvar MxMoveSupportedAMs = ["o", "e", "k", "q", "f", "p", "b", "j"];104 105let Defs = [CCR] in106class MxMove<string size, dag outs, dag ins, list<dag> pattern, MxMoveEncoding enc>107    : MxInst<outs, ins, "move."#size#"\t$src, $dst", pattern> {108  let Inst = enc.Value;109}110 111// R <- R112class MxMove_RR<MxType TYPE, string DST_REG, string SRC_REG,113                MxMoveEncoding ENC,114                MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG),115                MxOpBundle SRC = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#SRC_REG)>116    : MxMove<TYPE.Prefix,117             (outs DST.Op:$dst), (ins SRC.Op:$src),118             [(null_frag)], ENC>;119 120foreach DST_REG = ["r", "a"] in {121  foreach SRC_REG = ["r", "a"] in122  foreach TYPE = [MxType16, MxType32] in123  def MOV # TYPE.Size # DST_REG # SRC_REG # TYPE.Postfix124      : MxMove_RR<TYPE, DST_REG, SRC_REG,125                  MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),126                                 !cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_REG),127                                 !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#SRC_REG)>>;128} // foreach DST_REG129foreach TYPE = [MxType8, MxType16, MxType32] in130def MOV # TYPE.Size # dd # TYPE.Postfix131    : MxMove_RR<TYPE, "d", "d",132                MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),133                               MxMoveDstOpEnc_d, MxMoveSrcOpEnc_d>>;134 135// M <- R136let mayStore = 1 in {137class MxMove_MR<MxType TYPE, MxOpBundle DST, string SRC_REG, MxMoveEncoding ENC,138                MxOpBundle SRC = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#SRC_REG)>139    : MxMove<TYPE.Prefix, (outs), (ins DST.Op:$dst, SRC.Op:$src),140             [(store TYPE.VT:$src, DST.Pat:$dst)], ENC>;141 142class MxMove_MI<MxType TYPE, MxOpBundle DST, MxMoveEncoding ENC,143                MxImmOpBundle SRC = !cast<MxImmOpBundle>("MxOp"#TYPE.Size#"AddrMode_i")>144    : MxMove<TYPE.Prefix, (outs), (ins DST.Op:$dst, SRC.Op:$src),145             [(store SRC.ImmPat:$src, DST.Pat:$dst)], ENC>;146} // let mayStore = 1147 148foreach REG = ["r", "a", "d"] in149foreach AM = MxMoveSupportedAMs in {150  foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in151  def MOV # TYPE.Size # AM # REG # TYPE.Postfix152      : MxMove_MR<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM), REG,153                  MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),154                                 !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM),155                                 !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#REG)>>;156} // foreach AM157 158foreach AM = MxMoveSupportedAMs in {159  foreach TYPE = [MxType8, MxType16, MxType32] in160  def MOV # TYPE.Size # AM # i # TYPE.Postfix161      : MxMove_MI<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),162                  MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),163                                 !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM),164                                 MxEncAddrMode_i<"src", TYPE.Size>>>;165} // foreach AM166 167// R <- I168// No pattern, as all immediate -> register moves are matched to the MOVI pseudo169class MxMove_RI<MxType TYPE, string DST_REG, MxMoveEncoding ENC,170                MxImmOpBundle SRC = !cast<MxImmOpBundle>("MxOp"#TYPE.Size#"AddrMode_i"),171                MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG)>172    : MxMove<TYPE.Prefix, (outs DST.Op:$dst), (ins SRC.Op:$src),173              [(null_frag)], ENC>;174 175foreach REG = ["r", "a", "d"] in {176  foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in177  def MOV # TYPE.Size # REG # i # TYPE.Postfix178      : MxMove_RI<TYPE, REG,179                  MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),180                                 !cast<MxEncMemOp>("MxMoveDstOpEnc_"#REG),181                                 MxEncAddrMode_i<"src", TYPE.Size>>>;182} // foreach REG183 184// R <- M185let mayLoad = 1 in186class MxMove_RM<MxType TYPE, string DST_REG, MxOpBundle SRC, MxEncMemOp SRC_ENC,187                MxMoveSize SIZE_ENC = !cast<MxMoveSize>("MxMoveSize"#TYPE.Size),188                MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG),189                MxEncMemOp DST_ENC = !cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_REG)>190    : MxMove<TYPE.Prefix, (outs DST.Op:$dst), (ins SRC.Op:$src),191             [(set TYPE.VT:$dst, (TYPE.Load SRC.Pat:$src))],192             MxMoveEncoding<SIZE_ENC, DST_ENC, SRC_ENC>>;193 194foreach REG = ["r", "a", "d"] in195foreach AM = MxMoveSupportedAMs in {196  foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in197  def MOV # TYPE.Size # REG # AM # TYPE.Postfix198      : MxMove_RM<TYPE, REG, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),199                  !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;200} // foreach AM201 202// Tail call version203let Pattern = [(null_frag)] in {204  foreach REG = ["r", "a"] in205  foreach AM = MxMoveSupportedAMs in {206    foreach TYPE = [MxType16, MxType32] in207    def MOV # TYPE.Size # REG # AM # _TC208        : MxMove_RM<TYPE, REG, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),209                    !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)> {210      let isCodeGenOnly = true;211    }212  } // foreach AM213} // let Pattern214 215let mayLoad = 1, mayStore = 1 in216class MxMove_MM<MxType TYPE, MxOpBundle DST, MxOpBundle SRC,217                MxEncMemOp DST_ENC, MxEncMemOp SRC_ENC>218    : MxMove<TYPE.Prefix, (outs), (ins DST.Op:$dst, SRC.Op:$src),219             [(store (TYPE.Load SRC.Pat:$src), DST.Pat:$dst)],220             MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),221                            DST_ENC, SRC_ENC>>;222 223foreach DST_AM = MxMoveSupportedAMs in224foreach SRC_AM = MxMoveSupportedAMs in {225  foreach TYPE = [MxType8, MxType16, MxType32] in226  def MOV # TYPE.Size # DST_AM # SRC_AM # TYPE.Postfix227      : MxMove_MM<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_AM),228                  !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#SRC_AM),229                  !cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_AM),230                  !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#SRC_AM)>;231} // foreach SRC_AM232 233// Store ABS(basically pointer) as Immdiate to Mem234def : Pat<(store   MxType32.BPat :$src, MxType32.PPat :$dst),235          (MOV32pi MxType32.POp  :$dst, MxType32.IOp  :$src)>;236 237def : Pat<(store   MxType32.BPat :$src, MxType32.FPat :$dst),238          (MOV32fi MxType32.FOp  :$dst, MxType32.IOp  :$src)>;239 240def : Pat<(store   MxType32.BPat :$src, MxType32.BPat :$dst),241          (MOV32bi MxType32.BOp  :$dst, MxType32.IOp  :$src)>;242 243def : Pat<(store   MxType32.BPat :$src, MxType32.JPat :$dst),244          (MOV32ji MxType32.JOp  :$dst, MxType32.IOp  :$src)>;245 246//===----------------------------------------------------------------------===//247// MOVEQ248//===----------------------------------------------------------------------===//249 250/// ------------+---------+---+-----------------------251///  F  E  D  C | B  A  9 | 8 | 7  6  5  4  3  2  1  0252/// ------------+---------+---+-----------------------253///  0  1  1  1 |   REG   | 0 |          DATA254/// ------------+---------+---+-----------------------255 256// No pattern, as all immediate -> register moves are matched to the MOVI pseudo257let Defs = [CCR] in258def MOVQ : MxInst<(outs MxDRD32:$dst), (ins Mxi8imm:$imm),259                  "moveq\t$imm, $dst",260                  [(null_frag)]> {261  let Inst = (descend 0b0111, (operand "$dst", 3), 0b0, (operand "$imm", 8));262}263 264//===----------------------------------------------------------------------===//265// MOVEM266//267// The mask is already pre-processed by the save/restore spill hook268//===----------------------------------------------------------------------===//269 270// Direction271defvar MxMOVEM_MR = false;272defvar MxMOVEM_RM = true;273 274// Size275defvar MxMOVEM_W = false;276defvar MxMOVEM_L = true;277 278/// ---------------+-------------+-------------+---------279///  F  E  D  C  B | A | 9  8  7 | 6 | 5  4  3 | 2  1  0280/// ---------------+---+---------+---+---------+---------281///  0  1  0  0  1 | D | 0  0  1 | S |   MODE  |   REG282/// ---------------+---+---------+---+---------+---------283///                  REGISTER LIST MASK284/// -----------------------------------------------------285/// D - direction(RM,MR)286/// S - size(W,L)287class MxMOVEMEncoding<MxEncMemOp opnd_enc, bit size, bit direction,288                      string mask_op_name> {289  dag Value = (ascend290    (descend 0b01001, direction, 0b001, size, opnd_enc.EA),291    // Mask292    (operand "$"#mask_op_name, 16),293    opnd_enc.Supplement294  );295}296 297let mayStore = 1 in298class MxMOVEM_MR<MxType TYPE, bit SIZE_ENC,299                 MxOperand MEMOp, MxEncMemOp MEM_ENC,300                 MxOp MASKOp>301    : MxInst<(outs), (ins MEMOp:$dst, MASKOp:$mask),302             "movem."#TYPE.Prefix#"\t$mask, $dst", []> {303  let Inst = MxMOVEMEncoding<MEM_ENC, SIZE_ENC, MxMOVEM_MR, "mask">.Value;304}305 306foreach AM = MxMoveSupportedAMs in {307  foreach TYPE = [MxType16, MxType32] in308  def MOVM # TYPE.Size # AM # m # TYPE.Postfix309      : MxMOVEM_MR<TYPE, !if(!eq(TYPE, MxType16), MxMOVEM_W, MxMOVEM_L),310                   !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM).Op,311                   !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM),312                   !if(!eq(AM, "e"), MxInverseMoveMask, MxMoveMask)>;313} // foreach AM314 315let mayLoad = 1 in316class MxMOVEM_RM<MxType TYPE, bit SIZE_ENC,317                 MxOperand MEMOp, MxEncMemOp MEM_ENC,318                 MxOp MASKOp>319    : MxInst<(outs), (ins MASKOp:$mask, MEMOp:$src),320             "movem."#TYPE.Prefix#"\t$src, $mask", []> {321  let Inst = MxMOVEMEncoding<MEM_ENC, SIZE_ENC, MxMOVEM_RM, "mask">.Value;322}323 324foreach AM = MxMoveSupportedAMs in {325  foreach TYPE = [MxType16, MxType32] in326  def MOVM # TYPE.Size # m # AM # TYPE.Postfix327      : MxMOVEM_RM<TYPE, !if(!eq(TYPE, MxType16), MxMOVEM_W, MxMOVEM_L),328                   !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM).Op,329                   !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM),330                   !if(!eq(AM, "e"), MxInverseMoveMask, MxMoveMask)>;331} // foreach AM332 333// Pseudo versions. These a required by virtual register spill/restore since334// the mask requires real register to encode. These instruction will be expanded335// into real MOVEM after RA finishes.336let mayStore = 1 in337class MxMOVEM_MR_Pseudo<MxType TYPE, MxOperand MEMOp>338    : MxPseudo<(outs), (ins MEMOp:$dst, TYPE.ROp:$reg)>;339let mayLoad = 1 in340class MxMOVEM_RM_Pseudo<MxType TYPE, MxOperand MEMOp>341    : MxPseudo<(outs TYPE.ROp:$dst), (ins MEMOp:$src)>;342 343// Mem <- Reg344def MOVM16jm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.JOp>;345def MOVM32jm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.JOp>;346 347def MOVM16pm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.POp>;348def MOVM32pm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.POp>;349 350// Reg <- Mem351def MOVM16mj_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.JOp>;352def MOVM32mj_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.JOp>;353 354def MOVM16mp_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.POp>;355def MOVM32mp_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.POp>;356 357 358//===----------------------------------------------------------------------===//359// MOVE to/from SR/CCR360//361// A special care must be taken working with to/from CCR since it is basically362// word-size SR register truncated for user mode thus it only supports word-size363// instructions. Plus the original M68000 does not support moves from CCR. So in364// order to use CCR effectively one MUST use proper byte-size pseudo instructi-365// ons that will be resolved sometime after RA pass.366//===----------------------------------------------------------------------===//367 368/// Move to CCR369/// --------------------------------------------------370///  F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0371/// --------------------------------------------------372///                               | EFFECTIVE ADDRESS373///  0  1  0  0  0  1  0  0  1  1 |   MODE  |   REG374/// --------------------------------------------------375let Defs = [CCR] in {376class MxMoveToCCR<MxOperand MEMOp, MxEncMemOp SRC_ENC>377    : MxInst<(outs CCRC:$dst), (ins MEMOp:$src), "move.w\t$src, $dst", []> {378  let Inst = (ascend379    (descend 0b0100010011, SRC_ENC.EA),380    SRC_ENC.Supplement381  );382}383 384class MxMoveToCCRPseudo<MxOperand MEMOp>385    : MxPseudo<(outs CCRC:$dst), (ins MEMOp:$src)>;386} // let Defs = [CCR]387 388let mayLoad = 1 in389foreach AM = MxMoveSupportedAMs in {390  def MOV16c # AM : MxMoveToCCR<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,391                                !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;392  def MOV8c # AM  : MxMoveToCCRPseudo<!cast<MxOpBundle>("MxOp8AddrMode_"#AM).Op>;393} // foreach AM394 395// Only data register is allowed.396def MOV16cd : MxMoveToCCR<MxOp16AddrMode_d.Op, MxMoveSrcOpEnc_d>;397def MOV8cd  : MxMoveToCCRPseudo<MxOp8AddrMode_d.Op>;398 399/// Move from CCR400/// --------------------------------------------------401///  F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0402/// --------------------------------------------------403///                               | EFFECTIVE ADDRESS404///  0  1  0  0  0  0  1  0  1  1 |   MODE  |   REG405/// --------------------------------------------------406let Uses = [CCR] in {407class MxMoveFromCCR_R408    : MxInst<(outs MxDRD16:$dst), (ins CCRC:$src), "move.w\t$src, $dst", []>,409      Requires<[ AtLeastM68010 ]> {410  let Inst = (descend 0b0100001011, MxEncAddrMode_d<"dst">.EA);411}412 413class MxMoveFromCCR_M<MxOperand MEMOp, MxEncMemOp DST_ENC>414    : MxInst<(outs), (ins MEMOp:$dst, CCRC:$src), "move.w\t$src, $dst", []>,415      Requires<[ AtLeastM68010 ]> {416  let Inst = (ascend417    (descend 0b0100001011, DST_ENC.EA),418    DST_ENC.Supplement419  );420}421 422class MxMoveFromCCRPseudo<MxOperand MEMOp>423    : MxPseudo<(outs), (ins MEMOp:$dst, CCRC:$src)>;424class MxMoveFromCCR_RPseudo<MxOperand MEMOp>425    : MxPseudo<(outs MEMOp:$dst), (ins CCRC:$src)>;426} // let Uses = [CCR]427 428let mayStore = 1 in429foreach AM = MxMoveSupportedAMs in {430  def MOV16 # AM # c431    : MxMoveFromCCR_M<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,432                      !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM)>;433  def MOV8 # AM # c434    : MxMoveFromCCRPseudo<!cast<MxOpBundle>("MxOp8AddrMode_"#AM).Op>;435} // foreach AM436 437// Only data register is allowed.438def MOV16dc : MxMoveFromCCR_R;439def MOV8dc  : MxMoveFromCCR_RPseudo<MxOp8AddrMode_d.Op>;440 441/// Move to SR442/// --------------------------------------------------443///  F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0444/// --------------------------------------------------445///                               | EFFECTIVE ADDRESS446///  0  1  0  0  0  1  1  0  1  1 |   MODE  |   REG447/// --------------------------------------------------448let Defs = [SR] in {449class MxMoveToSR<MxOperand MEMOp, MxEncMemOp SRC_ENC>450    : MxInst<(outs SRC:$dst), (ins MEMOp:$src), "move.w\t$src, $dst", []> {451  let Inst = (ascend452    (descend 0b0100011011, SRC_ENC.EA),453    SRC_ENC.Supplement454  );455}456} // let Defs = [SR]457 458let mayLoad = 1 in459foreach AM = MxMoveSupportedAMs in {460  def MOV16s # AM : MxMoveToSR<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,461                                !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;462} // foreach AM463 464def MOV16sd : MxMoveToSR<MxOp16AddrMode_d.Op, MxMoveSrcOpEnc_d>;465 466/// Move from SR467/// --------------------------------------------------468///  F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0469/// --------------------------------------------------470///                               | EFFECTIVE ADDRESS471///  0  1  0  0  0  0  0  0  1  1 |   MODE  |   REG472/// --------------------------------------------------473let Uses = [SR] in {474class MxMoveFromSR_R475    : MxInst<(outs MxDRD16:$dst), (ins SRC:$src), "move.w\t$src, $dst", []>,476      Requires<[ AtLeastM68010 ]> {477  let Inst = (descend 0b0100000011, MxEncAddrMode_d<"dst">.EA);478}479 480class MxMoveFromSR_M<MxOperand MEMOp, MxEncMemOp DST_ENC>481    : MxInst<(outs), (ins MEMOp:$dst, SRC:$src), "move.w\t$src, $dst", []>,482      Requires<[ AtLeastM68010 ]> {483  let Inst = (ascend484    (descend 0b0100000011, DST_ENC.EA),485    DST_ENC.Supplement486  );487}488} // let Uses = [SR]489 490let mayStore = 1 in491foreach AM = MxMoveSupportedAMs in {492  def MOV16 # AM # s493    : MxMoveFromSR_M<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,494                      !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM)>;495} // foreach AM496 497def MOV16ds : MxMoveFromSR_R;498 499//===----------------------------------------------------------------------===//500// LEA501//===----------------------------------------------------------------------===//502 503/// ----------------------------------------------------504///  F  E  D  C | B  A  9 | 8  7  6 | 5  4  3 | 2  1  0505/// ----------------------------------------------------506///  0  1  0  0 | DST REG | 1  1  1 |   MODE  |   REG507/// ----------------------------------------------------508class MxLEA<MxOpBundle SRC, MxEncMemOp SRC_ENC>509    : MxInst<(outs MxARD32:$dst), (ins SRC.Op:$src),510             "lea\t$src, $dst", [(set i32:$dst, SRC.Pat:$src)]> {511  let Inst = (ascend512    (descend 0b0100, (operand "$dst", 3), 0b111, SRC_ENC.EA),513    SRC_ENC.Supplement514  );515}516 517foreach AM = ["p", "f", "b", "q", "k"] in518def LEA32 # AM : MxLEA<!cast<MxOpBundle>("MxOp32AddrMode_"#AM),519                       !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;520 521//===----------------------------------------------------------------------===//522// LINK/UNLK523//===----------------------------------------------------------------------===//524 525let Uses = [SP], Defs = [SP] in {526let mayStore = 1 in {527 528def LINK16 : MxInst<(outs), (ins MxARD16:$src, Mxi16imm:$disp), "link.w\t$src, $disp", []> {529  let Inst = (ascend530    (descend 0b0100111001010, (operand "$src", 3)),531    (operand "$disp", 16)532  );533}534 535def LINK32 : MxInst<(outs), (ins MxARD16:$src, Mxi32imm:$disp), "link.l\t$src, $disp", []> {536  let Inst = (ascend537    (descend 0b0100100000001, (operand "$src", 3)),538    (slice "$disp", 31, 16),539    (slice "$disp", 15, 0)540  );541}542 543def UNLK : MxInst<(outs), (ins MxARD32:$src), "unlk\t$src", []> {544  let Inst = (descend 0b0100111001011, (operand "$src", 3));545}546 547} // let mayStore = 1548} // let Uses = [SP], Defs = [SP]549 550//===----------------------------------------------------------------------===//551// Pseudos552//===----------------------------------------------------------------------===//553 554/// Pushe/Pop to/from SP for simplicity555let Uses = [SP], Defs = [SP], hasSideEffects = 0 in {556 557// SP <- SP - <size>; (SP) <- Dn558let mayStore = 1 in {559def PUSH8d  : MxPseudo<(outs), (ins DR8:$reg)>;560def PUSH16d : MxPseudo<(outs), (ins DR16:$reg)>;561def PUSH32r : MxPseudo<(outs), (ins XR32:$reg)>;562} // let mayStore = 1563 564// Dn <- (SP); SP <- SP + <size>565let mayLoad = 1 in {566def POP8d  : MxPseudo<(outs DR8:$reg),  (ins)>;567def POP16d : MxPseudo<(outs DR16:$reg), (ins)>;568def POP32r : MxPseudo<(outs XR32:$reg), (ins)>;569} // let mayLoad = 1570 571} // let Uses/Defs = [SP], hasSideEffects = 0572 573 574let Defs = [CCR] in {575class MxPseudoMove_RR<MxType DST, MxType SRC, list<dag> PAT = []>576    : MxPseudo<(outs DST.ROp:$dst), (ins SRC.ROp:$src), PAT>;577 578class MxPseudoMove_RM<MxType DST, MxOperand SRCOpd, list<dag> PAT = []>579    : MxPseudo<(outs DST.ROp:$dst), (ins SRCOpd:$src), PAT>;580 581 582// These Pseudos handle loading immediates to registers.583// They are expanded post-RA into either move or moveq instructions,584// depending on size, destination register class, and immediate value.585// This is done with pseudoinstructions in order to not constrain RA to586// data registers if moveq matches.587class MxPseudoMove_DI<MxType TYPE>588    : MxPseudo<(outs TYPE.ROp:$dst), (ins TYPE.IOp:$src),589               [(set TYPE.ROp:$dst, imm:$src)]>;590 591// i8 imm -> reg can always be converted to moveq,592// but we still emit a pseudo for consistency.593def MOVI8di  : MxPseudoMove_DI<MxType8d>;594def MOVI16ri : MxPseudoMove_DI<MxType16r>;595def MOVI32ri : MxPseudoMove_DI<MxType32r>;596} // let Defs = [CCR]597 598/// This group of Pseudos is analogues to the real x86 extending moves, but599/// since M68k does not have those we need to emulate. These instructions600/// will be expanded right after RA completed because we need to know precisely601/// what registers are allocated for the operands and if they overlap we just602/// extend the value if the registers are completely different we need to move603/// first.604foreach EXT = ["S", "Z"] in {605  let hasSideEffects = 0 in {606 607    def MOV#EXT#Xd16d8  : MxPseudoMove_RR<MxType16d,  MxType8d>;608    def MOV#EXT#Xd32d8  : MxPseudoMove_RR<MxType32d,  MxType8d>;609    def MOV#EXT#Xd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>;610 611    let mayLoad = 1 in {612 613      def MOV#EXT#Xd16j8   : MxPseudoMove_RM<MxType16d,  MxType8.JOp>;614      def MOV#EXT#Xd32j8   : MxPseudoMove_RM<MxType32d,  MxType8.JOp>;615      def MOV#EXT#Xd32j16  : MxPseudoMove_RM<MxType32d, MxType16.JOp>;616 617      def MOV#EXT#Xd16p8   : MxPseudoMove_RM<MxType16d,  MxType8.POp>;618      def MOV#EXT#Xd32p8   : MxPseudoMove_RM<MxType32d,  MxType8.POp>;619      def MOV#EXT#Xd32p16  : MxPseudoMove_RM<MxType32d, MxType16.POp>;620 621      def MOV#EXT#Xd16f8   : MxPseudoMove_RM<MxType16d,  MxType8.FOp>;622      def MOV#EXT#Xd32f8   : MxPseudoMove_RM<MxType32d,  MxType8.FOp>;623      def MOV#EXT#Xd32f16  : MxPseudoMove_RM<MxType32d, MxType16.FOp>;624 625      def MOV#EXT#Xd16q8   : MxPseudoMove_RM<MxType16d,  MxType8.QOp>;626      def MOV#EXT#Xd32q8   : MxPseudoMove_RM<MxType32d,  MxType8.QOp>;627      def MOV#EXT#Xd32q16  : MxPseudoMove_RM<MxType32d,  MxType16.QOp>;628 629    }630  }631}632 633/// This group of instructions is similar to the group above but DOES NOT do634/// any value extension, they just load a smaller register into the lower part635/// of another register if operands' real registers are different or does636/// nothing if they are the same.637def MOVXd16d8  : MxPseudoMove_RR<MxType16d,  MxType8d>;638def MOVXd32d8  : MxPseudoMove_RR<MxType32d,  MxType8d>;639def MOVXd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>;640 641//===----------------------------------------------------------------------===//642// Extend/Truncate Patterns643//===----------------------------------------------------------------------===//644 645// i16 <- sext i8646def: Pat<(i16 (sext i8:$src)),647          (EXTRACT_SUBREG (MOVSXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;648def: Pat<(MxSExtLoadi16i8 MxCP_ARI:$src),649          (EXTRACT_SUBREG (MOVSXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;650def: Pat<(MxSExtLoadi16i8 MxCP_ARID:$src),651          (EXTRACT_SUBREG (MOVSXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;652def: Pat<(MxSExtLoadi16i8 MxCP_ARII:$src),653          (EXTRACT_SUBREG (MOVSXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;654def: Pat<(MxSExtLoadi16i8 MxCP_PCD:$src), (MOVSXd16q8 MxPCD8:$src)>;655 656// i32 <- sext i8657def: Pat<(i32 (sext i8:$src)), (MOVSXd32d8 MxDRD8:$src)>;658def: Pat<(MxSExtLoadi32i8 MxCP_ARI :$src), (MOVSXd32j8 MxARI8 :$src)>;659def: Pat<(MxSExtLoadi32i8 MxCP_ARID:$src), (MOVSXd32p8 MxARID8:$src)>;660def: Pat<(MxSExtLoadi32i8 MxCP_ARII:$src), (MOVSXd32f8 MxARII8:$src)>;661def: Pat<(MxSExtLoadi32i8 MxCP_PCD:$src),  (MOVSXd32q8 MxPCD8:$src)>;662 663// i32 <- sext i16664def: Pat<(i32 (sext i16:$src)), (MOVSXd32d16 MxDRD16:$src)>;665def: Pat<(MxSExtLoadi32i16 MxCP_ARI :$src), (MOVSXd32j16 MxARI16 :$src)>;666def: Pat<(MxSExtLoadi32i16 MxCP_ARID:$src), (MOVSXd32p16 MxARID16:$src)>;667def: Pat<(MxSExtLoadi32i16 MxCP_ARII:$src), (MOVSXd32f16 MxARII16:$src)>;668def: Pat<(MxSExtLoadi32i16 MxCP_PCD:$src),  (MOVSXd32q16 MxPCD16:$src)>;669 670// i16 <- zext i8671def: Pat<(i16 (zext i8:$src)),672          (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;673def: Pat<(MxZExtLoadi16i8 MxCP_ARI:$src),674          (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;675def: Pat<(MxZExtLoadi16i8 MxCP_ARID:$src),676          (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;677def: Pat<(MxZExtLoadi16i8 MxCP_ARII:$src),678          (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;679def: Pat<(MxZExtLoadi16i8 MxCP_PCD :$src), (MOVZXd16q8 MxPCD8 :$src)>;680 681// i32 <- zext i8682def: Pat<(i32 (zext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>;683def: Pat<(MxZExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>;684def: Pat<(MxZExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>;685def: Pat<(MxZExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>;686def: Pat<(MxZExtLoadi32i8 MxCP_PCD :$src), (MOVZXd32q8 MxPCD8 :$src)>;687 688// i32 <- zext i16689def: Pat<(i32 (zext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>;690def: Pat<(MxZExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>;691def: Pat<(MxZExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>;692def: Pat<(MxZExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>;693def: Pat<(MxZExtLoadi32i16 MxCP_PCD :$src), (MOVZXd32q16 MxPCD16 :$src)>;694 695// i16 <- anyext i8696def: Pat<(i16 (anyext i8:$src)),697          (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;698def: Pat<(MxExtLoadi16i8 MxCP_ARI:$src),699          (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;700def: Pat<(MxExtLoadi16i8 MxCP_ARID:$src),701          (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;702def: Pat<(MxExtLoadi16i8 MxCP_ARII:$src),703          (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;704def: Pat<(MxExtLoadi16i8 MxCP_PCD:$src),705          (EXTRACT_SUBREG (MOVZXd32q8 MxPCD8:$src), MxSubRegIndex16Lo)>;706 707// i32 <- anyext i8708def: Pat<(i32 (anyext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>;709def: Pat<(MxExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>;710def: Pat<(MxExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>;711def: Pat<(MxExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>;712def: Pat<(MxExtLoadi32i8 MxCP_PCD:$src), (MOVZXd32q8 MxPCD8:$src)>;713 714// i32 <- anyext i16715def: Pat<(i32 (anyext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>;716def: Pat<(MxExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>;717def: Pat<(MxExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>;718def: Pat<(MxExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>;719def: Pat<(MxExtLoadi32i16 MxCP_PCD:$src), (MOVZXd32q16 MxPCD16:$src)>;720 721// trunc patterns722def : Pat<(i16 (trunc i32:$src)),723          (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex16Lo)>;724def : Pat<(i8  (trunc i32:$src)),725          (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex8Lo)>;726def : Pat<(i8  (trunc i16:$src)),727          (EXTRACT_SUBREG MxXRD16:$src, MxSubRegIndex8Lo)>;728 729//===----------------------------------------------------------------------===//730// FMOVE731//===----------------------------------------------------------------------===//732 733let Defs = [FPS] in734class MxFMove<string size, dag outs, dag ins, list<dag> pattern,735              string rounding = "">736    : MxInst<outs, ins,737             "f"#rounding#"move."#size#"\t$src, $dst", pattern> {738  // Only FMOVE uses FPC739  let Uses = !if(!eq(rounding, ""), [FPC], []);740 741  // FSMOVE and FDMOVE are only available after M68040742  let Predicates = [!if(!eq(rounding, ""), AtLeastM68881, AtLeastM68040)];743}744 745// FPDR <- FPDR746class MxFMove_FF<string rounding, int size,747                 MxOpBundle Opnd = !cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr")>748    : MxFMove<"x", (outs Opnd.Op:$dst), (ins Opnd.Op:$src),749              [(null_frag)], rounding> {750  let Inst = (ascend751    (descend 0b1111,752      /*COPROCESSOR ID*/0b001,753      0b000,754      /*MODE + REGISTER*/0b000000755    ),756    (descend 0b0, /* R/M */0b0, 0b0,757      /*SOURCE SPECIFIER*/758      (operand "$src", 3),759      /*DESTINATION*/760      (operand "$dst", 3),761      /*OPMODE*/762      !cond(!eq(rounding, "s"): 0b1000000,763            !eq(rounding, "d"): 0b1000100,764            true: 0b0000000)765    )766  );767}768 769foreach rounding = ["", "s", "d"] in {770  def F # !toupper(rounding) # MOV80fp_fp : MxFMove_FF<rounding, 80>;771 772  // We don't have `fmove.s` or `fmove.d` because values will be converted to773  // f80 upon storing into the register, but FMOV32/64fp_fp are still needed774  // to make codegen easier.775  let isCodeGenOnly = true in776  foreach size = [32, 64] in777    def F # !toupper(rounding) # MOV # size # fp_fp : MxFMove_FF<rounding, size>;778}779// Direction780defvar MxFMove_FP_EA = false;781defvar MxFMove_EA_FP = true;782 783// Encoding scheme for FPSYS <-> R/M784class MxEncFSysMove<bit dir, MxEncMemOp EAEnc, string fsys_reg> {785  dag Value = (ascend786    (descend 0b1111,787      /*COPROCESSOR ID*/0b001,788      0b000,789      /*MODE + REGISTER*/790      EAEnc.EA791    ),792    (descend 0b10, /*dir*/ dir,793      /*REGISTER SELECT*/794      (operand "$"#fsys_reg, 3, (encoder "encodeFPSYSSelect")),795      0b0000000000796    )797  );798}799 800// FPSYS <-> R801class MxFMove_FSYS_R<string src_reg,802                     MxOpBundle SrcOpnd = !cast<MxOpBundle>("MxOp32AddrMode_"#src_reg),803                     MxOpBundle DstOpnd = !cond(!eq(src_reg, "d"): MxOp32AddrMode_fpcs,804                                                !eq(src_reg, "a"): MxOp32AddrMode_fpi),805                     MxEncMemOp SrcEnc = !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#src_reg)>806    : MxFMove<"l", (outs DstOpnd.Op:$dst), (ins SrcOpnd.Op:$src),807              [(null_frag)]> {808  let Inst = MxEncFSysMove<MxFMove_FP_EA, SrcEnc, "dst">.Value;809}810 811class MxFMove_R_FSYS<string dst_reg,812                     MxOpBundle SrcOpnd = !cond(!eq(dst_reg, "d"): MxOp32AddrMode_fpcs,813                                                !eq(dst_reg, "a"): MxOp32AddrMode_fpi),814                     MxOpBundle DstOpnd = !cast<MxOpBundle>("MxOp32AddrMode_"#dst_reg),815                     MxEncMemOp DstEnc = !cast<MxEncMemOp>("MxMoveDstOpEnc_"#dst_reg)>816    : MxFMove<"l", (outs DstOpnd.Op:$dst), (ins SrcOpnd.Op:$src),817              [(null_frag)]> {818  let Inst = MxEncFSysMove<MxFMove_EA_FP, DstEnc, "src">.Value;819}820 821def FMOVE32fpcs_d : MxFMove_FSYS_R<"d">;822def FMOVE32d_fpcs : MxFMove_R_FSYS<"d">;823def FMOVE32fpi_a  : MxFMove_FSYS_R<"a">;824def FMOVE32a_fpi  : MxFMove_R_FSYS<"a">;825