Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / lib / Target / M68k / M68kInstrArithmetic.td
blob15d2049f62cb73e36c4c27e10e3a693ad5b3de4b
1 //===-- M68kInstrArithmetic.td - Integer Arith Instrs ------*- 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 integer arithmetic instructions in the M68k
11 /// architecture. Here is the current status of the file:
12 ///
13 ///  Machine:
14 ///
15 ///    ADD       [~]   ADDA      [~]   ADDI        [~]   ADDQ [ ]   ADDX [~]
16 ///    CLR       [ ]   CMP       [~]   CMPA        [~]   CMPI [~]   CMPM [ ]
17 ///    CMP2      [ ]   DIVS/DIVU [~]   DIVSL/DIVUL [ ]   EXT  [~]   EXTB [ ]
18 ///    MULS/MULU [~]   NEG       [~]   NEGX        [~]   SUB  [~]   SUBA [~]
19 ///    SUBI      [~]   SUBQ      [ ]   SUBX        [~]
20 ///
21 ///  Map:
22 ///
23 ///   [ ] - was not touched at all
24 ///   [!] - requires extarnal stuff implemented
25 ///   [~] - functional implementation
26 ///   [X] - complete implementation
27 ///
28 //===----------------------------------------------------------------------===//
30 //===----------------------------------------------------------------------===//
31 // OPMODE Encoding
32 //===----------------------------------------------------------------------===//
33 class MxOpModeEncoding<bits<3> encoding> {
34   bits<3> Value = encoding;
37 // op EA, Dn
38 def MxOpMode8_d_EA  : MxOpModeEncoding<0b000>;
39 def MxOpMode16_d_EA : MxOpModeEncoding<0b001>;
40 def MxOpMode32_d_EA : MxOpModeEncoding<0b010>;
42 // op Dn, EA
43 def MxOpMode8_EA_d  : MxOpModeEncoding<0b100>;
44 def MxOpMode16_EA_d : MxOpModeEncoding<0b101>;
45 def MxOpMode32_EA_d : MxOpModeEncoding<0b110>;
47 // op EA, An
48 def MxOpMode16_a_EA : MxOpModeEncoding<0b011>;
49 def MxOpMode32_a_EA : MxOpModeEncoding<0b111>;
52 //===----------------------------------------------------------------------===//
53 // Encoding
54 //===----------------------------------------------------------------------===//
56 let Defs = [CCR] in {
57 let Constraints = "$src = $dst" in {
59 /// Encoding for Normal forms
60 /// ----------------------------------------------------
61 ///  F  E  D  C | B  A  9 | 8  7  6 | 5  4  3 | 2  1  0
62 /// ----------------------------------------------------
63 ///             |         |         | EFFECTIVE ADDRESS
64 ///  x  x  x  x |   REG   | OP MODE |   MODE  |   REG
65 /// ----------------------------------------------------
67 // $reg, $ccr <- $reg op $reg
68 class MxBiArOp_R_RR_xEA<string MN, SDNode NODE, MxType DST_TYPE, MxType SRC_TYPE,
69                         bits<4> CMD>
70     : MxInst<(outs DST_TYPE.ROp:$dst), (ins DST_TYPE.ROp:$src, SRC_TYPE.ROp:$opd),
71              MN#"."#DST_TYPE.Prefix#"\t$opd, $dst",
72              [(set DST_TYPE.VT:$dst, CCR, (NODE DST_TYPE.VT:$src, SRC_TYPE.VT:$opd))]> {
73   let Inst = (descend
74     CMD, (operand "$dst", 3),
75     !cast<MxOpModeEncoding>("MxOpMode"#DST_TYPE.Size#"_"#DST_TYPE.RLet#"_EA").Value,
76     !cond(
77       !eq(SRC_TYPE.RLet, "r") : (descend 0b00, (operand "$opd", 4)),
78       !eq(SRC_TYPE.RLet, "d") : (descend 0b000, (operand "$opd", 3))
79     )
80   );
83 /// This Op is similar to the one above except it uses reversed opmode, some
84 /// commands(e.g. eor) do not support dEA or rEA modes and require EAd for
85 /// register only operations.
86 /// NOTE when using dd commands it is irrelevant which opmode to use(as it seems)
87 /// but some opcodes support address register and some do not which creates this
88 /// mess.
89 class MxBiArOp_R_RR_EAd<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
90     : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
91              MN#"."#TYPE.Prefix#"\t$opd, $dst",
92              [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd))]> {
93   let Inst = (descend
94     CMD, (operand "$opd", 3),
95     !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value,
96     /*Destination can only be a data register*/
97     /*MODE*/0b000,
98     /*REGISTER*/(operand "$dst", 3));
101 let mayLoad = 1 in
102 class MxBiArOp_R_RM<string MN, SDNode NODE, MxType TYPE, MxOperand OPD, ComplexPattern PAT,
103                     bits<4> CMD, MxEncMemOp SRC_ENC>
104     : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, OPD:$opd),
105              MN#"."#TYPE.Prefix#"\t$opd, $dst",
106              [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, (TYPE.Load PAT:$opd)))]> {
107   let Inst = (ascend
108     (descend CMD, (operand "$dst", 3),
109              !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value,
110              SRC_ENC.EA),
111     SRC_ENC.Supplement
112   );
115 /// Encoding for Immediate forms
116 /// ---------------------------------------------------
117 ///  F  E  D  C  B  A  9  8 | 7  6 | 5  4  3 | 2  1  0
118 /// ---------------------------------------------------
119 ///                         |      | EFFECTIVE ADDRESS
120 ///  x  x  x  x  x  x  x  x | SIZE |   MODE  |   REG
121 /// ---------------------------------------------------
122 ///     16-BIT WORD DATA    |     8-BIT BYTE DATA
123 /// ---------------------------------------------------
124 ///                 32-BIT LONG DATA
125 /// ---------------------------------------------------
126 /// NOTE It is used to store an immediate to memory, imm-to-reg are handled with
127 /// normal version
129 // $reg <- $reg op $imm
130 class MxBiArOp_R_RI_xEA<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
131     : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd),
132              MN#"."#TYPE.Prefix#"\t$opd, $dst",
133              [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> {
134   let Inst = (ascend
135     (descend CMD, (operand "$dst", 3),
136              !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value,
137              MxEncAddrMode_i<"opd", TYPE.Size>.EA),
138     MxEncAddrMode_i<"opd", TYPE.Size>.Supplement
139   );
142 // Again, there are two ways to write an immediate to Dn register either dEA
143 // opmode or using *I encoding, and again some instructions also support address
144 // registers some do not.
145 class MxBiArOp_R_RI<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
146     : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd),
147              MN#"i."#TYPE.Prefix#"\t$opd, $dst",
148              [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> {
149   let Inst = (ascend
150     (descend 0b0000, CMD,
151              !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
152              // The destination cannot be address register, so it's always
153              // the MODE for data register direct mode.
154              /*MODE*/0b000,
155              /*REGISTER*/(operand "$dst", 3)),
156     // Source (i.e. immediate value) encoding
157     MxEncAddrMode_i<"opd", TYPE.Size>.Supplement
158   );
160 } // Constraints
162 let mayLoad = 1, mayStore = 1 in {
164 // FIXME MxBiArOp_FMR/FMI cannot consume CCR from MxAdd/MxSub which leads for
165 // MxAdd to survive the match and subsequent mismatch.
166 class MxBiArOp_MR<string MN, MxType TYPE,
167                   MxOperand MEMOpd, bits<4> CMD, MxEncMemOp DST_ENC>
168     : MxInst<(outs), (ins MEMOpd:$dst, TYPE.ROp:$opd),
169              MN#"."#TYPE.Prefix#"\t$opd, $dst", []> {
170   let Inst = (ascend
171     (descend CMD, (operand "$opd", 3),
172              !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value,
173              DST_ENC.EA),
174     DST_ENC.Supplement
175   );
178 class MxBiArOp_MI<string MN, MxType TYPE,
179                   MxOperand MEMOpd, bits<4> CMD, MxEncMemOp DST_ENC>
180     : MxInst<(outs), (ins MEMOpd:$dst, TYPE.IOp:$opd),
181              MN#"."#TYPE.Prefix#"\t$opd, $dst", []> {
182   let Inst = (ascend
183     (descend 0b0000, CMD,
184              !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
185              DST_ENC.EA),
186     // Source (i.e. immediate value) encoding
187     MxEncAddrMode_i<"opd", TYPE.Size>.Supplement,
188     // Destination encoding
189     DST_ENC.Supplement
190   );
192 } // mayLoad, mayStore
193 } // Defs = [CCR]
195 multiclass MxBiArOp_DF<string MN, SDNode NODE, bit isComm,
196                        bits<4> CMD, bits<4> CMDI> {
198   foreach SZ = [8, 16, 32] in {
199     // op $mem, $reg
200     def NAME#SZ#"dk"  : MxBiArOp_R_RM<MN, NODE,
201                                       !cast<MxType>("MxType"#SZ#"d"),
202                                       !cast<MxType>("MxType"#SZ).KOp,
203                                       !cast<MxType>("MxType"#SZ).KPat,
204                                       CMD, MxEncAddrMode_k<"opd">>;
206     def NAME#SZ#"dq"  : MxBiArOp_R_RM<MN, NODE,
207                                       !cast<MxType>("MxType"#SZ#"d"),
208                                       !cast<MxType>("MxType"#SZ).QOp,
209                                       !cast<MxType>("MxType"#SZ).QPat,
210                                       CMD, MxEncAddrMode_q<"opd">>;
212     def NAME#SZ#"dp"  : MxBiArOp_R_RM<MN, NODE,
213                                       !cast<MxType>("MxType"#SZ#"d"),
214                                       !cast<MxType>("MxType"#SZ).POp,
215                                       !cast<MxType>("MxType"#SZ).PPat,
216                                       CMD, MxEncAddrMode_p<"opd">>;
218     def NAME#SZ#"df"  : MxBiArOp_R_RM<MN, NODE,
219                                       !cast<MxType>("MxType"#SZ#"d"),
220                                       !cast<MxType>("MxType"#SZ).FOp,
221                                       !cast<MxType>("MxType"#SZ).FPat,
222                                       CMD, MxEncAddrMode_f<"opd">>;
224     def NAME#SZ#"dj"  : MxBiArOp_R_RM<MN, NODE,
225                                       !cast<MxType>("MxType"#SZ#"d"),
226                                       !cast<MxType>("MxType"#SZ).JOp,
227                                       !cast<MxType>("MxType"#SZ).JPat,
228                                       CMD, MxEncAddrMode_j<"opd">>;
229     // op $imm, $reg
230     def NAME#SZ#"di"  : MxBiArOp_R_RI_xEA<MN, NODE,
231                                           !cast<MxType>("MxType"#SZ#"d"),
232                                           CMD>;
233     // op $reg, $mem
234     def NAME#SZ#"pd"  : MxBiArOp_MR<MN,
235                                     !cast<MxType>("MxType"#SZ#"d"),
236                                     !cast<MxType>("MxType"#SZ).POp,
237                                     CMD, MxEncAddrMode_p<"dst">>;
239     def NAME#SZ#"fd"  : MxBiArOp_MR<MN,
240                                     !cast<MxType>("MxType"#SZ#"d"),
241                                     !cast<MxType>("MxType"#SZ).FOp,
242                                     CMD, MxEncAddrMode_f<"dst">>;
244     def NAME#SZ#"jd"  : MxBiArOp_MR<MN,
245                                     !cast<MxType>("MxType"#SZ#"d"),
246                                     !cast<MxType>("MxType"#SZ).JOp,
247                                     CMD, MxEncAddrMode_j<"dst">>;
248     // op $imm, $mem
249     def NAME#SZ#"pi"  : MxBiArOp_MI<MN,
250                                     !cast<MxType>("MxType"#SZ),
251                                     !cast<MxType>("MxType"#SZ).POp,
252                                     CMDI, MxEncAddrMode_p<"dst">>;
254     def NAME#SZ#"fi"  : MxBiArOp_MI<MN,
255                                     !cast<MxType>("MxType"#SZ),
256                                     !cast<MxType>("MxType"#SZ).FOp,
257                                     CMDI, MxEncAddrMode_f<"dst">>;
259     def NAME#SZ#"ji"  : MxBiArOp_MI<MN,
260                                     !cast<MxType>("MxType"#SZ),
261                                     !cast<MxType>("MxType"#SZ).JOp,
262                                     CMDI, MxEncAddrMode_j<"dst">>;
263     // op $reg, $reg
264     let isCommutable = isComm in
265     def NAME#SZ#"dd" : MxBiArOp_R_RR_xEA<MN, NODE,
266                                          !cast<MxType>("MxType"#SZ#"d"),
267                                          !cast<MxType>("MxType"#SZ#"d"),
268                                          CMD>;
269   } // foreach SZ
271   foreach SZ = [16, 32] in
272   def NAME#SZ#"dr" : MxBiArOp_R_RR_xEA<MN, NODE,
273                                        !cast<MxType>("MxType"#SZ#"d"),
274                                        !cast<MxType>("MxType"#SZ#"r"),
275                                        CMD>;
277 } // MxBiArOp_DF
280 // These special snowflakes allowed to match address registers but since *A
281 // operations do not produce CCR we should not match them against Mx nodes that
282 // produce it.
283 let Pattern = [(null_frag)] in
284 multiclass MxBiArOp_AF<string MN, SDNode NODE, bits<4> CMD> {
286   def NAME#"32ak" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.KOp, MxType32.KPat,
287                                   CMD, MxEncAddrMode_k<"opd">>;
288   def NAME#"32aq" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.QOp, MxType32.QPat,
289                                   CMD, MxEncAddrMode_q<"opd">>;
290   def NAME#"32af" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.FOp, MxType32.FPat,
291                                   CMD, MxEncAddrMode_f<"opd">>;
292   def NAME#"32ap" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.POp, MxType32.PPat,
293                                   CMD, MxEncAddrMode_p<"opd">>;
294   def NAME#"32aj" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.JOp, MxType32.JPat,
295                                   CMD, MxEncAddrMode_j<"opd">>;
296   def NAME#"32ab" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.BOp, MxType32.BPat,
297                                   CMD, MxEncAddrMode_abs<"opd", true>>;
298   def NAME#"32ai" : MxBiArOp_R_RI_xEA<MN, NODE, MxType32a, CMD>;
300   def NAME#"32ar" : MxBiArOp_R_RR_xEA<MN, NODE, MxType32a, MxType32r, CMD>;
302 } // MxBiArOp_AF
304 // NOTE These naturally produce CCR
306 //===----------------------------------------------------------------------===//
307 // Add/Sub
308 //===----------------------------------------------------------------------===//
310 defm ADD : MxBiArOp_DF<"add",  MxAdd, 1, 0xD, 0x6>;
311 defm ADD : MxBiArOp_AF<"adda", MxAdd, 0xD>;
312 defm SUB : MxBiArOp_DF<"sub",  MxSub, 0, 0x9, 0x4>;
313 defm SUB : MxBiArOp_AF<"suba", MxSub, 0x9>;
315 // This pattern is used to enable the instruction selector to select ADD32ab
316 // for global values that are allocated in thread-local storage, i.e.:
317 //   t8: i32 = ISD::ADD GLOBAL_OFFSET_TABLE, TargetGlobalTLSAddress:i32<ptr @myvar>
318 //     ====>
319 //   t8: i32,i8 = ADD32ab GLOBAL_OFFSET_TABLE, TargetGlobalTLSAddress:i32<ptr @myvar>
320 def : Pat<(add MxARD32:$src, tglobaltlsaddr:$opd), (ADD32ab MxARD32:$src, MxAL32:$opd)>;
322 let Uses = [CCR], Defs = [CCR] in {
323 let Constraints = "$src = $dst" in {
325 /// Encoding for Extended forms
326 /// ------------------------------------------------------
327 ///  F  E  D  C | B  A  9 | 8 | 7  6 | 5  4 | 3 | 2  1  0
328 /// ------------------------------------------------------
329 ///  x  x  x  x |  REG Rx | 1 | SIZE | 0  0 | M |  REG Ry
330 /// ------------------------------------------------------
331 /// Rx - destination
332 /// Ry - source
333 /// M  - address mode switch
335 // $reg, ccr <- $reg op $reg op ccr
336 class MxBiArOp_R_RRX<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
337     : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
338              MN#"."#TYPE.Prefix#"\t$opd, $dst",
339              [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd, CCR))]> {
340   let Inst = (descend CMD,
341     // Destination register
342     (operand "$dst", 3),
343     0b1,
344     // SIZE
345     !cond(!eq(TYPE.Size, 8): 0b00,
346           !eq(TYPE.Size, 16): 0b01,
347           !eq(TYPE.Size, 32): 0b10),
348     0b00, /*R/M*/0b0,
349     // Source register
350     (operand "$opd", 3)
351   );
353 } // Constraints
354 } // Uses, Defs
356 multiclass MxBiArOp_RFF<string MN, SDNode NODE, bit isComm, bits<4> CMD> {
358 let isCommutable = isComm in {
359   foreach SZ = [8, 16, 32] in
360   def NAME#SZ#"dd"  : MxBiArOp_R_RRX<MN, NODE, !cast<MxType>("MxType"#SZ#"d"), CMD>;
361 } // isComm
363 } // MxBiArOp_RFF
365 // NOTE These consume and produce CCR
366 defm ADDX : MxBiArOp_RFF<"addx", MxAddX, 1, 0xD>;
367 defm SUBX : MxBiArOp_RFF<"subx", MxSubX, 0, 0x9>;
370 //===----------------------------------------------------------------------===//
371 // And/Xor/Or
372 //===----------------------------------------------------------------------===//
374 defm AND : MxBiArOp_DF<"and", MxAnd, 1, 0xC, 0x2>;
375 defm OR  : MxBiArOp_DF<"or",  MxOr,  1, 0x8, 0x0>;
377 multiclass MxBiArOp_DF_EAd<string MN, SDNode NODE, bits<4> CMD, bits<4> CMDI> {
378   foreach SZ = [8, 16, 32] in {
379     let isCommutable = 1 in
380     def NAME#SZ#"dd"  : MxBiArOp_R_RR_EAd<MN, NODE,
381                                           !cast<MxType>("MxType"#SZ#"d"),
382                                           CMD>;
384     def NAME#SZ#"di"  : MxBiArOp_R_RI<MN, NODE,
385                                       !cast<MxType>("MxType"#SZ#"d"),
386                                       CMDI>;
387   } // foreach SZ
388 } // MxBiArOp_DF_EAd
390 defm XOR : MxBiArOp_DF_EAd<"eor", MxXor, 0xB, 0xA>;
393 //===----------------------------------------------------------------------===//
394 // CMP
395 //===----------------------------------------------------------------------===//
397 let Defs = [CCR] in {
398 class MxCmp_RR<MxType LHS_TYPE, MxType RHS_TYPE = LHS_TYPE>
399     : MxInst<(outs), (ins LHS_TYPE.ROp:$lhs, RHS_TYPE.ROp:$rhs),
400              "cmp."#RHS_TYPE.Prefix#"\t$lhs, $rhs",
401              [(set CCR, (MxCmp LHS_TYPE.VT:$lhs, RHS_TYPE.VT:$rhs))]> {
402   let Inst = (descend 0b1011,
403     // REGISTER
404     (operand "$rhs", 3),
405     // OPMODE
406     !cast<MxOpModeEncoding>("MxOpMode"#RHS_TYPE.Size#"_"#RHS_TYPE.RLet#"_EA").Value,
407     // MODE without last bit
408     0b00,
409     // REGISTER prefixed by D/A bit
410     (operand "$lhs", 4)
411   );
414 class MxCmp_RI<MxType TYPE>
415     : MxInst<(outs), (ins TYPE.IOp:$imm, TYPE.ROp:$reg),
416              "cmpi."#TYPE.Prefix#"\t$imm, $reg",
417              [(set CCR, (MxCmp TYPE.IPat:$imm, TYPE.VT:$reg))]> {
418   let Inst = (ascend
419     (descend 0b00001100,
420              !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
421              // The destination cannot be address register, so it's always
422              // the MODE for data register direct mode.
423              /*MODE*/0b000,
424              /*REGISTER*/(operand "$reg", 3)),
425     // Source (i.e. immediate value) encoding
426     MxEncAddrMode_i<"imm", TYPE.Size>.Supplement
427   );
430 let mayLoad = 1 in {
432 class MxCmp_MI<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat,
433                MxEncMemOp MEM_ENC>
434     : MxInst<(outs), (ins TYPE.IOp:$imm, MEMOpd:$mem),
435              "cmpi."#TYPE.Prefix#"\t$imm, $mem",
436              [(set CCR, (MxCmp TYPE.IPat:$imm, (load MEMPat:$mem)))]> {
437   let Inst = (ascend
438     (descend 0b00001100,
439              !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
440              MEM_ENC.EA),
441     // Source (i.e. immediate value) encoding
442     MxEncAddrMode_i<"imm", TYPE.Size>.Supplement,
443     // Destination (i.e. memory operand) encoding
444     MEM_ENC.Supplement
445   );
448 // FIXME: What about abs.W?
449 class MxCmp_BI<MxType TYPE>
450     : MxInst<(outs), (ins TYPE.IOp:$imm, MxAL32:$abs),
451              "cmpi."#TYPE.Prefix#"\t$imm, $abs",
452              [(set CCR, (MxCmp TYPE.IPat:$imm,
453                                (load (i32 (MxWrapper tglobaladdr:$abs)))))]> {
454   defvar AbsEncoding = MxEncAddrMode_abs<"abs", true>;
455   let Inst = (ascend
456     (descend 0b00001100,
457              !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
458              AbsEncoding.EA),
459     // Source (i.e. immediate value) encoding
460     MxEncAddrMode_i<"imm", TYPE.Size>.Supplement,
461     // Destination (i.e. memory operand) encoding
462     AbsEncoding.Supplement
463   );
466 class MxCmp_RM<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat,
467                MxEncMemOp MEM_ENC>
468     : MxInst<(outs), (ins TYPE.ROp:$reg, MEMOpd:$mem),
469              "cmp."#TYPE.Prefix#"\t$mem, $reg",
470              [(set CCR, (MxCmp (load MEMPat:$mem), TYPE.ROp:$reg))]> {
471   let Inst = (ascend
472     (descend 0b1011,
473       // REGISTER
474       (operand "$reg", 3),
475       // OPMODE
476       !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_d_EA").Value,
477       MEM_ENC.EA),
478     MEM_ENC.Supplement
479   );
481 } // let mayLoad = 1
483 } // let Defs = [CCR]
485 multiclass MMxCmp_RM<MxType TYPE> {
486   def NAME#TYPE.KOp.Letter : MxCmp_RM<TYPE, TYPE.KOp, TYPE.KPat, MxEncAddrMode_k<"mem">>;
487   def NAME#TYPE.QOp.Letter : MxCmp_RM<TYPE, TYPE.QOp, TYPE.QPat, MxEncAddrMode_q<"mem">>;
488   def NAME#TYPE.POp.Letter : MxCmp_RM<TYPE, TYPE.POp, TYPE.PPat, MxEncAddrMode_p<"mem">>;
489   def NAME#TYPE.FOp.Letter : MxCmp_RM<TYPE, TYPE.FOp, TYPE.FPat, MxEncAddrMode_f<"mem">>;
490   def NAME#TYPE.JOp.Letter : MxCmp_RM<TYPE, TYPE.JOp, TYPE.JPat, MxEncAddrMode_j<"mem">>;
493 multiclass MMxCmp_MI<MxType TYPE> {
494   def NAME#TYPE.KOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.KOp, TYPE.KPat,
495                                           MxEncAddrMode_k<"mem">>;
496   def NAME#TYPE.QOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.QOp, TYPE.QPat,
497                                           MxEncAddrMode_q<"mem">>;
498   def NAME#TYPE.POp.Letter#"i" : MxCmp_MI<TYPE, TYPE.POp, TYPE.PPat,
499                                           MxEncAddrMode_p<"mem">>;
500   def NAME#TYPE.FOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.FOp, TYPE.FPat,
501                                           MxEncAddrMode_f<"mem">>;
502   def NAME#TYPE.JOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.JOp, TYPE.JPat,
503                                           MxEncAddrMode_j<"mem">>;
506 foreach S = [8, 16, 32] in {
507   def CMP#S#di : MxCmp_RI<!cast<MxType>("MxType"#S#"d")>;
508   def CMP#S#bi : MxCmp_BI<!cast<MxType>("MxType"#S#"d")>;
509 } // foreach
511 def CMP8dd : MxCmp_RR<MxType8d>;
512 foreach S = [16, 32] in {
513   def CMP#S#dr : MxCmp_RR<!cast<MxType>("MxType"#S#"r"),
514                           !cast<MxType>("MxType"#S#"d")>;
517 // cmp mem, Dn
518 defm CMP8d  : MMxCmp_RM<MxType8d>;
519 defm CMP16d : MMxCmp_RM<MxType16d>;
520 defm CMP32d : MMxCmp_RM<MxType32d>;
522 // cmp #imm, mem
523 defm CMP8  : MMxCmp_MI<MxType8d>;
524 defm CMP16 : MMxCmp_MI<MxType16d>;
525 defm CMP32 : MMxCmp_MI<MxType32d>;
528 //===----------------------------------------------------------------------===//
529 // EXT
530 //===----------------------------------------------------------------------===//
532 /// ---------------------------------------------------
533 ///  F  E  D  C  B  A  9 | 8  7  6 | 5  4  3 | 2  1  0
534 /// ---------------------------------------------------
535 ///  0  1  0  0  1  0  0 |  OPMODE | 0  0  0 |   REG
536 /// ---------------------------------------------------
537 let Defs = [CCR] in
538 let Constraints = "$src = $dst" in
539 class MxExt<MxType TO, MxType FROM>
540     : MxInst<(outs TO.ROp:$dst), (ins TO.ROp:$src),
541              "ext."#TO.Prefix#"\t$src", []> {
542   let Inst = (descend 0b0100100,
543     // OPMODE
544     !cond(
545       // byte -> word
546       !and(!eq(FROM.Size, 8), !eq(TO.Size, 16)): 0b010,
547       // word -> long
548       !and(!eq(FROM.Size, 16), !eq(TO.Size, 32)): 0b011,
549       // byte -> long
550       !and(!eq(FROM.Size, 8), !eq(TO.Size, 32)): 0b111
551     ),
552     0b000,
553     // REGISTER
554     (operand "$src", 3)
555   );
558 def EXT16 : MxExt<MxType16d, MxType8d>;
559 def EXT32 : MxExt<MxType32d, MxType16d>;
561 def : Pat<(sext_inreg i16:$src, i8),  (EXT16 $src)>;
562 def : Pat<(sext_inreg i32:$src, i16), (EXT32 $src)>;
563 def : Pat<(sext_inreg i32:$src, i8),
564           (EXT32 (MOVXd32d16 (EXT16 (EXTRACT_SUBREG $src, MxSubRegIndex16Lo))))>;
567 //===----------------------------------------------------------------------===//
568 // DIV/MUL
569 //===----------------------------------------------------------------------===//
571 /// Word operation:
572 /// ----------------------------------------------------
573 ///  F  E  D  C | B  A  9 | 8  7  6 | 5  4  3 | 2  1  0
574 /// ----------------------------------------------------
575 ///             |         |         | EFFECTIVE ADDRESS
576 ///  x  x  x  x |   REG   | OP MODE |   MODE  |   REG
577 /// ----------------------------------------------------
578 let Defs = [CCR] in {
579 let Constraints = "$src = $dst" in {
580 // $dreg <- $dreg op $dreg
581 class MxDiMuOp_DD<string MN, bits<4> CMD, bit SIGNED = false,
582                   MxOperand DST, MxOperand OPD>
583     : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> {
584   let Inst = (descend CMD,
585     // REGISTER
586     (operand "$dst", 3),
587     !if(SIGNED, 0b111, 0b011),
588     /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3)
589   );
592 // $dreg <- $dreg op $dreg
593 class MxDiMuOp_DD_Long<string MN, bits<10> CMD, bit SIGNED = false>
594     : MxInst<(outs MxDRD32:$dst), (ins MxDRD32:$src, MxDRD32:$opd), MN#"\t$opd, $dst", []> {
595   let Inst = (ascend
596     (descend CMD,
597       /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3)),
598     (descend 0b0,
599       // REGISTER
600       (operand "$dst", 3),
601       !if(SIGNED, 0b1, 0b0),
602       /*SIZE*/0b0, 0b0000000,
603       // Dr REGISTER
604       0b000)
605   );
608 // $reg <- $reg op $imm
609 class MxDiMuOp_DI<string MN, bits<4> CMD, bit SIGNED = false,
610                   MxOperand DST, MxOperand OPD>
611     : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> {
612   // FIXME: Support immediates with different widths.
613   defvar ImmEnc = MxEncAddrMode_i<"opd", 16>;
614   let Inst = (ascend
615     (descend CMD,
616       // REGISTER
617       (operand "$dst", 3),
618       !if(SIGNED, 0b111, 0b011), ImmEnc.EA),
619     ImmEnc.Supplement
620   );
622 } // let Constraints
623 } // Defs = [CCR]
625 multiclass MxDiMuOp<string MN, bits<4> CMD, bit isComm = 0> {
626   let isCommutable = isComm in {
627     def "S"#NAME#"d32d16" : MxDiMuOp_DD<MN#"s", CMD, /*SIGNED*/true, MxDRD32, MxDRD16>;
628     def "U"#NAME#"d32d16" : MxDiMuOp_DD<MN#"u", CMD, /*SIGNED*/false, MxDRD32, MxDRD16>;
629   }
631   def "S"#NAME#"d32i16" : MxDiMuOp_DI<MN#"s", CMD, /*SIGNED*/true, MxDRD32, Mxi16imm>;
632   def "U"#NAME#"d32i16" : MxDiMuOp_DI<MN#"u", CMD, /*SIGNED*/false, MxDRD32, Mxi16imm>;
635 defm DIV : MxDiMuOp<"div", 0x8>;
637 def SDIVd32d32 : MxDiMuOp_DD_Long<"divs.l", 0x131, /*SIGNED*/true>;
638 def UDIVd32d32 : MxDiMuOp_DD_Long<"divu.l", 0x131, /*SIGNED*/false>;
640 // This is used to cast immediates to 16-bits for operations which don't
641 // support smaller immediate sizes.
642 def as_i16imm : SDNodeXForm<imm, [{
643   return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16);
644 }]>;
646 // RR i8
647 def : Pat<(sdiv i8:$dst, i8:$opd),
648           (EXTRACT_SUBREG
649             (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)),
650              MxSubRegIndex8Lo)>;
652 def : Pat<(udiv i8:$dst, i8:$opd),
653           (EXTRACT_SUBREG
654             (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)),
655              MxSubRegIndex8Lo)>;
657 def : Pat<(srem i8:$dst, i8:$opd),
658           (EXTRACT_SUBREG
659             (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)), 8), 8),
660              MxSubRegIndex8Lo)>;
662 def : Pat<(urem i8:$dst, i8:$opd),
663           (EXTRACT_SUBREG
664             (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)), 8), 8),
665              MxSubRegIndex8Lo)>;
667 // RR i16
668 def : Pat<(sdiv i16:$dst, i16:$opd),
669           (EXTRACT_SUBREG
670             (SDIVd32d16 (MOVSXd32d16 $dst), $opd),
671              MxSubRegIndex16Lo)>;
673 def : Pat<(udiv i16:$dst, i16:$opd),
674           (EXTRACT_SUBREG
675             (UDIVd32d16 (MOVZXd32d16 $dst), $opd),
676              MxSubRegIndex16Lo)>;
678 def : Pat<(srem i16:$dst, i16:$opd),
679           (EXTRACT_SUBREG
680             (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d16 $dst), $opd), 8), 8),
681              MxSubRegIndex16Lo)>;
683 def : Pat<(urem i16:$dst, i16:$opd),
684           (EXTRACT_SUBREG
685             (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d16 $dst), $opd), 8), 8),
686              MxSubRegIndex16Lo)>;
689 // RR i32
690 def : Pat<(sdiv i32:$dst, i32:$opd), (SDIVd32d32 $dst, $opd)>;
692 def : Pat<(udiv i32:$dst, i32:$opd), (UDIVd32d32 $dst, $opd)>;
695 // RI i8
696 def : Pat<(sdiv i8:$dst, MximmSExt8:$opd),
697           (EXTRACT_SUBREG
698             (SDIVd32i16 (MOVSXd32d8 $dst), (as_i16imm $opd)),
699              MxSubRegIndex8Lo)>;
701 def : Pat<(udiv i8:$dst, MximmSExt8:$opd),
702           (EXTRACT_SUBREG
703             (UDIVd32i16 (MOVZXd32d8 $dst), (as_i16imm $opd)),
704              MxSubRegIndex8Lo)>;
706 def : Pat<(srem i8:$dst, MximmSExt8:$opd),
707           (EXTRACT_SUBREG
708             (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d8 $dst), (as_i16imm $opd)), 8), 8),
709              MxSubRegIndex8Lo)>;
711 def : Pat<(urem i8:$dst, MximmSExt8:$opd),
712           (EXTRACT_SUBREG
713             (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d8 $dst), (as_i16imm $opd)), 8), 8),
714              MxSubRegIndex8Lo)>;
716 // RI i16
717 def : Pat<(sdiv i16:$dst, MximmSExt16:$opd),
718           (EXTRACT_SUBREG
719             (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd),
720              MxSubRegIndex16Lo)>;
722 def : Pat<(udiv i16:$dst, MximmSExt16:$opd),
723           (EXTRACT_SUBREG
724             (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd),
725              MxSubRegIndex16Lo)>;
727 def : Pat<(srem i16:$dst, MximmSExt16:$opd),
728           (EXTRACT_SUBREG
729             (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd), 8), 8),
730              MxSubRegIndex16Lo)>;
732 def : Pat<(urem i16:$dst, MximmSExt16:$opd),
733           (EXTRACT_SUBREG
734             (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd), 8), 8),
735              MxSubRegIndex16Lo)>;
738 defm MUL : MxDiMuOp<"mul", 0xC, 1>;
740 def SMULd32d32 : MxDiMuOp_DD_Long<"muls.l", 0x130, /*SIGNED*/true>;
741 def UMULd32d32 : MxDiMuOp_DD_Long<"mulu.l", 0x130, /*SIGNED*/false>;
743 // RR
744 def : Pat<(mul i16:$dst, i16:$opd),
745           (EXTRACT_SUBREG
746             (SMULd32d16 (MOVXd32d16 $dst), $opd),
747              MxSubRegIndex16Lo)>;
749 def : Pat<(mulhs i16:$dst, i16:$opd),
750           (EXTRACT_SUBREG
751             (ASR32di (ASR32di (SMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8),
752              MxSubRegIndex16Lo)>;
754 def : Pat<(mulhu i16:$dst, i16:$opd),
755           (EXTRACT_SUBREG
756             (LSR32di (LSR32di (UMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8),
757              MxSubRegIndex16Lo)>;
759 def : Pat<(mul i32:$dst, i32:$opd), (SMULd32d32 $dst, $opd)>;
762 // RI
763 def : Pat<(mul i16:$dst, MximmSExt16:$opd),
764           (EXTRACT_SUBREG
765             (SMULd32i16 (MOVXd32d16 $dst), imm:$opd),
766              MxSubRegIndex16Lo)>;
768 def : Pat<(mulhs i16:$dst, MximmSExt16:$opd),
769           (EXTRACT_SUBREG
770             (ASR32di (ASR32di (SMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8),
771              MxSubRegIndex16Lo)>;
773 def : Pat<(mulhu i16:$dst, MximmSExt16:$opd),
774           (EXTRACT_SUBREG
775             (LSR32di (LSR32di (UMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8),
776              MxSubRegIndex16Lo)>;
779 //===----------------------------------------------------------------------===//
780 // NEG/NEGX
781 //===----------------------------------------------------------------------===//
783 /// ------------+------------+------+---------+---------
784 ///  F  E  D  C | B  A  9  8 | 7  6 | 5  4  3 | 2  1  0
785 /// ------------+------------+------+-------------------
786 ///             |            |      | EFFECTIVE ADDRESS
787 ///  0  1  0  0 | x  x  x  x | SIZE |   MODE  |   REG
788 /// ------------+------------+------+---------+---------
789 let Defs = [CCR] in {
790 let Constraints = "$src = $dst" in {
792 class MxNeg_D<MxType TYPE>
793     : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src),
794              "neg."#TYPE.Prefix#"\t$dst",
795              [(set TYPE.VT:$dst, (ineg TYPE.VT:$src))]> {
796   let Inst = (descend 0b01000100,
797     /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
798     //MODE without last bit
799     0b00,
800     //REGISTER prefixed by D/A bit
801     (operand "$dst", 4)
802   );
805 let Uses = [CCR] in {
806 class MxNegX_D<MxType TYPE>
807     : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src),
808              "negx."#TYPE.Prefix#"\t$dst",
809              [(set TYPE.VT:$dst, (MxSubX 0, TYPE.VT:$src, CCR))]> {
810   let Inst = (descend 0b01000000,
811     /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
812     //MODE without last bit
813     0b00,
814     //REGISTER prefixed by D/A bit
815     (operand "$dst", 4)
816   );
820 } // let Constraints
821 } // let Defs = [CCR]
823 foreach S = [8, 16, 32] in {
824   def NEG#S#d  : MxNeg_D<!cast<MxType>("MxType"#S#"d")>;
825   def NEGX#S#d : MxNegX_D<!cast<MxType>("MxType"#S#"d")>;
828 def : Pat<(MxSub 0, i8 :$src), (NEG8d  MxDRD8 :$src)>;
829 def : Pat<(MxSub 0, i16:$src), (NEG16d MxDRD16:$src)>;
830 def : Pat<(MxSub 0, i32:$src), (NEG32d MxDRD32:$src)>;
831 // SExt of i1 values.
832 // Although we specify `ZeroOrOneBooleanContent` for boolean content,
833 // we're still adding an AND here as we don't know the origin of the i1 value.
834 def : Pat<(sext_inreg i8:$src,  i1), (NEG8d  (AND8di  MxDRD8:$src,  1))>;
835 def : Pat<(sext_inreg i16:$src, i1), (NEG16d (AND16di MxDRD16:$src, 1))>;
836 def : Pat<(sext_inreg i32:$src, i1), (NEG32d (AND32di MxDRD32:$src, 1))>;
838 //===----------------------------------------------------------------------===//
839 // no-CCR Patterns
840 //===----------------------------------------------------------------------===//
842 /// Basically the reason for this stuff is that add and addc share the same
843 /// operand types constraints for whatever reasons and I had to define a common
844 /// MxAdd and MxSub instructions that produce CCR and then pattern-map add and addc
845 /// to it.
846 /// NOTE On the other hand I see no reason why I cannot just drop explicit CCR
847 /// result. Anyway works for now, hopefully I will better understand how this stuff
848 /// is designed later
849 foreach N = ["add", "addc"] in {
851   // add reg, reg
852   def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd),
853             (ADD8dd  MxDRD8 :$src, MxDRD8 :$opd)>;
854   def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd),
855             (ADD16dr MxXRD16:$src, MxDRD16:$opd)>;
856   def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd),
857             (ADD32dr MxXRD32:$src, MxDRD32:$opd)>;
859   // add (An), reg
860   def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)),
861             (ADD8dj MxDRD8:$src, MxType8.JOp:$opd)>;
862   def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)),
863             (ADD16dj MxDRD16:$src, MxType16.JOp:$opd)>;
864   def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)),
865             (ADD32dj MxDRD32:$src, MxType32.JOp:$opd)>;
867   // add (i,An), reg
868   def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)),
869             (ADD8dp MxDRD8:$src, MxType8.POp:$opd)>;
870   def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)),
871             (ADD16dp MxDRD16:$src, MxType16.POp:$opd)>;
872   def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)),
873             (ADD32dp MxDRD32:$src, MxType32.POp:$opd)>;
875   // add (i,An,Xn), reg
876   def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)),
877             (ADD8df MxDRD8:$src, MxType8.FOp:$opd)>;
878   def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)),
879             (ADD16df MxDRD16:$src, MxType16.FOp:$opd)>;
880   def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)),
881             (ADD32df MxDRD32:$src, MxType32.FOp:$opd)>;
883   // add reg, imm
884   def : Pat<(!cast<SDNode>(N) i8: $src, MximmSExt8:$opd),
885             (ADD8di  MxDRD8 :$src, imm:$opd)>;
886   def : Pat<(!cast<SDNode>(N) i16:$src, MximmSExt16:$opd),
887             (ADD16di MxDRD16:$src, imm:$opd)>;
889   // LEAp is more complex and thus will be selected over normal ADD32ri but it cannot
890   // be used with data registers, here by adding complexity to a simple ADD32ri insts
891   // we make sure it will be selected over LEAp
892   let AddedComplexity = 15 in {
893   def : Pat<(!cast<SDNode>(N) i32:$src, MximmSExt32:$opd),
894             (ADD32di MxDRD32:$src, imm:$opd)>;
895   } // AddedComplexity = 15
897   // add imm, (An)
898   def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd),
899                    MxType8.JPat:$dst),
900             (ADD8ji MxType8.JOp:$dst, imm:$opd)>;
901   def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd),
902                    MxType16.JPat:$dst),
903             (ADD16ji MxType16.JOp:$dst, imm:$opd)>;
904   def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd),
905                    MxType32.JPat:$dst),
906             (ADD32ji MxType32.JOp:$dst, imm:$opd)>;
908 } // foreach add, addc
910 def : Pat<(adde i8 :$src, i8 :$opd), (ADDX8dd  MxDRD8 :$src, MxDRD8 :$opd)>;
911 def : Pat<(adde i16:$src, i16:$opd), (ADDX16dd MxDRD16:$src, MxDRD16:$opd)>;
912 def : Pat<(adde i32:$src, i32:$opd), (ADDX32dd MxDRD32:$src, MxDRD32:$opd)>;
916 foreach N = ["sub", "subc"] in {
918   // sub reg, reg
919   def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd),
920             (SUB8dd  MxDRD8 :$src, MxDRD8 :$opd)>;
921   def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd),
922             (SUB16dd MxDRD16:$src, MxDRD16:$opd)>;
923   def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd),
924             (SUB32dd MxDRD32:$src, MxDRD32:$opd)>;
927   // sub (An), reg
928   def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)),
929             (SUB8dj MxDRD8:$src, MxType8.JOp:$opd)>;
930   def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)),
931             (SUB16dj MxDRD16:$src, MxType16.JOp:$opd)>;
932   def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)),
933             (SUB32dj MxDRD32:$src, MxType32.JOp:$opd)>;
935   // sub (i,An), reg
936   def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)),
937             (SUB8dp MxDRD8:$src, MxType8.POp:$opd)>;
938   def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)),
939             (SUB16dp MxDRD16:$src, MxType16.POp:$opd)>;
940   def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)),
941             (SUB32dp MxDRD32:$src, MxType32.POp:$opd)>;
943   // sub (i,An,Xn), reg
944   def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)),
945             (SUB8df MxDRD8:$src, MxType8.FOp:$opd)>;
946   def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)),
947             (SUB16df MxDRD16:$src, MxType16.FOp:$opd)>;
948   def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)),
949             (SUB32df MxDRD32:$src, MxType32.FOp:$opd)>;
951   // sub reg, imm
952   def : Pat<(!cast<SDNode>(N) i8 :$src, MximmSExt8 :$opd),
953             (SUB8di  MxDRD8 :$src, imm:$opd)>;
954   def : Pat<(!cast<SDNode>(N) i16:$src, MximmSExt16:$opd),
955             (SUB16di MxDRD16:$src, imm:$opd)>;
956   def : Pat<(!cast<SDNode>(N) i32:$src, MximmSExt32:$opd),
957             (SUB32di MxDRD32:$src, imm:$opd)>;
959   // sub imm, (An)
960   def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd),
961                    MxType8.JPat:$dst),
962             (SUB8ji MxType8.JOp:$dst, imm:$opd)>;
963   def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd),
964                    MxType16.JPat:$dst),
965             (SUB16ji MxType16.JOp:$dst, imm:$opd)>;
966   def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd),
967                    MxType32.JPat:$dst),
968             (SUB32ji MxType32.JOp:$dst, imm:$opd)>;
970 } // foreach sub, subx
972 def : Pat<(sube i8 :$src, i8 :$opd), (SUBX8dd  MxDRD8 :$src, MxDRD8 :$opd)>;
973 def : Pat<(sube i16:$src, i16:$opd), (SUBX16dd MxDRD16:$src, MxDRD16:$opd)>;
974 def : Pat<(sube i32:$src, i32:$opd), (SUBX32dd MxDRD32:$src, MxDRD32:$opd)>;
976 multiclass BitwisePat<string INST, SDNode OP> {
977   // op reg, reg
978   def : Pat<(OP i8 :$src, i8 :$opd),
979             (!cast<MxInst>(INST#"8dd")  MxDRD8 :$src, MxDRD8 :$opd)>;
980   def : Pat<(OP i16:$src, i16:$opd),
981             (!cast<MxInst>(INST#"16dd") MxDRD16:$src, MxDRD16:$opd)>;
982   def : Pat<(OP i32:$src, i32:$opd),
983             (!cast<MxInst>(INST#"32dd") MxDRD32:$src, MxDRD32:$opd)>;
984   // op reg, imm
985   def : Pat<(OP i8: $src, MximmSExt8 :$opd),
986             (!cast<MxInst>(INST#"8di")  MxDRD8 :$src, imm:$opd)>;
987   def : Pat<(OP i16:$src, MximmSExt16:$opd),
988             (!cast<MxInst>(INST#"16di") MxDRD16:$src, imm:$opd)>;
989   def : Pat<(OP i32:$src, MximmSExt32:$opd),
990             (!cast<MxInst>(INST#"32di") MxDRD32:$src, imm:$opd)>;
993 defm : BitwisePat<"AND", and>;
994 defm : BitwisePat<"OR",  or>;
995 defm : BitwisePat<"XOR", xor>;
997 //===----------------------------------------------------------------------===//
998 // Floating point arithmetic instruction
999 //===----------------------------------------------------------------------===//
1001 let Defs = [FPS] in
1002 class MxFArithBase_FF<dag outs, dag ins, string asm, string rounding,
1003                       list<dag> patterns>
1004     : MxInst<outs, ins, asm, patterns> {
1005   let Uses = !if(!eq(rounding, ""), [FPC], []);
1007   let Predicates = !if(!eq(rounding, ""), [AtLeastM68881], [AtLeastM68040]);
1010 class MxFPOpModeSelector<string rounding, bits<7> single, bits<7> double,
1011                          bits<7> extended> {
1012   bits<7> Mode = !cond(!eq(rounding, "s"): single,
1013                        !eq(rounding, "d"): double,
1014                        !eq(rounding, ""): extended);
1017 //===----------------------------------------------------------------------===//
1018 // Unary floating point instruction
1019 //===----------------------------------------------------------------------===//
1021 class MxFUnary_FF<MxOpBundle Opnd, string rounding,
1022                   string mnemonic, bits<7> opmode>
1023     : MxFArithBase_FF<(outs Opnd.Op:$dst), (ins Opnd.Op:$src),
1024                     "f"#rounding#mnemonic#".x\t$src, $dst", rounding, [(null_frag)]> {
1025   let Inst = (ascend
1026   (descend 0b1111,
1027     /*COPROCESSOR ID*/0b001,
1028     0b000,
1029     /*MODE+REGISTER*/0b000000),
1030   (descend 0b0, /* R/M */ 0b0, 0b0,
1031     /*SOURCE SPECIFIER*/
1032     (operand "$src", 3),
1033     /*DESTINATION*/
1034     (operand "$dst", 3),
1035     /*OPMODE*/
1036     opmode)
1037   );
1040 multiclass MxFUnaryOp<string mnemonic, bits<7> single, bits<7> double,
1041                       bits<7> extended> {
1042   foreach rounding = ["", "s", "d"] in {
1043     defvar opmode = MxFPOpModeSelector<rounding, single, double, extended>.Mode;
1045     def F # !toupper(rounding) # !substr(NAME, 1) # "80fp_fp"
1046       : MxFUnary_FF<MxOp80AddrMode_fpr, rounding, mnemonic, opmode>;
1047   
1048     let isCodeGenOnly = 1 in
1049     foreach size = [32, 64] in
1050       def F # !toupper(rounding) # !substr(NAME, 1) # size # "fp_fp"
1051         : MxFUnary_FF<!cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr"),
1052                       rounding, mnemonic, opmode>;
1053   }
1056 defm FABS : MxFUnaryOp<"abs", 0b1011000, 0b1011100, 0b0011000>;
1057 defm FNEG : MxFUnaryOp<"neg", 0b1011010, 0b1011110, 0b0011010>;
1059 //===----------------------------------------------------------------------===//
1060 // Binary floating point instruction
1061 //===----------------------------------------------------------------------===//
1063 let Constraints = "$src = $dst" in
1064 class MxFBinary_FF<MxOpBundle Opnd, string rounding,
1065                    string mnemonic, bits<7> opmode>
1066     : MxFArithBase_FF<(outs Opnd.Op:$dst), (ins Opnd.Op:$src, Opnd.Op:$opd),
1067                       "f"#rounding#mnemonic#".x\t$opd, $dst", rounding, [(null_frag)]> {
1068   let Inst = (ascend
1069   (descend 0b1111,
1070     /*COPROCESSOR ID*/0b001,
1071     0b000,
1072     /*MODE+REGISTER*/0b000000),
1073   (descend 0b0, /* R/M */ 0b0, 0b0,
1074     /*SOURCE SPECIFIER*/
1075     (operand "$opd", 3),
1076     /*DESTINATION*/
1077     (operand "$dst", 3),
1078     /*OPMODE*/
1079     opmode)
1080   );
1083 multiclass MxFBinaryOp<string mnemonic, bits<7> single, bits<7> double,
1084                       bits<7> extended> {
1085   foreach rounding = ["", "s", "d"] in {
1086     defvar opmode = MxFPOpModeSelector<rounding, single, double, extended>.Mode;
1088     def F # !toupper(rounding) # !substr(NAME, 1) # "80fp_fp"
1089       : MxFBinary_FF<MxOp80AddrMode_fpr, rounding, mnemonic, opmode>;
1091     let isCodeGenOnly = 1 in
1092     foreach size = [32, 64] in
1093       def F # !toupper(rounding) # !substr(NAME, 1) # size # "fp_fp"
1094         : MxFBinary_FF<!cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr"),
1095                         rounding, mnemonic, opmode>;
1096   }
1099 defm FADD : MxFBinaryOp<"add", 0b1100010, 0b1100110, 0b0100010>;
1100 defm FSUB : MxFBinaryOp<"sub", 0b1101000, 0b1101100, 0b0101000>;
1101 defm FMUL : MxFBinaryOp<"mul", 0b1100011, 0b1100111, 0b0100011>;
1102 defm FDIV : MxFBinaryOp<"div", 0b1100000, 0b1100100, 0b0100000>;