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-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file describes the Motorola 680x0 data movement instructions which are
11/// the basic means of transferring and storing addresses and data. Here is the
12/// 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///     MOVSX [x]     MOVZX [x]     MOVX   [x]
23///
24///  Map:
25///
26///   [ ] - was not touched at all
27///   [!] - requires extarnal stuff implemented
28///   [~] - in progress but usable
29///   [x] - done
30///
31//===----------------------------------------------------------------------===//
32
33//===----------------------------------------------------------------------===//
34// MOVE
35//===----------------------------------------------------------------------===//
36
37/// -----------------------------------------------------
38///  F  E | D  C | B  A  9 | 8  7  6 | 5  4  3 | 2  1  0
39/// -----------------------------------------------------
40///       |      |    DESTINATION    |       SOURCE
41///  0  0 | SIZE |   REG   |   MODE  |   MODE  |   REG
42/// -----------------------------------------------------
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 = (ascend
56    (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 extension
62    src_enc.Supplement,
63    // Destination extension
64    dst_enc.Supplement
65  );
66}
67
68// Special encoding for Xn
69class 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  // Dn
77  def MxMove#NAME#OpEnc_d : MxEncAddrMode_d<opnd_name>;
78  // An
79  def MxMove#NAME#OpEnc_a : MxEncAddrMode_a<opnd_name>;
80  // Xn
81  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).L
95  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] in
106class 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 <- R
112class 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"] in
122  foreach TYPE = [MxType16, MxType32] in
123  def MOV # TYPE.Size # DST_REG # SRC_REG # TYPE.Postfix
124      : 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_REG
129foreach TYPE = [MxType8, MxType16, MxType32] in
130def MOV # TYPE.Size # dd # TYPE.Postfix
131    : MxMove_RR<TYPE, "d", "d",
132                MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
133                               MxMoveDstOpEnc_d, MxMoveSrcOpEnc_d>>;
134
135// M <- R
136let 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 = 1
147
148foreach REG = ["r", "a", "d"] in
149foreach AM = MxMoveSupportedAMs in {
150  foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in
151  def MOV # TYPE.Size # AM # REG # TYPE.Postfix
152      : 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 AM
157
158foreach AM = MxMoveSupportedAMs in {
159  foreach TYPE = [MxType8, MxType16, MxType32] in
160  def MOV # TYPE.Size # AM # i # TYPE.Postfix
161      : 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 AM
166
167// R <- I
168class MxMove_RI<MxType TYPE, string DST_REG, MxMoveEncoding ENC,
169                MxImmOpBundle SRC = !cast<MxImmOpBundle>("MxOp"#TYPE.Size#"AddrMode_i"),
170                MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG)>
171    : MxMove<TYPE.Prefix, (outs DST.Op:$dst), (ins SRC.Op:$src),
172              [(set TYPE.VT:$dst, SRC.ImmPat:$src)], ENC>;
173
174foreach REG = ["r", "a", "d"] in {
175  foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in
176  def MOV # TYPE.Size # REG # i # TYPE.Postfix
177      : MxMove_RI<TYPE, REG,
178                  MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
179                                 !cast<MxEncMemOp>("MxMoveDstOpEnc_"#REG),
180                                 MxEncAddrMode_i<"src", TYPE.Size>>>;
181} // foreach REG
182
183// R <- M
184let mayLoad = 1 in
185class MxMove_RM<MxType TYPE, string DST_REG, MxOpBundle SRC, MxEncMemOp SRC_ENC,
186                MxMoveSize SIZE_ENC = !cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
187                MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG),
188                MxEncMemOp DST_ENC = !cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_REG)>
189    : MxMove<TYPE.Prefix, (outs DST.Op:$dst), (ins SRC.Op:$src),
190             [(set TYPE.VT:$dst, (TYPE.Load SRC.Pat:$src))],
191             MxMoveEncoding<SIZE_ENC, DST_ENC, SRC_ENC>>;
192
193foreach REG = ["r", "a", "d"] in
194foreach AM = MxMoveSupportedAMs in {
195  foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in
196  def MOV # TYPE.Size # REG # AM # TYPE.Postfix
197      : MxMove_RM<TYPE, REG, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),
198                  !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;
199} // foreach AM
200
201// Tail call version
202let Pattern = [(null_frag)] in {
203  foreach REG = ["r", "a"] in
204  foreach AM = MxMoveSupportedAMs in {
205    foreach TYPE = [MxType16, MxType32] in
206    def MOV # TYPE.Size # REG # AM # _TC
207        : MxMove_RM<TYPE, REG, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),
208                    !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)> {
209      let isCodeGenOnly = true;
210    }
211  } // foreach AM
212} // let Pattern
213
214let mayLoad = 1, mayStore = 1 in
215class MxMove_MM<MxType TYPE, MxOpBundle DST, MxOpBundle SRC,
216                MxEncMemOp DST_ENC, MxEncMemOp SRC_ENC>
217    : MxMove<TYPE.Prefix, (outs), (ins DST.Op:$dst, SRC.Op:$src),
218             [(store (TYPE.Load SRC.Pat:$src), DST.Pat:$dst)],
219             MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
220                            DST_ENC, SRC_ENC>>;
221
222foreach DST_AM = MxMoveSupportedAMs in
223foreach SRC_AM = MxMoveSupportedAMs in {
224  foreach TYPE = [MxType8, MxType16, MxType32] in
225  def MOV # TYPE.Size # DST_AM # SRC_AM # TYPE.Postfix
226      : MxMove_MM<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_AM),
227                  !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#SRC_AM),
228                  !cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_AM),
229                  !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#SRC_AM)>;
230} // foreach SRC_AM
231
232// Store ABS(basically pointer) as Immdiate to Mem
233def : Pat<(store   MxType32.BPat :$src, MxType32.PPat :$dst),
234          (MOV32pi MxType32.POp  :$dst, MxType32.IOp  :$src)>;
235
236def : Pat<(store   MxType32.BPat :$src, MxType32.FPat :$dst),
237          (MOV32fi MxType32.FOp  :$dst, MxType32.IOp  :$src)>;
238
239def : Pat<(store   MxType32.BPat :$src, MxType32.BPat :$dst),
240          (MOV32bi MxType32.BOp  :$dst, MxType32.IOp  :$src)>;
241
242def : Pat<(store   MxType32.BPat :$src, MxType32.JPat :$dst),
243          (MOV32ji MxType32.JOp  :$dst, MxType32.IOp  :$src)>;
244
245//===----------------------------------------------------------------------===//
246// MOVEM
247//
248// The mask is already pre-processed by the save/restore spill hook
249//===----------------------------------------------------------------------===//
250
251// Direction
252defvar MxMOVEM_MR = false;
253defvar MxMOVEM_RM = true;
254
255// Size
256defvar MxMOVEM_W = false;
257defvar MxMOVEM_L = true;
258
259/// ---------------+-------------+-------------+---------
260///  F  E  D  C  B | A | 9  8  7 | 6 | 5  4  3 | 2  1  0
261/// ---------------+---+---------+---+---------+---------
262///  0  1  0  0  1 | D | 0  0  1 | S |   MODE  |   REG
263/// ---------------+---+---------+---+---------+---------
264///                  REGISTER LIST MASK
265/// -----------------------------------------------------
266/// D - direction(RM,MR)
267/// S - size(W,L)
268class MxMOVEMEncoding<MxEncMemOp opnd_enc, bit size, bit direction,
269                      string mask_op_name> {
270  dag Value = (ascend
271    (descend 0b01001, direction, 0b001, size, opnd_enc.EA),
272    // Mask
273    (operand "$"#mask_op_name, 16),
274    opnd_enc.Supplement
275  );
276}
277
278let mayStore = 1 in
279class MxMOVEM_MR<MxType TYPE, bit SIZE_ENC,
280                 MxOperand MEMOp, MxEncMemOp MEM_ENC>
281    : MxInst<(outs), (ins MEMOp:$dst, MxMoveMask:$mask),
282             "movem."#TYPE.Prefix#"\t$mask, $dst", []> {
283  let Inst = MxMOVEMEncoding<MEM_ENC, SIZE_ENC, MxMOVEM_MR, "mask">.Value;
284}
285
286foreach AM = MxMoveSupportedAMs in {
287  foreach TYPE = [MxType16, MxType32] in
288  def MOVM # TYPE.Size # AM # m # TYPE.Postfix
289      : MxMOVEM_MR<TYPE, !if(!eq(TYPE, MxType16), MxMOVEM_W, MxMOVEM_L),
290                   !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM).Op,
291                   !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM)>;
292} // foreach AM
293
294let mayLoad = 1 in
295class MxMOVEM_RM<MxType TYPE, bit SIZE_ENC,
296                 MxOperand MEMOp, MxEncMemOp MEM_ENC>
297    : MxInst<(outs), (ins MxMoveMask:$mask, MEMOp:$src),
298             "movem."#TYPE.Prefix#"\t$src, $mask", []> {
299  let Inst = MxMOVEMEncoding<MEM_ENC, SIZE_ENC, MxMOVEM_RM, "mask">.Value;
300}
301
302foreach AM = MxMoveSupportedAMs in {
303  foreach TYPE = [MxType16, MxType32] in
304  def MOVM # TYPE.Size # m # AM # TYPE.Postfix
305      : MxMOVEM_RM<TYPE, !if(!eq(TYPE, MxType16), MxMOVEM_W, MxMOVEM_L),
306                   !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM).Op,
307                   !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;
308} // foreach AM
309
310// Pseudo versions. These a required by virtual register spill/restore since
311// the mask requires real register to encode. These instruction will be expanded
312// into real MOVEM after RA finishes.
313let mayStore = 1 in
314class MxMOVEM_MR_Pseudo<MxType TYPE, MxOperand MEMOp>
315    : MxPseudo<(outs), (ins MEMOp:$dst, TYPE.ROp:$reg)>;
316let mayLoad = 1 in
317class MxMOVEM_RM_Pseudo<MxType TYPE, MxOperand MEMOp>
318    : MxPseudo<(outs TYPE.ROp:$dst), (ins MEMOp:$src)>;
319
320// Mem <- Reg
321def MOVM8jm_P  : MxMOVEM_MR_Pseudo<MxType8d,  MxType8.JOp>;
322def MOVM16jm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.JOp>;
323def MOVM32jm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.JOp>;
324
325def MOVM8pm_P  : MxMOVEM_MR_Pseudo<MxType8d,  MxType8.POp>;
326def MOVM16pm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.POp>;
327def MOVM32pm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.POp>;
328
329// Reg <- Mem
330def MOVM8mj_P  : MxMOVEM_RM_Pseudo<MxType8d,  MxType8.JOp>;
331def MOVM16mj_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.JOp>;
332def MOVM32mj_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.JOp>;
333
334def MOVM8mp_P  : MxMOVEM_RM_Pseudo<MxType8d,  MxType8.POp>;
335def MOVM16mp_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.POp>;
336def MOVM32mp_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.POp>;
337
338
339//===----------------------------------------------------------------------===//
340// MOVE to/from SR/CCR
341//
342// A special care must be taken working with to/from CCR since it is basically
343// word-size SR register truncated for user mode thus it only supports word-size
344// instructions. Plus the original M68000 does not support moves from CCR. So in
345// order to use CCR effectively one MUST use proper byte-size pseudo instructi-
346// ons that will be resolved sometime after RA pass.
347//===----------------------------------------------------------------------===//
348
349/// --------------------------------------------------
350///  F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0
351/// --------------------------------------------------
352///                               | EFFECTIVE ADDRESS
353///  0  1  0  0  0  1  0  0  1  1 |   MODE  |   REG
354/// --------------------------------------------------
355let Defs = [CCR] in
356class MxMoveToCCR<MxOperand MEMOp, MxEncMemOp SRC_ENC>
357    : MxInst<(outs CCRC:$dst), (ins MEMOp:$src), "move.w\t$src, $dst", []> {
358  let Inst = (ascend
359    (descend 0b0100010011, SRC_ENC.EA),
360    SRC_ENC.Supplement
361  );
362}
363
364class MxMoveToCCRPseudo<MxOperand MEMOp>
365    : MxPseudo<(outs CCRC:$dst), (ins MEMOp:$src)>;
366
367let mayLoad = 1 in
368foreach AM = MxMoveSupportedAMs in {
369  def MOV16c # AM : MxMoveToCCR<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,
370                                !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;
371  def MOV8c # AM  : MxMoveToCCRPseudo<!cast<MxOpBundle>("MxOp8AddrMode_"#AM).Op>;
372} // foreach AM
373
374// Only data register is allowed.
375def MOV16cd : MxMoveToCCR<MxOp16AddrMode_d.Op, MxMoveSrcOpEnc_d>;
376def MOV8cd  : MxMoveToCCRPseudo<MxOp8AddrMode_d.Op>;
377
378/// Move from CCR
379/// --------------------------------------------------
380///  F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0
381/// --------------------------------------------------
382///                               | EFFECTIVE ADDRESS
383///  0  1  0  0  0  0  1  0  1  1 |   MODE  |   REG
384/// --------------------------------------------------
385let Uses = [CCR] in {
386class MxMoveFromCCR_R
387    : MxInst<(outs MxDRD16:$dst), (ins CCRC:$src), "move.w\t$src, $dst", []>,
388      Requires<[ IsM68010 ]> {
389  let Inst = (descend 0b0100001011, MxEncAddrMode_d<"dst">.EA);
390}
391
392class MxMoveFromCCR_M<MxOperand MEMOp, MxEncMemOp DST_ENC>
393    : MxInst<(outs), (ins MEMOp:$dst, CCRC:$src), "move.w\t$src, $dst", []>,
394      Requires<[ IsM68010 ]> {
395  let Inst = (ascend
396    (descend 0b0100001011, DST_ENC.EA),
397    DST_ENC.Supplement
398  );
399}
400
401class MxMoveFromCCRPseudo<MxOperand MEMOp>
402    : MxPseudo<(outs), (ins MEMOp:$dst, CCRC:$src)>;
403} // let Uses = [CCR]
404
405let mayStore = 1 in
406foreach AM = MxMoveSupportedAMs in {
407  def MOV16 # AM # c
408    : MxMoveFromCCR_M<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,
409                      !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM)>;
410  def MOV8 # AM # c
411    : MxMoveFromCCRPseudo<!cast<MxOpBundle>("MxOp8AddrMode_"#AM).Op>;
412} // foreach AM
413
414// Only data register is allowed.
415def MOV16dc : MxMoveFromCCR_R;
416def MOV8dc  : MxMoveFromCCRPseudo<MxOp8AddrMode_d.Op>;
417
418//===----------------------------------------------------------------------===//
419// LEA
420//===----------------------------------------------------------------------===//
421
422/// ----------------------------------------------------
423///  F  E  D  C | B  A  9 | 8  7  6 | 5  4  3 | 2  1  0
424/// ----------------------------------------------------
425///  0  1  0  0 | DST REG | 1  1  1 |   MODE  |   REG
426/// ----------------------------------------------------
427class MxLEA<MxOpBundle SRC, MxEncMemOp SRC_ENC>
428    : MxInst<(outs MxARD32:$dst), (ins SRC.Op:$src),
429             "lea\t$src, $dst", [(set i32:$dst, SRC.Pat:$src)]> {
430  let Inst = (ascend
431    (descend 0b0100, (operand "$dst", 3), 0b111, SRC_ENC.EA),
432    SRC_ENC.Supplement
433  );
434}
435
436foreach AM = ["p", "f", "b", "q", "k"] in
437def LEA32 # AM : MxLEA<!cast<MxOpBundle>("MxOp32AddrMode_"#AM),
438                       !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;
439
440//===----------------------------------------------------------------------===//
441// Pseudos
442//===----------------------------------------------------------------------===//
443
444/// Pushe/Pop to/from SP for simplicity
445let Uses = [SP], Defs = [SP], hasSideEffects = 0 in {
446
447// SP <- SP - <size>; (SP) <- Dn
448let mayStore = 1 in {
449def PUSH8d  : MxPseudo<(outs), (ins DR8:$reg)>;
450def PUSH16d : MxPseudo<(outs), (ins DR16:$reg)>;
451def PUSH32r : MxPseudo<(outs), (ins XR32:$reg)>;
452} // let mayStore = 1
453
454// Dn <- (SP); SP <- SP + <size>
455let mayLoad = 1 in {
456def POP8d  : MxPseudo<(outs DR8:$reg),  (ins)>;
457def POP16d : MxPseudo<(outs DR16:$reg), (ins)>;
458def POP32r : MxPseudo<(outs XR32:$reg), (ins)>;
459} // let mayLoad = 1
460
461} // let Uses/Defs = [SP], hasSideEffects = 0
462
463
464let Defs = [CCR] in {
465class MxPseudoMove_RR<MxType DST, MxType SRC, list<dag> PAT = []>
466    : MxPseudo<(outs DST.ROp:$dst), (ins SRC.ROp:$src), PAT>;
467
468class MxPseudoMove_RM<MxType DST, MxOperand SRCOpd, list<dag> PAT = []>
469    : MxPseudo<(outs DST.ROp:$dst), (ins SRCOpd:$src), PAT>;
470}
471
472/// This group of Pseudos is analogues to the real x86 extending moves, but
473/// since M68k does not have those we need to emulate. These instructions
474/// will be expanded right after RA completed because we need to know precisely
475/// what registers are allocated for the operands and if they overlap we just
476/// extend the value if the registers are completely different we need to move
477/// first.
478foreach EXT = ["S", "Z"] in {
479  let hasSideEffects = 0 in {
480
481    def MOV#EXT#Xd16d8  : MxPseudoMove_RR<MxType16d,  MxType8d>;
482    def MOV#EXT#Xd32d8  : MxPseudoMove_RR<MxType32d,  MxType8d>;
483    def MOV#EXT#Xd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>;
484
485    let mayLoad = 1 in {
486
487      def MOV#EXT#Xd16j8   : MxPseudoMove_RM<MxType16d,  MxType8.JOp>;
488      def MOV#EXT#Xd32j8   : MxPseudoMove_RM<MxType32d,  MxType8.JOp>;
489      def MOV#EXT#Xd32j16  : MxPseudoMove_RM<MxType32d, MxType16.JOp>;
490
491      def MOV#EXT#Xd16p8   : MxPseudoMove_RM<MxType16d,  MxType8.POp>;
492      def MOV#EXT#Xd32p8   : MxPseudoMove_RM<MxType32d,  MxType8.POp>;
493      def MOV#EXT#Xd32p16  : MxPseudoMove_RM<MxType32d, MxType16.POp>;
494
495      def MOV#EXT#Xd16f8   : MxPseudoMove_RM<MxType16d,  MxType8.FOp>;
496      def MOV#EXT#Xd32f8   : MxPseudoMove_RM<MxType32d,  MxType8.FOp>;
497      def MOV#EXT#Xd32f16  : MxPseudoMove_RM<MxType32d, MxType16.FOp>;
498
499    }
500  }
501}
502
503/// This group of instructions is similar to the group above but DOES NOT do
504/// any value extension, they just load a smaller register into the lower part
505/// of another register if operands' real registers are different or does
506/// nothing if they are the same.
507def MOVXd16d8  : MxPseudoMove_RR<MxType16d,  MxType8d>;
508def MOVXd32d8  : MxPseudoMove_RR<MxType32d,  MxType8d>;
509def MOVXd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>;
510
511//===----------------------------------------------------------------------===//
512// Extend/Truncate Patterns
513//===----------------------------------------------------------------------===//
514
515// i16 <- sext i8
516def: Pat<(i16 (sext i8:$src)),
517          (EXTRACT_SUBREG (MOVSXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
518def: Pat<(MxSExtLoadi16i8 MxCP_ARI:$src),
519          (EXTRACT_SUBREG (MOVSXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
520def: Pat<(MxSExtLoadi16i8 MxCP_ARID:$src),
521          (EXTRACT_SUBREG (MOVSXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
522def: Pat<(MxSExtLoadi16i8 MxCP_ARII:$src),
523          (EXTRACT_SUBREG (MOVSXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
524
525// i32 <- sext i8
526def: Pat<(i32 (sext i8:$src)), (MOVSXd32d8 MxDRD8:$src)>;
527def: Pat<(MxSExtLoadi32i8 MxCP_ARI :$src), (MOVSXd32j8 MxARI8 :$src)>;
528def: Pat<(MxSExtLoadi32i8 MxCP_ARID:$src), (MOVSXd32p8 MxARID8:$src)>;
529def: Pat<(MxSExtLoadi32i8 MxCP_ARII:$src), (MOVSXd32f8 MxARII8:$src)>;
530
531// i32 <- sext i16
532def: Pat<(i32 (sext i16:$src)), (MOVSXd32d16 MxDRD16:$src)>;
533def: Pat<(MxSExtLoadi32i16 MxCP_ARI :$src), (MOVSXd32j16 MxARI16 :$src)>;
534def: Pat<(MxSExtLoadi32i16 MxCP_ARID:$src), (MOVSXd32p16 MxARID16:$src)>;
535def: Pat<(MxSExtLoadi32i16 MxCP_ARII:$src), (MOVSXd32f16 MxARII16:$src)>;
536
537// i16 <- zext i8
538def: Pat<(i16 (zext i8:$src)),
539          (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
540def: Pat<(MxZExtLoadi16i8 MxCP_ARI:$src),
541          (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
542def: Pat<(MxZExtLoadi16i8 MxCP_ARID:$src),
543          (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
544def: Pat<(MxZExtLoadi16i8 MxCP_ARII:$src),
545          (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
546
547// i32 <- zext i8
548def: Pat<(i32 (zext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>;
549def: Pat<(MxZExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>;
550def: Pat<(MxZExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>;
551def: Pat<(MxZExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>;
552
553// i32 <- zext i16
554def: Pat<(i32 (zext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>;
555def: Pat<(MxZExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>;
556def: Pat<(MxZExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>;
557def: Pat<(MxZExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>;
558
559// i16 <- anyext i8
560def: Pat<(i16 (anyext i8:$src)),
561          (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
562def: Pat<(MxExtLoadi16i8 MxCP_ARI:$src),
563          (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
564def: Pat<(MxExtLoadi16i8 MxCP_ARID:$src),
565          (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
566def: Pat<(MxExtLoadi16i8 MxCP_ARII:$src),
567          (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
568
569// i32 <- anyext i8
570def: Pat<(i32 (anyext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>;
571def: Pat<(MxExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>;
572def: Pat<(MxExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>;
573def: Pat<(MxExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>;
574
575// i32 <- anyext i16
576def: Pat<(i32 (anyext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>;
577def: Pat<(MxExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>;
578def: Pat<(MxExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>;
579def: Pat<(MxExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>;
580
581// trunc patterns
582def : Pat<(i16 (trunc i32:$src)),
583          (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex16Lo)>;
584def : Pat<(i8  (trunc i32:$src)),
585          (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex8Lo)>;
586def : Pat<(i8  (trunc i16:$src)),
587          (EXTRACT_SUBREG MxXRD16:$src, MxSubRegIndex8Lo)>;
588