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)
45class MxMoveEncoding<MxBead2Bits size,
46                     MxEncEA srcEA, MxEncExt srcExt,
47                     MxEncEA dstEA, MxEncExt dstExt>
48    : MxEncoding<srcEA.Reg, srcEA.DA, srcEA.Mode, dstEA.DA, dstEA.Mode, dstEA.Reg,
49                 size, MxBead2Bits<0b00>,
50                 srcExt.Imm, srcExt.B8, srcExt.Scale, srcExt.WL, srcExt.DAReg,
51                 dstExt.Imm, dstExt.B8, dstExt.Scale, dstExt.WL, dstExt.DAReg>;
52
53/// MOVE has alternate size encoding
54class MxMoveSize<bits<2> value> : MxBead2Bits<value>;
55def MxMoveSize8  : MxMoveSize<0b01>;
56def MxMoveSize16 : MxMoveSize<0b11>;
57def MxMoveSize32 : MxMoveSize<0b10>;
58
59let Defs = [CCR] in
60class MxMove<string size, dag outs, dag ins, list<dag> pattern, MxEncoding enc>
61    : MxInst<outs, ins, "move."#size#"\t$src, $dst", pattern, enc>;
62
63class MxMove_RR<MxType DST, MxType SRC, MxMoveEncoding ENC>
64    : MxMove<DST.Prefix, (outs DST.ROp:$dst), (ins SRC.ROp:$src),
65             [(null_frag)], ENC>;
66
67let mayStore = 1 in {
68class MxMove_MR<MxOperand MEMOpd, ComplexPattern MEMPat, MxType REG,
69                MxMoveEncoding ENC>
70    : MxMove<REG.Prefix, (outs), (ins MEMOpd:$dst, REG.ROp:$src),
71             [(store REG.VT:$src, MEMPat:$dst)], ENC>;
72
73class MxMove_MI<MxOperand MEMOpd, ComplexPattern MEMPat, MxType TYPE,
74                MxMoveEncoding ENC>
75    : MxMove<TYPE.Prefix, (outs), (ins MEMOpd:$dst, TYPE.IOp:$src),
76             [(store TYPE.IPat:$src, MEMPat:$dst)], ENC>;
77} // let mayStore = 1
78
79class MxMove_RI<MxType DST, MxMoveEncoding ENC>
80    : MxMove<DST.Prefix, (outs DST.ROp:$dst), (ins DST.IOp:$src),
81              [(set DST.VT:$dst, DST.IPat:$src)], ENC>;
82
83
84let mayLoad = 1 in
85class MxMove_RM<MxType REG, MxOperand MEMOpd, ComplexPattern MEMPat,
86                MxBead2Bits SIZE,
87                MxEncEA SRCEA, MxEncExt SRCEXT,
88                MxEncEA DSTEA, MxEncExt DSTEXT>
89    : MxMove<REG.Prefix, (outs REG.ROp:$dst), (ins MEMOpd:$src),
90             [(set REG.VT:$dst, (REG.Load MEMPat:$src))],
91             MxMoveEncoding<SIZE, SRCEA, SRCEXT, DSTEA, DSTEXT>>;
92
93multiclass MMxMove_RM<MxType REG, MxMoveSize SIZE, MxEncEA EA_0> {
94
95  // REG <- (An)+
96  def NAME#REG.OOp.Letter#REG.Postfix : MxMove_RM<REG, REG.OOp, REG.OPat,
97      SIZE, MxEncEAo_1, MxExtEmpty, EA_0, MxExtEmpty>;
98
99  // REG <- -(An)
100  def NAME#REG.EOp.Letter#REG.Postfix : MxMove_RM<REG, REG.EOp, REG.EPat,
101      SIZE, MxEncEAe_1, MxExtEmpty, EA_0, MxExtEmpty>;
102
103  // REG <- (i,PC,Xn)
104  def NAME#REG.KOp.Letter#REG.Postfix : MxMove_RM<REG, REG.KOp, REG.KPat,
105      SIZE, MxEncEAk, MxExtBrief_1, EA_0, MxExtEmpty>;
106
107  // REG <- (i,PC)
108  def NAME#REG.QOp.Letter#REG.Postfix : MxMove_RM<REG, REG.QOp, REG.QPat,
109      SIZE, MxEncEAq, MxExtI16_1, EA_0, MxExtEmpty>;
110
111  // REG <- (i,An,Xn)
112  def NAME#REG.FOp.Letter#REG.Postfix : MxMove_RM<REG, REG.FOp, REG.FPat,
113      SIZE, MxEncEAf_1, MxExtBrief_1, EA_0, MxExtEmpty>;
114
115  // REG <- (i,An)
116  def NAME#REG.POp.Letter#REG.Postfix : MxMove_RM<REG, REG.POp, REG.PPat,
117      SIZE, MxEncEAp_1, MxExtI16_1, EA_0, MxExtEmpty>;
118
119  // REG <- (ABS)
120  def NAME#REG.BOp.Letter#REG.Postfix : MxMove_RM<REG, REG.BOp, REG.BPat,
121      SIZE, MxEncEAb, MxExtI32_1, EA_0, MxExtEmpty>;
122
123  // REG <- (An)
124  def NAME#REG.JOp.Letter#REG.Postfix : MxMove_RM<REG, REG.JOp, REG.JPat,
125      SIZE, MxEncEAj_1, MxExtEmpty, EA_0, MxExtEmpty>;
126}
127
128let mayLoad = 1, mayStore = 1 in {
129class MxMove_MM<string SIZE, PatFrag LOAD,
130                MxOperand DSTOpd, ComplexPattern DSTPat,
131                MxOperand SRCOpd, ComplexPattern SRCPat,
132                MxBead2Bits ESIZE,
133                MxEncEA SRCEA, MxEncExt SRCEXT,
134                MxEncEA DSTEA, MxEncExt DSTEXT>
135    : MxMove<SIZE, (outs), (ins DSTOpd:$dst, SRCOpd:$src),
136             [(store (LOAD SRCPat:$src), DSTPat:$dst)],
137             MxMoveEncoding<ESIZE, SRCEA, SRCEXT, DSTEA, DSTEXT>>;
138} // let mayLoad = 1, mayStore = 1
139
140multiclass MMxMove_MM<MxType TYPE, MxOperand DSTOpd, ComplexPattern DSTPat,
141                      MxMoveSize SIZE, MxEncEA EA_0, MxEncExt EXT_0> {
142
143  // MEM <- (An)+
144  def NAME#TYPE.OOp.Letter#TYPE.Postfix
145    : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.OOp, TYPE.OPat,
146                SIZE, MxEncEAo_1, MxExtEmpty, EA_0, EXT_0>;
147
148  // MEM <- -(An)
149  def NAME#TYPE.EOp.Letter#TYPE.Postfix
150    : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.EOp, TYPE.EPat,
151                SIZE, MxEncEAe_1, MxExtEmpty, EA_0, EXT_0>;
152
153  // MEM <- (i,An)
154  def NAME#TYPE.POp.Letter#TYPE.Postfix
155    : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.POp, TYPE.PPat,
156                SIZE, MxEncEAp_1, MxExtI16_1, EA_0, EXT_0>;
157
158  // MEM <- (i,An,Xn)
159  def NAME#TYPE.FOp.Letter#TYPE.Postfix
160    : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.FOp, TYPE.FPat,
161                SIZE, MxEncEAf_1, MxExtBrief_1, EA_0, EXT_0>;
162
163  // MEM <- (i,PC,Xn)
164  def NAME#TYPE.KOp.Letter#TYPE.Postfix
165    : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.KOp, TYPE.KPat,
166                SIZE, MxEncEAk, MxExtBrief_1, EA_0, EXT_0>;
167
168  // MEM <- (i,PC)
169  def NAME#TYPE.QOp.Letter#TYPE.Postfix
170    : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.QOp, TYPE.QPat,
171                SIZE, MxEncEAq, MxExtI16_1, EA_0, EXT_0>;
172
173  // MEM <- (ABS)
174  def NAME#TYPE.BOp.Letter#TYPE.Postfix
175    : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.BOp, TYPE.BPat,
176                SIZE, MxEncEAb, MxExtI32_1, EA_0, EXT_0>;
177
178  // MEM <- (An)
179  def NAME#TYPE.JOp.Letter#TYPE.Postfix
180    : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.JOp, TYPE.JPat,
181                SIZE, MxEncEAj_1, MxExtEmpty, EA_0, EXT_0>;
182}
183
184def MOV8dd
185  : MxMove_RR<MxType8d, MxType8d,
186    MxMoveEncoding<MxMoveSize8, MxEncEAd_1, MxExtEmpty, MxEncEAd_0, MxExtEmpty>>;
187
188// M <- R
189def MOV8fd : MxMove_MR<MxType8.FOp, MxType8.FPat, MxType8d,
190                       MxMoveEncoding<MxMoveSize8,
191                            /*src*/   MxEncEAd_1, MxExtEmpty,
192                            /*dst*/   MxEncEAf_0, MxExtBrief_0>>;
193
194def MOV8pd : MxMove_MR<MxType8.POp, MxType8.PPat, MxType8d,
195                       MxMoveEncoding<MxMoveSize8,
196                            /*src*/   MxEncEAd_1, MxExtEmpty,
197                            /*dst*/   MxEncEAp_0, MxExtI16_0>>;
198
199def MOV8ed : MxMove_MR<MxType8.EOp, MxType8.EPat, MxType8d,
200                       MxMoveEncoding<MxMoveSize8,
201                            /*src*/   MxEncEAd_1, MxExtEmpty,
202                            /*dst*/   MxEncEAe_0, MxExtEmpty>>;
203
204def MOV8od : MxMove_MR<MxType8.OOp, MxType8.OPat, MxType8d,
205                       MxMoveEncoding<MxMoveSize8,
206                            /*src*/   MxEncEAd_1, MxExtEmpty,
207                            /*dst*/   MxEncEAo_0, MxExtEmpty>>;
208
209def MOV8bd : MxMove_MR<MxType8.BOp, MxType8.BPat, MxType8d,
210                       MxMoveEncoding<MxMoveSize8,
211                            /*src*/   MxEncEAd_1, MxExtEmpty,
212                            /*dst*/   MxEncEAb,   MxExtI32_0>>;
213
214def MOV8jd : MxMove_MR<MxType8.JOp, MxType8.JPat, MxType8d,
215                       MxMoveEncoding<MxMoveSize8,
216                            /*src*/   MxEncEAd_1, MxExtEmpty,
217                            /*dst*/   MxEncEAj_0, MxExtEmpty>>;
218
219
220// R <- I
221def MOV8di : MxMove_RI<MxType8d,
222    MxMoveEncoding<MxMoveSize8, MxEncEAi, MxExtI8_1, MxEncEAd_0, MxExtEmpty>>;
223
224foreach S = [16, 32] in {
225  foreach D = [ "r", "a" ] in {
226
227    foreach O = [ "r", "a" ] in {
228      def MOV#S#D#O : MxMove_RR<
229        !cast<MxType>("MxType"#S#D),
230        !cast<MxType>("MxType"#S#O),
231        MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
232                       !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
233                       !cast<MxEncEA>("MxEncEA"#D#"_0_reflected"), MxExtEmpty>>;
234    }
235
236    // M <- R
237    def MOV#S#"f"#D : MxMove_MR<
238      !cast<MxType>("MxType"#S).FOp,
239      !cast<MxType>("MxType"#S).FPat,
240      !cast<MxType>("MxType"#S#D),
241      MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
242                     !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
243                     MxEncEAf_0, MxExtBrief_0>>;
244
245    def MOV#S#"p"#D : MxMove_MR<
246      !cast<MxType>("MxType"#S).POp,
247      !cast<MxType>("MxType"#S).PPat,
248      !cast<MxType>("MxType"#S#D),
249      MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
250                     !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
251                     MxEncEAp_0, MxExtI16_0>>;
252
253    def MOV#S#"e"#D : MxMove_MR<
254      !cast<MxType>("MxType"#S).EOp,
255      !cast<MxType>("MxType"#S).EPat,
256      !cast<MxType>("MxType"#S#D),
257      MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
258                     !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
259                     MxEncEAe_0, MxExtEmpty>>;
260
261    def MOV#S#"o"#D : MxMove_MR<
262      !cast<MxType>("MxType"#S).OOp,
263      !cast<MxType>("MxType"#S).OPat,
264      !cast<MxType>("MxType"#S#D),
265      MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
266                     !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
267                     MxEncEAo_0, MxExtEmpty>>;
268
269    def MOV#S#"b"#D : MxMove_MR<
270      !cast<MxType>("MxType"#S).BOp,
271      !cast<MxType>("MxType"#S).BPat,
272      !cast<MxType>("MxType"#S#D),
273      MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
274                     !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
275                     MxEncEAb, MxExtI32_0>>;
276
277    def MOV#S#"j"#D : MxMove_MR<
278      !cast<MxType>("MxType"#S).JOp,
279      !cast<MxType>("MxType"#S).JPat,
280      !cast<MxType>("MxType"#S#D),
281      MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
282                     !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
283                     MxEncEAj_0, MxExtEmpty>>;
284
285
286    // R <- I
287    def MOV#S#D#"i" : MxMove_RI<
288      !cast<MxType>("MxType"#S#D),
289      MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
290                     MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
291                     !cast<MxEncEA>("MxEncEA"#D#"_0_reflected"), MxExtEmpty>>;
292  }
293}
294
295// M <- I
296foreach S = [8, 16, 32] in {
297  def MOV#S#"f"#"i" : MxMove_MI<
298    !cast<MxType>("MxType"#S).FOp,
299    !cast<MxType>("MxType"#S).FPat,
300    !cast<MxType>("MxType"#S),
301    MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
302                   MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
303                   MxEncEAf_0, MxExtBrief_0>>;
304
305  def MOV#S#"p"#"i" : MxMove_MI<
306    !cast<MxType>("MxType"#S).POp,
307    !cast<MxType>("MxType"#S).PPat,
308    !cast<MxType>("MxType"#S),
309    MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
310                   MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
311                   MxEncEAp_0, MxExtI16_0>>;
312
313  def MOV#S#"b"#"i" : MxMove_MI<
314    !cast<MxType>("MxType"#S).BOp,
315    !cast<MxType>("MxType"#S).BPat,
316    !cast<MxType>("MxType"#S),
317    MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
318                   MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
319                   MxEncEAb, MxExtI32_0>>;
320
321  def MOV#S#"j"#"i" : MxMove_MI<
322    !cast<MxType>("MxType"#S).JOp,
323    !cast<MxType>("MxType"#S).JPat,
324    !cast<MxType>("MxType"#S),
325    MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
326                   MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
327                   MxEncEAj_0, MxExtEmpty>>;
328}
329
330// Store ABS(basically pointer) as Immdiate to Mem
331def : Pat<(store   MxType32.BPat :$src, MxType32.PPat :$dst),
332          (MOV32pi MxType32.POp  :$dst, MxType32.IOp  :$src)>;
333
334def : Pat<(store   MxType32.BPat :$src, MxType32.FPat :$dst),
335          (MOV32fi MxType32.FOp  :$dst, MxType32.IOp  :$src)>;
336
337def : Pat<(store   MxType32.BPat :$src, MxType32.BPat :$dst),
338          (MOV32bi MxType32.BOp  :$dst, MxType32.IOp  :$src)>;
339
340def : Pat<(store   MxType32.BPat :$src, MxType32.JPat :$dst),
341          (MOV32ji MxType32.JOp  :$dst, MxType32.IOp  :$src)>;
342
343// R <- M
344defm MOV8d  : MMxMove_RM<MxType8d, MxMoveSize8, MxEncEAd_0>;
345
346defm MOV16r : MMxMove_RM<MxType16r, MxMoveSize16, MxEncEAr_0_reflected>;
347defm MOV16a : MMxMove_RM<MxType16a, MxMoveSize16, MxEncEAa_0>;
348
349defm MOV32r : MMxMove_RM<MxType32r, MxMoveSize32, MxEncEAr_0_reflected>;
350defm MOV32a : MMxMove_RM<MxType32a, MxMoveSize32, MxEncEAa_0>;
351
352let Pattern = [(null_frag)] in {
353defm MOV16r : MMxMove_RM<MxType16r_TC, MxMoveSize16, MxEncEAr_0_reflected>;
354defm MOV16a : MMxMove_RM<MxType16a_TC, MxMoveSize16, MxEncEAa_0>;
355
356defm MOV32r : MMxMove_RM<MxType32r_TC, MxMoveSize32, MxEncEAr_0_reflected>;
357defm MOV32a : MMxMove_RM<MxType32a_TC, MxMoveSize32, MxEncEAa_0>;
358} // Pattern
359
360// M <- M
361defm MOV8p  : MMxMove_MM<MxType8,      MxType8.POp,  MxType8.PPat,
362                         MxMoveSize8,  MxEncEAp_0,   MxExtI16_0>;
363defm MOV16p : MMxMove_MM<MxType16,     MxType16.POp, MxType16.PPat,
364                         MxMoveSize16, MxEncEAp_0,   MxExtI16_0>;
365defm MOV32p : MMxMove_MM<MxType32,     MxType32.POp, MxType32.PPat,
366                         MxMoveSize32, MxEncEAp_0,   MxExtI16_0>;
367
368defm MOV8f  : MMxMove_MM<MxType8,      MxType8.FOp,  MxType8.FPat,
369                         MxMoveSize8,  MxEncEAf_0,   MxExtBrief_0>;
370defm MOV16f : MMxMove_MM<MxType16,     MxType16.FOp, MxType16.FPat,
371                         MxMoveSize16, MxEncEAf_0,   MxExtBrief_0>;
372defm MOV32f : MMxMove_MM<MxType32,     MxType32.FOp, MxType32.FPat,
373                         MxMoveSize32, MxEncEAf_0,   MxExtBrief_0>;
374
375defm MOV8b  : MMxMove_MM<MxType8,      MxType8.BOp,  MxType8.BPat,
376                         MxMoveSize8,  MxEncEAb,     MxExtI32_0>;
377defm MOV16b : MMxMove_MM<MxType16,     MxType16.BOp, MxType16.BPat,
378                         MxMoveSize16, MxEncEAb,     MxExtI32_0>;
379defm MOV32b : MMxMove_MM<MxType32,     MxType32.BOp, MxType32.BPat,
380                         MxMoveSize32, MxEncEAb,     MxExtI32_0>;
381
382defm MOV8e  : MMxMove_MM<MxType8,      MxType8.EOp,  MxType8.EPat,
383                         MxMoveSize8,  MxEncEAe_0,   MxExtEmpty>;
384defm MOV16e : MMxMove_MM<MxType16,     MxType16.EOp, MxType16.EPat,
385                         MxMoveSize16, MxEncEAe_0,   MxExtEmpty>;
386defm MOV32e : MMxMove_MM<MxType32,     MxType32.EOp, MxType32.EPat,
387                         MxMoveSize32, MxEncEAe_0,   MxExtEmpty>;
388
389defm MOV8o  : MMxMove_MM<MxType8,      MxType8.OOp,  MxType8.OPat,
390                         MxMoveSize8,  MxEncEAo_0,   MxExtEmpty>;
391defm MOV16o : MMxMove_MM<MxType16,     MxType16.OOp, MxType16.OPat,
392                         MxMoveSize16, MxEncEAo_0,   MxExtEmpty>;
393defm MOV32o : MMxMove_MM<MxType32,     MxType32.OOp, MxType32.OPat,
394                         MxMoveSize32, MxEncEAo_0,   MxExtEmpty>;
395
396defm MOV8j  : MMxMove_MM<MxType8,      MxType8.JOp,  MxType8.JPat,
397                         MxMoveSize8,  MxEncEAj_0,   MxExtEmpty>;
398defm MOV16j : MMxMove_MM<MxType16,     MxType16.JOp, MxType16.JPat,
399                         MxMoveSize16, MxEncEAj_0,   MxExtEmpty>;
400defm MOV32j : MMxMove_MM<MxType32,     MxType32.JOp, MxType32.JPat,
401                         MxMoveSize32, MxEncEAj_0,   MxExtEmpty>;
402
403//===----------------------------------------------------------------------===//
404// MOVEM
405//
406// The mask is already pre-processed by the save/restore spill hook
407//===----------------------------------------------------------------------===//
408
409// Direction
410def MxMOVEM_MR : MxBead1Bit<0>;
411def MxMOVEM_RM : MxBead1Bit<1>;
412
413// Size
414def MxMOVEM_W  : MxBead1Bit<0>;
415def MxMOVEM_L  : MxBead1Bit<1>;
416
417/// ---------------+-------------+-------------+---------
418///  F  E  D  C  B | A | 9  8  7 | 6 | 5  4  3 | 2  1  0
419/// ---------------+---+---------+---+---------+---------
420///  0  1  0  0  1 | D | 0  0  1 | S |   MODE  |   REG
421/// ---------------+---+---------+---+---------+---------
422///                  REGISTER LIST MASK
423/// -----------------------------------------------------
424/// D - direction(RM,MR)
425/// S - size(W,L)
426class MxMOVEMEncoding<MxEncEA EA, MxEncExt EXT, MxBead1Bit SIZE, MxBead1Bit DIR,
427                      MxBead16Imm IMM>
428    : MxEncoding<EA.Reg, EA.DA, EA.Mode, SIZE, MxBead3Bits<0b001>, DIR,
429                 MxBead1Bit<1>, MxBead4Bits<0b0100>, IMM,
430                 EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>;
431
432let mayStore = 1 in
433class MxMOVEM_MR<MxType TYPE, MxBead1Bit SIZE,
434                 MxOperand MEMOp, MxEncEA EA, MxEncExt EXT>
435    : MxInst<(outs), (ins MEMOp:$dst, MxMoveMask:$mask),
436             "movem."#TYPE.Prefix#"\t$mask, $dst", [],
437             MxMOVEMEncoding<EA, EXT, SIZE, MxMOVEM_MR, MxBead16Imm<1>>>;
438
439let mayLoad = 1 in
440class MxMOVEM_RM<MxType TYPE, MxBead1Bit SIZE,
441                 MxOperand MEMOp, MxEncEA EA, MxEncExt EXT>
442    : MxInst<(outs), (ins MxMoveMask:$mask, MEMOp:$src),
443             "movem."#TYPE.Prefix#"\t$src, $mask", [],
444             MxMOVEMEncoding<EA, EXT, SIZE, MxMOVEM_RM, MxBead16Imm<0>>>;
445
446def MOVM32jm : MxMOVEM_MR<MxType32, MxMOVEM_L, MxType32.JOp, MxEncEAj_0, MxExtEmpty>;
447def MOVM32pm : MxMOVEM_MR<MxType32, MxMOVEM_L, MxType32.POp, MxEncEAp_0, MxExtI16_0>;
448
449def MOVM32mj : MxMOVEM_RM<MxType32, MxMOVEM_L, MxType32.JOp, MxEncEAj_1, MxExtEmpty>;
450def MOVM32mp : MxMOVEM_RM<MxType32, MxMOVEM_L, MxType32.POp, MxEncEAp_1, MxExtI16_1>;
451
452// Pseudo versions. These a required by virtual register spill/restore since
453// the mask requires real register to encode. These instruction will be expanded
454// into real MOVEM after RA finishes.
455let mayStore = 1 in
456class MxMOVEM_MR_Pseudo<MxType TYPE, MxOperand MEMOp>
457    : MxPseudo<(outs), (ins MEMOp:$dst, TYPE.ROp:$reg)>;
458let mayLoad = 1 in
459class MxMOVEM_RM_Pseudo<MxType TYPE, MxOperand MEMOp>
460    : MxPseudo<(outs TYPE.ROp:$dst), (ins MEMOp:$src)>;
461
462// Mem <- Reg
463def MOVM8jm_P  : MxMOVEM_MR_Pseudo<MxType8d,  MxType8.JOp>;
464def MOVM16jm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.JOp>;
465def MOVM32jm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.JOp>;
466
467def MOVM8pm_P  : MxMOVEM_MR_Pseudo<MxType8d,  MxType8.POp>;
468def MOVM16pm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.POp>;
469def MOVM32pm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.POp>;
470
471// Reg <- Mem
472def MOVM8mj_P  : MxMOVEM_RM_Pseudo<MxType8d,  MxType8.JOp>;
473def MOVM16mj_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.JOp>;
474def MOVM32mj_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.JOp>;
475
476def MOVM8mp_P  : MxMOVEM_RM_Pseudo<MxType8d,  MxType8.POp>;
477def MOVM16mp_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.POp>;
478def MOVM32mp_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.POp>;
479
480
481//===----------------------------------------------------------------------===//
482// MOVE to/from SR/CCR
483//
484// A special care must be taken working with to/from CCR since it is basically
485// word-size SR register truncated for user mode thus it only supports word-size
486// instructions. Plus the original M68000 does not support moves from CCR. So in
487// order to use CCR effectively one MUST use proper byte-size pseudo instructi-
488// ons that will be resolved sometime after RA pass.
489//===----------------------------------------------------------------------===//
490
491/// --------------------------------------------------
492///  F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0
493/// --------------------------------------------------
494///                               | EFFECTIVE ADDRESS
495///  0  1  0  0  0  1  0  0  1  1 |   MODE  |   REG
496/// --------------------------------------------------
497let Defs = [CCR] in
498class MxMoveToCCR<dag INS, MxEncEA EA, MxEncExt EXT>
499    : MxInst<(outs CCRC:$dst), INS, "move.w\t$src, $dst", [],
500             MxEncoding<EA.Reg, EA.DA, EA.Mode,
501                        MxBead4Bits<0b0011>, MxBead4Bits<0b0001>, MxBead2Bits<0b01>,
502                        EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>;
503
504class MxMoveToCCRPseudo<dag INS> : MxPseudo<(outs CCRC:$dst), INS>;
505
506let mayLoad = 1 in {
507def MOV16cp : MxMoveToCCR<(ins MxType16d.POp:$src), MxEncEAp_1, MxExtI16_1>;
508def  MOV8cp : MxMoveToCCRPseudo<(ins MxType8d.POp:$src)>;
509} // let mayLoad = 1
510
511def MOV16cd : MxMoveToCCR<(ins MxType16d.ROp:$src), MxEncEAd_1, MxExtEmpty>;
512def  MOV8cd : MxMoveToCCRPseudo<(ins MxType8d.ROp:$src)>;
513
514/// Move from CCR
515/// --------------------------------------------------
516///  F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0
517/// --------------------------------------------------
518///                               | EFFECTIVE ADDRESS
519///  0  1  0  0  0  0  1  0  1  1 |   MODE  |   REG
520/// --------------------------------------------------
521let Uses = [CCR] in
522class MxMoveFromCCR<dag OUTS, dag INS, MxEncEA EA, MxEncExt EXT>
523    : MxInst<OUTS, INS, "move.w\t$src, $dst", [],
524             MxEncoding<EA.Reg, EA.DA, EA.Mode,
525                        MxBead4Bits<0b1011>, MxBead4Bits<0b0000>, MxBead2Bits<0b01>,
526                        EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>,
527      Requires<[ IsM68010 ]>;
528
529class MxMoveFromCCRPseudo<dag INS> : MxPseudo<(outs), INS>;
530
531let mayStore = 1 in {
532def MOV16pc
533  : MxMoveFromCCR<(outs), (ins MxType16d.POp:$dst, CCRC:$src), MxEncEAp_0, MxExtI16_0>;
534def MOV8pc : MxMoveFromCCRPseudo<(ins MxType8d.POp:$dst, CCRC:$src)>;
535} // let mayStore = 1
536
537def MOV16dc
538  : MxMoveFromCCR<(outs MxType16d.ROp:$dst), (ins CCRC:$src), MxEncEAd_0, MxExtEmpty>;
539
540def MOV8dc : MxMoveFromCCRPseudo<(ins MxType8d.ROp:$dst, CCRC:$src)>;
541
542
543//===----------------------------------------------------------------------===//
544// LEA
545//===----------------------------------------------------------------------===//
546
547/// ----------------------------------------------------
548///  F  E  D  C | B  A  9 | 8  7  6 | 5  4  3 | 2  1  0
549/// ----------------------------------------------------
550///  0  1  0  0 | DST REG | 1  1  1 |   MODE  |   REG
551/// ----------------------------------------------------
552class MxLEA<MxOperand SRCOpd, ComplexPattern SRCPat, MxEncEA EA, MxEncExt EXT>
553    : MxInst<(outs MxARD32:$dst), (ins SRCOpd:$src),
554             "lea\t$src, $dst", [(set i32:$dst, SRCPat:$src)],
555             MxEncoding<EA.Reg, EA.DA, EA.Mode,
556                        MxBead3Bits<0b111>, MxBeadReg<0>, MxBead4Bits<0x4>,
557                        EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>;
558
559def LEA32p : MxLEA<MxARID32, MxCP_ARID, MxEncEAp_1, MxExtI16_1>;
560def LEA32f : MxLEA<MxARII32, MxCP_ARII, MxEncEAf_1, MxExtBrief_1>;
561def LEA32q : MxLEA<MxPCD32,  MxCP_PCD,  MxEncEAq,   MxExtI16_1>;
562def LEA32b : MxLEA<MxAL32,   MxCP_AL,   MxEncEAb,   MxExtI32_1>;
563
564
565//===----------------------------------------------------------------------===//
566// Pseudos
567//===----------------------------------------------------------------------===//
568
569/// Pushe/Pop to/from SP for simplicity
570let Uses = [SP], Defs = [SP], hasSideEffects = 0 in {
571
572// SP <- SP - <size>; (SP) <- Dn
573let mayStore = 1 in {
574def PUSH8d  : MxPseudo<(outs), (ins DR8:$reg)>;
575def PUSH16d : MxPseudo<(outs), (ins DR16:$reg)>;
576def PUSH32r : MxPseudo<(outs), (ins XR32:$reg)>;
577} // let mayStore = 1
578
579// Dn <- (SP); SP <- SP + <size>
580let mayLoad = 1 in {
581def POP8d  : MxPseudo<(outs DR8:$reg),  (ins)>;
582def POP16d : MxPseudo<(outs DR16:$reg), (ins)>;
583def POP32r : MxPseudo<(outs XR32:$reg), (ins)>;
584} // let mayLoad = 1
585
586} // let Uses/Defs = [SP], hasSideEffects = 0
587
588
589let Defs = [CCR] in {
590class MxPseudoMove_RR<MxType DST, MxType SRC, list<dag> PAT = []>
591    : MxPseudo<(outs DST.ROp:$dst), (ins SRC.ROp:$src), PAT>;
592
593class MxPseudoMove_RM<MxType DST, MxOperand SRCOpd, list<dag> PAT = []>
594    : MxPseudo<(outs DST.ROp:$dst), (ins SRCOpd:$src), PAT>;
595}
596
597/// This group of Pseudos is analogues to the real x86 extending moves, but
598/// since M68k does not have those we need to emulate. These instructions
599/// will be expanded right after RA completed because we need to know precisely
600/// what registers are allocated for the operands and if they overlap we just
601/// extend the value if the registers are completely different we need to move
602/// first.
603foreach EXT = ["S", "Z"] in {
604  let hasSideEffects = 0 in {
605
606    def MOV#EXT#Xd16d8  : MxPseudoMove_RR<MxType16d,  MxType8d>;
607    def MOV#EXT#Xd32d8  : MxPseudoMove_RR<MxType32d,  MxType8d>;
608    def MOV#EXT#Xd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>;
609
610    let mayLoad = 1 in {
611
612      def MOV#EXT#Xd16j8   : MxPseudoMove_RM<MxType16d,  MxType8.JOp>;
613      def MOV#EXT#Xd32j8   : MxPseudoMove_RM<MxType32d,  MxType8.JOp>;
614      def MOV#EXT#Xd32j16  : MxPseudoMove_RM<MxType32d, MxType16.JOp>;
615
616      def MOV#EXT#Xd16p8   : MxPseudoMove_RM<MxType16d,  MxType8.POp>;
617      def MOV#EXT#Xd32p8   : MxPseudoMove_RM<MxType32d,  MxType8.POp>;
618      def MOV#EXT#Xd32p16  : MxPseudoMove_RM<MxType32d, MxType16.POp>;
619
620      def MOV#EXT#Xd16f8   : MxPseudoMove_RM<MxType16d,  MxType8.FOp>;
621      def MOV#EXT#Xd32f8   : MxPseudoMove_RM<MxType32d,  MxType8.FOp>;
622      def MOV#EXT#Xd32f16  : MxPseudoMove_RM<MxType32d, MxType16.FOp>;
623
624    }
625  }
626}
627
628/// This group of instructions is similar to the group above but DOES NOT do
629/// any value extension, they just load a smaller register into the lower part
630/// of another register if operands' real registers are different or does
631/// nothing if they are the same.
632def MOVXd16d8  : MxPseudoMove_RR<MxType16d,  MxType8d>;
633def MOVXd32d8  : MxPseudoMove_RR<MxType32d,  MxType8d>;
634def MOVXd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>;
635
636//===----------------------------------------------------------------------===//
637// Extend/Truncate Patterns
638//===----------------------------------------------------------------------===//
639
640// i16 <- sext i8
641def: Pat<(i16 (sext i8:$src)),
642          (EXTRACT_SUBREG (MOVSXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
643def: Pat<(MxSExtLoadi16i8 MxCP_ARI:$src),
644          (EXTRACT_SUBREG (MOVSXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
645def: Pat<(MxSExtLoadi16i8 MxCP_ARID:$src),
646          (EXTRACT_SUBREG (MOVSXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
647def: Pat<(MxSExtLoadi16i8 MxCP_ARII:$src),
648          (EXTRACT_SUBREG (MOVSXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
649
650// i32 <- sext i8
651def: Pat<(i32 (sext i8:$src)), (MOVSXd32d8 MxDRD8:$src)>;
652def: Pat<(MxSExtLoadi32i8 MxCP_ARI :$src), (MOVSXd32j8 MxARI8 :$src)>;
653def: Pat<(MxSExtLoadi32i8 MxCP_ARID:$src), (MOVSXd32p8 MxARID8:$src)>;
654def: Pat<(MxSExtLoadi32i8 MxCP_ARII:$src), (MOVSXd32f8 MxARII8:$src)>;
655
656// i32 <- sext i16
657def: Pat<(i32 (sext i16:$src)), (MOVSXd32d16 MxDRD16:$src)>;
658def: Pat<(MxSExtLoadi32i16 MxCP_ARI :$src), (MOVSXd32j16 MxARI16 :$src)>;
659def: Pat<(MxSExtLoadi32i16 MxCP_ARID:$src), (MOVSXd32p16 MxARID16:$src)>;
660def: Pat<(MxSExtLoadi32i16 MxCP_ARII:$src), (MOVSXd32f16 MxARII16:$src)>;
661
662// i16 <- zext i8
663def: Pat<(i16 (zext i8:$src)),
664          (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
665def: Pat<(MxZExtLoadi16i8 MxCP_ARI:$src),
666          (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
667def: Pat<(MxZExtLoadi16i8 MxCP_ARID:$src),
668          (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
669def: Pat<(MxZExtLoadi16i8 MxCP_ARII:$src),
670          (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
671
672// i32 <- zext i8
673def: Pat<(i32 (zext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>;
674def: Pat<(MxZExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>;
675def: Pat<(MxZExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>;
676def: Pat<(MxZExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>;
677
678// i32 <- zext i16
679def: Pat<(i32 (zext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>;
680def: Pat<(MxZExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>;
681def: Pat<(MxZExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>;
682def: Pat<(MxZExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>;
683
684// i16 <- anyext i8
685def: Pat<(i16 (anyext i8:$src)),
686          (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
687def: Pat<(MxExtLoadi16i8 MxCP_ARI:$src),
688          (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
689def: Pat<(MxExtLoadi16i8 MxCP_ARID:$src),
690          (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
691def: Pat<(MxExtLoadi16i8 MxCP_ARII:$src),
692          (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
693
694// i32 <- anyext i8
695def: Pat<(i32 (anyext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>;
696def: Pat<(MxExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>;
697def: Pat<(MxExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>;
698def: Pat<(MxExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>;
699
700// i32 <- anyext i16
701def: Pat<(i32 (anyext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>;
702def: Pat<(MxExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>;
703def: Pat<(MxExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>;
704def: Pat<(MxExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>;
705
706// trunc patterns
707def : Pat<(i16 (trunc i32:$src)),
708          (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex16Lo)>;
709def : Pat<(i8  (trunc i32:$src)),
710          (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex8Lo)>;
711def : Pat<(i8  (trunc i16:$src)),
712          (EXTRACT_SUBREG MxXRD16:$src, MxSubRegIndex8Lo)>;
713