xref: /freebsd/contrib/llvm-project/llvm/lib/Target/M68k/M68kInstrArithmetic.td (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1fe6060f1SDimitry Andric//===-- M68kInstrArithmetic.td - Integer Arith Instrs ------*- tablegen -*-===//
2fe6060f1SDimitry Andric//
3fe6060f1SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric//
7fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric///
9fe6060f1SDimitry Andric/// \file
10fe6060f1SDimitry Andric/// This file describes the integer arithmetic instructions in the M68k
11fe6060f1SDimitry Andric/// architecture. Here is the current status of the file:
12fe6060f1SDimitry Andric///
13fe6060f1SDimitry Andric///  Machine:
14fe6060f1SDimitry Andric///
15fe6060f1SDimitry Andric///    ADD       [~]   ADDA      [~]   ADDI        [~]   ADDQ [ ]   ADDX [~]
16fe6060f1SDimitry Andric///    CLR       [ ]   CMP       [~]   CMPA        [~]   CMPI [~]   CMPM [ ]
17fe6060f1SDimitry Andric///    CMP2      [ ]   DIVS/DIVU [~]   DIVSL/DIVUL [ ]   EXT  [~]   EXTB [ ]
18*0fca6ea1SDimitry Andric///    MULS/MULU [~]   NEG       [~]   NEGX        [~]   NOT  [~]   SUB  [~]
19*0fca6ea1SDimitry Andric///    SUBA      [~]   SUBI      [~]   SUBQ        [ ]   SUBX [~]
20fe6060f1SDimitry Andric///
21fe6060f1SDimitry Andric///  Map:
22fe6060f1SDimitry Andric///
23fe6060f1SDimitry Andric///   [ ] - was not touched at all
24fe6060f1SDimitry Andric///   [!] - requires extarnal stuff implemented
25fe6060f1SDimitry Andric///   [~] - functional implementation
26fe6060f1SDimitry Andric///   [X] - complete implementation
27fe6060f1SDimitry Andric///
28fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
29fe6060f1SDimitry Andric
30fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
3181ad6265SDimitry Andric// OPMODE Encoding
3281ad6265SDimitry Andric//===----------------------------------------------------------------------===//
3381ad6265SDimitry Andricclass MxOpModeEncoding<bits<3> encoding> {
3481ad6265SDimitry Andric  bits<3> Value = encoding;
3581ad6265SDimitry Andric}
3681ad6265SDimitry Andric
3781ad6265SDimitry Andric// op EA, Dn
3881ad6265SDimitry Andricdef MxOpMode8_d_EA  : MxOpModeEncoding<0b000>;
3981ad6265SDimitry Andricdef MxOpMode16_d_EA : MxOpModeEncoding<0b001>;
4081ad6265SDimitry Andricdef MxOpMode32_d_EA : MxOpModeEncoding<0b010>;
4181ad6265SDimitry Andric
4281ad6265SDimitry Andric// op Dn, EA
4381ad6265SDimitry Andricdef MxOpMode8_EA_d  : MxOpModeEncoding<0b100>;
4481ad6265SDimitry Andricdef MxOpMode16_EA_d : MxOpModeEncoding<0b101>;
4581ad6265SDimitry Andricdef MxOpMode32_EA_d : MxOpModeEncoding<0b110>;
4681ad6265SDimitry Andric
4781ad6265SDimitry Andric// op EA, An
4881ad6265SDimitry Andricdef MxOpMode16_a_EA : MxOpModeEncoding<0b011>;
4981ad6265SDimitry Andricdef MxOpMode32_a_EA : MxOpModeEncoding<0b111>;
5081ad6265SDimitry Andric
5181ad6265SDimitry Andric
5281ad6265SDimitry Andric//===----------------------------------------------------------------------===//
53fe6060f1SDimitry Andric// Encoding
54fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
55fe6060f1SDimitry Andric
5681ad6265SDimitry Andriclet Defs = [CCR] in {
5781ad6265SDimitry Andriclet Constraints = "$src = $dst" in {
5881ad6265SDimitry Andric
59fe6060f1SDimitry Andric/// Encoding for Normal forms
60fe6060f1SDimitry Andric/// ----------------------------------------------------
61fe6060f1SDimitry Andric///  F  E  D  C | B  A  9 | 8  7  6 | 5  4  3 | 2  1  0
62fe6060f1SDimitry Andric/// ----------------------------------------------------
63fe6060f1SDimitry Andric///             |         |         | EFFECTIVE ADDRESS
64fe6060f1SDimitry Andric///  x  x  x  x |   REG   | OP MODE |   MODE  |   REG
65fe6060f1SDimitry Andric/// ----------------------------------------------------
66fe6060f1SDimitry Andric
6781ad6265SDimitry Andric// $reg, $ccr <- $reg op $reg
6881ad6265SDimitry Andricclass MxBiArOp_R_RR_xEA<string MN, SDNode NODE, MxType DST_TYPE, MxType SRC_TYPE,
6981ad6265SDimitry Andric                        bits<4> CMD>
7081ad6265SDimitry Andric    : MxInst<(outs DST_TYPE.ROp:$dst), (ins DST_TYPE.ROp:$src, SRC_TYPE.ROp:$opd),
7181ad6265SDimitry Andric             MN#"."#DST_TYPE.Prefix#"\t$opd, $dst",
7281ad6265SDimitry Andric             [(set DST_TYPE.VT:$dst, CCR, (NODE DST_TYPE.VT:$src, SRC_TYPE.VT:$opd))]> {
7381ad6265SDimitry Andric  let Inst = (descend
7481ad6265SDimitry Andric    CMD, (operand "$dst", 3),
7581ad6265SDimitry Andric    !cast<MxOpModeEncoding>("MxOpMode"#DST_TYPE.Size#"_"#DST_TYPE.RLet#"_EA").Value,
7681ad6265SDimitry Andric    !cond(
7781ad6265SDimitry Andric      !eq(SRC_TYPE.RLet, "r") : (descend 0b00, (operand "$opd", 4)),
7881ad6265SDimitry Andric      !eq(SRC_TYPE.RLet, "d") : (descend 0b000, (operand "$opd", 3))
7981ad6265SDimitry Andric    )
8081ad6265SDimitry Andric  );
8181ad6265SDimitry Andric}
8281ad6265SDimitry Andric
8381ad6265SDimitry Andric/// This Op is similar to the one above except it uses reversed opmode, some
8481ad6265SDimitry Andric/// commands(e.g. eor) do not support dEA or rEA modes and require EAd for
8581ad6265SDimitry Andric/// register only operations.
8681ad6265SDimitry Andric/// NOTE when using dd commands it is irrelevant which opmode to use(as it seems)
8781ad6265SDimitry Andric/// but some opcodes support address register and some do not which creates this
8881ad6265SDimitry Andric/// mess.
8981ad6265SDimitry Andricclass MxBiArOp_R_RR_EAd<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
9081ad6265SDimitry Andric    : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
9181ad6265SDimitry Andric             MN#"."#TYPE.Prefix#"\t$opd, $dst",
9281ad6265SDimitry Andric             [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd))]> {
9381ad6265SDimitry Andric  let Inst = (descend
9481ad6265SDimitry Andric    CMD, (operand "$opd", 3),
9581ad6265SDimitry Andric    !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value,
9681ad6265SDimitry Andric    /*Destination can only be a data register*/
9781ad6265SDimitry Andric    /*MODE*/0b000,
9881ad6265SDimitry Andric    /*REGISTER*/(operand "$dst", 3));
9981ad6265SDimitry Andric}
10081ad6265SDimitry Andric
10181ad6265SDimitry Andriclet mayLoad = 1 in
10281ad6265SDimitry Andricclass MxBiArOp_R_RM<string MN, SDNode NODE, MxType TYPE, MxOperand OPD, ComplexPattern PAT,
10381ad6265SDimitry Andric                    bits<4> CMD, MxEncMemOp SRC_ENC>
10481ad6265SDimitry Andric    : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, OPD:$opd),
10581ad6265SDimitry Andric             MN#"."#TYPE.Prefix#"\t$opd, $dst",
10681ad6265SDimitry Andric             [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, (TYPE.Load PAT:$opd)))]> {
10781ad6265SDimitry Andric  let Inst = (ascend
10881ad6265SDimitry Andric    (descend CMD, (operand "$dst", 3),
10981ad6265SDimitry Andric             !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value,
11081ad6265SDimitry Andric             SRC_ENC.EA),
11181ad6265SDimitry Andric    SRC_ENC.Supplement
11281ad6265SDimitry Andric  );
11381ad6265SDimitry Andric}
114fe6060f1SDimitry Andric
115fe6060f1SDimitry Andric/// Encoding for Immediate forms
116fe6060f1SDimitry Andric/// ---------------------------------------------------
117fe6060f1SDimitry Andric///  F  E  D  C  B  A  9  8 | 7  6 | 5  4  3 | 2  1  0
118fe6060f1SDimitry Andric/// ---------------------------------------------------
119fe6060f1SDimitry Andric///                         |      | EFFECTIVE ADDRESS
120fe6060f1SDimitry Andric///  x  x  x  x  x  x  x  x | SIZE |   MODE  |   REG
121fe6060f1SDimitry Andric/// ---------------------------------------------------
122fe6060f1SDimitry Andric///     16-BIT WORD DATA    |     8-BIT BYTE DATA
123fe6060f1SDimitry Andric/// ---------------------------------------------------
124fe6060f1SDimitry Andric///                 32-BIT LONG DATA
125fe6060f1SDimitry Andric/// ---------------------------------------------------
126fe6060f1SDimitry Andric/// NOTE It is used to store an immediate to memory, imm-to-reg are handled with
127fe6060f1SDimitry Andric/// normal version
128fe6060f1SDimitry Andric
129fe6060f1SDimitry Andric// $reg <- $reg op $imm
13081ad6265SDimitry Andricclass MxBiArOp_R_RI_xEA<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
131fe6060f1SDimitry Andric    : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd),
132fe6060f1SDimitry Andric             MN#"."#TYPE.Prefix#"\t$opd, $dst",
13381ad6265SDimitry Andric             [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> {
13481ad6265SDimitry Andric  let Inst = (ascend
13581ad6265SDimitry Andric    (descend CMD, (operand "$dst", 3),
13681ad6265SDimitry Andric             !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value,
13781ad6265SDimitry Andric             MxEncAddrMode_i<"opd", TYPE.Size>.EA),
13881ad6265SDimitry Andric    MxEncAddrMode_i<"opd", TYPE.Size>.Supplement
13981ad6265SDimitry Andric  );
14081ad6265SDimitry Andric}
141fe6060f1SDimitry Andric
142fe6060f1SDimitry Andric// Again, there are two ways to write an immediate to Dn register either dEA
14381ad6265SDimitry Andric// opmode or using *I encoding, and again some instructions also support address
144fe6060f1SDimitry Andric// registers some do not.
14581ad6265SDimitry Andricclass MxBiArOp_R_RI<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
146fe6060f1SDimitry Andric    : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd),
147fe6060f1SDimitry Andric             MN#"i."#TYPE.Prefix#"\t$opd, $dst",
14881ad6265SDimitry Andric             [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> {
14981ad6265SDimitry Andric  let Inst = (ascend
15081ad6265SDimitry Andric    (descend 0b0000, CMD,
15106c3fb27SDimitry Andric             !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
15281ad6265SDimitry Andric             // The destination cannot be address register, so it's always
15381ad6265SDimitry Andric             // the MODE for data register direct mode.
15481ad6265SDimitry Andric             /*MODE*/0b000,
15581ad6265SDimitry Andric             /*REGISTER*/(operand "$dst", 3)),
15681ad6265SDimitry Andric    // Source (i.e. immediate value) encoding
15781ad6265SDimitry Andric    MxEncAddrMode_i<"opd", TYPE.Size>.Supplement
15881ad6265SDimitry Andric  );
15981ad6265SDimitry Andric}
160fe6060f1SDimitry Andric} // Constraints
161fe6060f1SDimitry Andric
162fe6060f1SDimitry Andriclet mayLoad = 1, mayStore = 1 in {
163fe6060f1SDimitry Andric
164fe6060f1SDimitry Andric// FIXME MxBiArOp_FMR/FMI cannot consume CCR from MxAdd/MxSub which leads for
165fe6060f1SDimitry Andric// MxAdd to survive the match and subsequent mismatch.
16681ad6265SDimitry Andricclass MxBiArOp_MR<string MN, MxType TYPE,
16781ad6265SDimitry Andric                  MxOperand MEMOpd, bits<4> CMD, MxEncMemOp DST_ENC>
168fe6060f1SDimitry Andric    : MxInst<(outs), (ins MEMOpd:$dst, TYPE.ROp:$opd),
16981ad6265SDimitry Andric             MN#"."#TYPE.Prefix#"\t$opd, $dst", []> {
17081ad6265SDimitry Andric  let Inst = (ascend
17181ad6265SDimitry Andric    (descend CMD, (operand "$opd", 3),
17281ad6265SDimitry Andric             !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value,
17381ad6265SDimitry Andric             DST_ENC.EA),
17481ad6265SDimitry Andric    DST_ENC.Supplement
17581ad6265SDimitry Andric  );
17681ad6265SDimitry Andric}
177fe6060f1SDimitry Andric
17881ad6265SDimitry Andricclass MxBiArOp_MI<string MN, MxType TYPE,
17981ad6265SDimitry Andric                  MxOperand MEMOpd, bits<4> CMD, MxEncMemOp DST_ENC>
180fe6060f1SDimitry Andric    : MxInst<(outs), (ins MEMOpd:$dst, TYPE.IOp:$opd),
18181ad6265SDimitry Andric             MN#"."#TYPE.Prefix#"\t$opd, $dst", []> {
18281ad6265SDimitry Andric  let Inst = (ascend
18381ad6265SDimitry Andric    (descend 0b0000, CMD,
18406c3fb27SDimitry Andric             !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
18581ad6265SDimitry Andric             DST_ENC.EA),
18681ad6265SDimitry Andric    // Source (i.e. immediate value) encoding
18781ad6265SDimitry Andric    MxEncAddrMode_i<"opd", TYPE.Size>.Supplement,
18881ad6265SDimitry Andric    // Destination encoding
18981ad6265SDimitry Andric    DST_ENC.Supplement
19081ad6265SDimitry Andric  );
19181ad6265SDimitry Andric}
192fe6060f1SDimitry Andric} // mayLoad, mayStore
193fe6060f1SDimitry Andric} // Defs = [CCR]
194fe6060f1SDimitry Andric
195fe6060f1SDimitry Andricmulticlass MxBiArOp_DF<string MN, SDNode NODE, bit isComm,
196fe6060f1SDimitry Andric                       bits<4> CMD, bits<4> CMDI> {
197fe6060f1SDimitry Andric
19881ad6265SDimitry Andric  foreach SZ = [8, 16, 32] in {
199fe6060f1SDimitry Andric    // op $mem, $reg
20081ad6265SDimitry Andric    def NAME#SZ#"dk"  : MxBiArOp_R_RM<MN, NODE,
20181ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ#"d"),
20281ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ).KOp,
20381ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ).KPat,
20481ad6265SDimitry Andric                                      CMD, MxEncAddrMode_k<"opd">>;
205fe6060f1SDimitry Andric
20681ad6265SDimitry Andric    def NAME#SZ#"dq"  : MxBiArOp_R_RM<MN, NODE,
20781ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ#"d"),
20881ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ).QOp,
20981ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ).QPat,
21081ad6265SDimitry Andric                                      CMD, MxEncAddrMode_q<"opd">>;
211fe6060f1SDimitry Andric
21281ad6265SDimitry Andric    def NAME#SZ#"dp"  : MxBiArOp_R_RM<MN, NODE,
21381ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ#"d"),
21481ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ).POp,
21581ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ).PPat,
21681ad6265SDimitry Andric                                      CMD, MxEncAddrMode_p<"opd">>;
217fe6060f1SDimitry Andric
21881ad6265SDimitry Andric    def NAME#SZ#"df"  : MxBiArOp_R_RM<MN, NODE,
21981ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ#"d"),
22081ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ).FOp,
22181ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ).FPat,
22281ad6265SDimitry Andric                                      CMD, MxEncAddrMode_f<"opd">>;
223fe6060f1SDimitry Andric
22481ad6265SDimitry Andric    def NAME#SZ#"dj"  : MxBiArOp_R_RM<MN, NODE,
22581ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ#"d"),
22681ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ).JOp,
22781ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ).JPat,
22881ad6265SDimitry Andric                                      CMD, MxEncAddrMode_j<"opd">>;
229fe6060f1SDimitry Andric    // op $imm, $reg
23081ad6265SDimitry Andric    def NAME#SZ#"di"  : MxBiArOp_R_RI_xEA<MN, NODE,
23181ad6265SDimitry Andric                                          !cast<MxType>("MxType"#SZ#"d"),
23281ad6265SDimitry Andric                                          CMD>;
233fe6060f1SDimitry Andric    // op $reg, $mem
23481ad6265SDimitry Andric    def NAME#SZ#"pd"  : MxBiArOp_MR<MN,
23581ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ#"d"),
23681ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ).POp,
23781ad6265SDimitry Andric                                    CMD, MxEncAddrMode_p<"dst">>;
238fe6060f1SDimitry Andric
23981ad6265SDimitry Andric    def NAME#SZ#"fd"  : MxBiArOp_MR<MN,
24081ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ#"d"),
24181ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ).FOp,
24281ad6265SDimitry Andric                                    CMD, MxEncAddrMode_f<"dst">>;
243fe6060f1SDimitry Andric
24481ad6265SDimitry Andric    def NAME#SZ#"jd"  : MxBiArOp_MR<MN,
24581ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ#"d"),
24681ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ).JOp,
24781ad6265SDimitry Andric                                    CMD, MxEncAddrMode_j<"dst">>;
248fe6060f1SDimitry Andric    // op $imm, $mem
24981ad6265SDimitry Andric    def NAME#SZ#"pi"  : MxBiArOp_MI<MN,
25081ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ),
25181ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ).POp,
25281ad6265SDimitry Andric                                    CMDI, MxEncAddrMode_p<"dst">>;
253fe6060f1SDimitry Andric
25481ad6265SDimitry Andric    def NAME#SZ#"fi"  : MxBiArOp_MI<MN,
25581ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ),
25681ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ).FOp,
25781ad6265SDimitry Andric                                    CMDI, MxEncAddrMode_f<"dst">>;
258fe6060f1SDimitry Andric
25981ad6265SDimitry Andric    def NAME#SZ#"ji"  : MxBiArOp_MI<MN,
26081ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ),
26181ad6265SDimitry Andric                                    !cast<MxType>("MxType"#SZ).JOp,
26281ad6265SDimitry Andric                                    CMDI, MxEncAddrMode_j<"dst">>;
26381ad6265SDimitry Andric    // op $reg, $reg
26481ad6265SDimitry Andric    let isCommutable = isComm in
26581ad6265SDimitry Andric    def NAME#SZ#"dd" : MxBiArOp_R_RR_xEA<MN, NODE,
26681ad6265SDimitry Andric                                         !cast<MxType>("MxType"#SZ#"d"),
26781ad6265SDimitry Andric                                         !cast<MxType>("MxType"#SZ#"d"),
26881ad6265SDimitry Andric                                         CMD>;
26981ad6265SDimitry Andric  } // foreach SZ
270fe6060f1SDimitry Andric
27181ad6265SDimitry Andric  foreach SZ = [16, 32] in
27281ad6265SDimitry Andric  def NAME#SZ#"dr" : MxBiArOp_R_RR_xEA<MN, NODE,
27381ad6265SDimitry Andric                                       !cast<MxType>("MxType"#SZ#"d"),
27481ad6265SDimitry Andric                                       !cast<MxType>("MxType"#SZ#"r"),
27581ad6265SDimitry Andric                                       CMD>;
276fe6060f1SDimitry Andric
277fe6060f1SDimitry Andric} // MxBiArOp_DF
278fe6060f1SDimitry Andric
279fe6060f1SDimitry Andric
280fe6060f1SDimitry Andric// These special snowflakes allowed to match address registers but since *A
281fe6060f1SDimitry Andric// operations do not produce CCR we should not match them against Mx nodes that
282fe6060f1SDimitry Andric// produce it.
283fe6060f1SDimitry Andriclet Pattern = [(null_frag)] in
28404eeddc0SDimitry Andricmulticlass MxBiArOp_AF<string MN, SDNode NODE, bits<4> CMD> {
285fe6060f1SDimitry Andric
28681ad6265SDimitry Andric  def NAME#"32ak" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.KOp, MxType32.KPat,
28781ad6265SDimitry Andric                                  CMD, MxEncAddrMode_k<"opd">>;
28881ad6265SDimitry Andric  def NAME#"32aq" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.QOp, MxType32.QPat,
28981ad6265SDimitry Andric                                  CMD, MxEncAddrMode_q<"opd">>;
29081ad6265SDimitry Andric  def NAME#"32af" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.FOp, MxType32.FPat,
29181ad6265SDimitry Andric                                  CMD, MxEncAddrMode_f<"opd">>;
29281ad6265SDimitry Andric  def NAME#"32ap" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.POp, MxType32.PPat,
29381ad6265SDimitry Andric                                  CMD, MxEncAddrMode_p<"opd">>;
29481ad6265SDimitry Andric  def NAME#"32aj" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.JOp, MxType32.JPat,
29581ad6265SDimitry Andric                                  CMD, MxEncAddrMode_j<"opd">>;
29606c3fb27SDimitry Andric  def NAME#"32ab" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.BOp, MxType32.BPat,
29706c3fb27SDimitry Andric                                  CMD, MxEncAddrMode_abs<"opd", true>>;
29881ad6265SDimitry Andric  def NAME#"32ai" : MxBiArOp_R_RI_xEA<MN, NODE, MxType32a, CMD>;
299fe6060f1SDimitry Andric
30081ad6265SDimitry Andric  def NAME#"32ar" : MxBiArOp_R_RR_xEA<MN, NODE, MxType32a, MxType32r, CMD>;
301fe6060f1SDimitry Andric
302fe6060f1SDimitry Andric} // MxBiArOp_AF
303fe6060f1SDimitry Andric
304fe6060f1SDimitry Andric// NOTE These naturally produce CCR
305fe6060f1SDimitry Andric
30681ad6265SDimitry Andric//===----------------------------------------------------------------------===//
30781ad6265SDimitry Andric// Add/Sub
30881ad6265SDimitry Andric//===----------------------------------------------------------------------===//
30981ad6265SDimitry Andric
310fe6060f1SDimitry Andricdefm ADD : MxBiArOp_DF<"add",  MxAdd, 1, 0xD, 0x6>;
31104eeddc0SDimitry Andricdefm ADD : MxBiArOp_AF<"adda", MxAdd, 0xD>;
312fe6060f1SDimitry Andricdefm SUB : MxBiArOp_DF<"sub",  MxSub, 0, 0x9, 0x4>;
31304eeddc0SDimitry Andricdefm SUB : MxBiArOp_AF<"suba", MxSub, 0x9>;
314fe6060f1SDimitry Andric
31506c3fb27SDimitry Andric// This pattern is used to enable the instruction selector to select ADD32ab
31606c3fb27SDimitry Andric// for global values that are allocated in thread-local storage, i.e.:
31706c3fb27SDimitry Andric//   t8: i32 = ISD::ADD GLOBAL_OFFSET_TABLE, TargetGlobalTLSAddress:i32<ptr @myvar>
31806c3fb27SDimitry Andric//     ====>
31906c3fb27SDimitry Andric//   t8: i32,i8 = ADD32ab GLOBAL_OFFSET_TABLE, TargetGlobalTLSAddress:i32<ptr @myvar>
32006c3fb27SDimitry Andricdef : Pat<(add MxARD32:$src, tglobaltlsaddr:$opd), (ADD32ab MxARD32:$src, MxAL32:$opd)>;
321fe6060f1SDimitry Andric
322fe6060f1SDimitry Andriclet Uses = [CCR], Defs = [CCR] in {
323fe6060f1SDimitry Andriclet Constraints = "$src = $dst" in {
324fe6060f1SDimitry Andric
32581ad6265SDimitry Andric/// Encoding for Extended forms
32681ad6265SDimitry Andric/// ------------------------------------------------------
32781ad6265SDimitry Andric///  F  E  D  C | B  A  9 | 8 | 7  6 | 5  4 | 3 | 2  1  0
32881ad6265SDimitry Andric/// ------------------------------------------------------
32981ad6265SDimitry Andric///  x  x  x  x |  REG Rx | 1 | SIZE | 0  0 | M |  REG Ry
33081ad6265SDimitry Andric/// ------------------------------------------------------
33181ad6265SDimitry Andric/// Rx - destination
33281ad6265SDimitry Andric/// Ry - source
33381ad6265SDimitry Andric/// M  - address mode switch
33481ad6265SDimitry Andric
335fe6060f1SDimitry Andric// $reg, ccr <- $reg op $reg op ccr
33681ad6265SDimitry Andricclass MxBiArOp_R_RRX<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
337fe6060f1SDimitry Andric    : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
338fe6060f1SDimitry Andric             MN#"."#TYPE.Prefix#"\t$opd, $dst",
33981ad6265SDimitry Andric             [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd, CCR))]> {
34081ad6265SDimitry Andric  let Inst = (descend CMD,
34181ad6265SDimitry Andric    // Destination register
34281ad6265SDimitry Andric    (operand "$dst", 3),
34381ad6265SDimitry Andric    0b1,
34481ad6265SDimitry Andric    // SIZE
34581ad6265SDimitry Andric    !cond(!eq(TYPE.Size, 8): 0b00,
34681ad6265SDimitry Andric          !eq(TYPE.Size, 16): 0b01,
34781ad6265SDimitry Andric          !eq(TYPE.Size, 32): 0b10),
34881ad6265SDimitry Andric    0b00, /*R/M*/0b0,
34981ad6265SDimitry Andric    // Source register
35081ad6265SDimitry Andric    (operand "$opd", 3)
35181ad6265SDimitry Andric  );
35281ad6265SDimitry Andric}
353fe6060f1SDimitry Andric} // Constraints
354fe6060f1SDimitry Andric} // Uses, Defs
355fe6060f1SDimitry Andric
356fe6060f1SDimitry Andricmulticlass MxBiArOp_RFF<string MN, SDNode NODE, bit isComm, bits<4> CMD> {
357fe6060f1SDimitry Andric
358fe6060f1SDimitry Andriclet isCommutable = isComm in {
35981ad6265SDimitry Andric  foreach SZ = [8, 16, 32] in
36081ad6265SDimitry Andric  def NAME#SZ#"dd"  : MxBiArOp_R_RRX<MN, NODE, !cast<MxType>("MxType"#SZ#"d"), CMD>;
361fe6060f1SDimitry Andric} // isComm
362fe6060f1SDimitry Andric
363fe6060f1SDimitry Andric} // MxBiArOp_RFF
364fe6060f1SDimitry Andric
365fe6060f1SDimitry Andric// NOTE These consume and produce CCR
366fe6060f1SDimitry Andricdefm ADDX : MxBiArOp_RFF<"addx", MxAddX, 1, 0xD>;
367fe6060f1SDimitry Andricdefm SUBX : MxBiArOp_RFF<"subx", MxSubX, 0, 0x9>;
368fe6060f1SDimitry Andric
369fe6060f1SDimitry Andric
370fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
371fe6060f1SDimitry Andric// And/Xor/Or
372fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
373fe6060f1SDimitry Andric
374fe6060f1SDimitry Andricdefm AND : MxBiArOp_DF<"and", MxAnd, 1, 0xC, 0x2>;
375fe6060f1SDimitry Andricdefm OR  : MxBiArOp_DF<"or",  MxOr,  1, 0x8, 0x0>;
376fe6060f1SDimitry Andric
377fe6060f1SDimitry Andricmulticlass MxBiArOp_DF_EAd<string MN, SDNode NODE, bits<4> CMD, bits<4> CMDI> {
37881ad6265SDimitry Andric  foreach SZ = [8, 16, 32] in {
37981ad6265SDimitry Andric    let isCommutable = 1 in
38081ad6265SDimitry Andric    def NAME#SZ#"dd"  : MxBiArOp_R_RR_EAd<MN, NODE,
38181ad6265SDimitry Andric                                          !cast<MxType>("MxType"#SZ#"d"),
38281ad6265SDimitry Andric                                          CMD>;
383fe6060f1SDimitry Andric
38481ad6265SDimitry Andric    def NAME#SZ#"di"  : MxBiArOp_R_RI<MN, NODE,
38581ad6265SDimitry Andric                                      !cast<MxType>("MxType"#SZ#"d"),
38681ad6265SDimitry Andric                                      CMDI>;
38781ad6265SDimitry Andric  } // foreach SZ
388fe6060f1SDimitry Andric} // MxBiArOp_DF_EAd
389fe6060f1SDimitry Andric
390fe6060f1SDimitry Andricdefm XOR : MxBiArOp_DF_EAd<"eor", MxXor, 0xB, 0xA>;
391fe6060f1SDimitry Andric
392fe6060f1SDimitry Andric
393fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
394fe6060f1SDimitry Andric// CMP
395fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
396fe6060f1SDimitry Andric
397fe6060f1SDimitry Andriclet Defs = [CCR] in {
39881ad6265SDimitry Andricclass MxCmp_RR<MxType LHS_TYPE, MxType RHS_TYPE = LHS_TYPE>
399349cc55cSDimitry Andric    : MxInst<(outs), (ins LHS_TYPE.ROp:$lhs, RHS_TYPE.ROp:$rhs),
400349cc55cSDimitry Andric             "cmp."#RHS_TYPE.Prefix#"\t$lhs, $rhs",
40181ad6265SDimitry Andric             [(set CCR, (MxCmp LHS_TYPE.VT:$lhs, RHS_TYPE.VT:$rhs))]> {
40281ad6265SDimitry Andric  let Inst = (descend 0b1011,
40381ad6265SDimitry Andric    // REGISTER
40481ad6265SDimitry Andric    (operand "$rhs", 3),
40581ad6265SDimitry Andric    // OPMODE
40681ad6265SDimitry Andric    !cast<MxOpModeEncoding>("MxOpMode"#RHS_TYPE.Size#"_"#RHS_TYPE.RLet#"_EA").Value,
40781ad6265SDimitry Andric    // MODE without last bit
40881ad6265SDimitry Andric    0b00,
40981ad6265SDimitry Andric    // REGISTER prefixed by D/A bit
41081ad6265SDimitry Andric    (operand "$lhs", 4)
41181ad6265SDimitry Andric  );
41281ad6265SDimitry Andric}
413fe6060f1SDimitry Andric
414fe6060f1SDimitry Andricclass MxCmp_RI<MxType TYPE>
415fe6060f1SDimitry Andric    : MxInst<(outs), (ins TYPE.IOp:$imm, TYPE.ROp:$reg),
416fe6060f1SDimitry Andric             "cmpi."#TYPE.Prefix#"\t$imm, $reg",
41781ad6265SDimitry Andric             [(set CCR, (MxCmp TYPE.IPat:$imm, TYPE.VT:$reg))]> {
41881ad6265SDimitry Andric  let Inst = (ascend
41981ad6265SDimitry Andric    (descend 0b00001100,
42006c3fb27SDimitry Andric             !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
42181ad6265SDimitry Andric             // The destination cannot be address register, so it's always
42281ad6265SDimitry Andric             // the MODE for data register direct mode.
42381ad6265SDimitry Andric             /*MODE*/0b000,
42481ad6265SDimitry Andric             /*REGISTER*/(operand "$reg", 3)),
42581ad6265SDimitry Andric    // Source (i.e. immediate value) encoding
42681ad6265SDimitry Andric    MxEncAddrMode_i<"imm", TYPE.Size>.Supplement
42781ad6265SDimitry Andric  );
42881ad6265SDimitry Andric}
429fe6060f1SDimitry Andric
430fe6060f1SDimitry Andriclet mayLoad = 1 in {
431fe6060f1SDimitry Andric
432fe6060f1SDimitry Andricclass MxCmp_MI<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat,
43381ad6265SDimitry Andric               MxEncMemOp MEM_ENC>
434fe6060f1SDimitry Andric    : MxInst<(outs), (ins TYPE.IOp:$imm, MEMOpd:$mem),
435fe6060f1SDimitry Andric             "cmpi."#TYPE.Prefix#"\t$imm, $mem",
43681ad6265SDimitry Andric             [(set CCR, (MxCmp TYPE.IPat:$imm, (load MEMPat:$mem)))]> {
43781ad6265SDimitry Andric  let Inst = (ascend
43881ad6265SDimitry Andric    (descend 0b00001100,
43906c3fb27SDimitry Andric             !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
44081ad6265SDimitry Andric             MEM_ENC.EA),
44181ad6265SDimitry Andric    // Source (i.e. immediate value) encoding
44281ad6265SDimitry Andric    MxEncAddrMode_i<"imm", TYPE.Size>.Supplement,
44381ad6265SDimitry Andric    // Destination (i.e. memory operand) encoding
44481ad6265SDimitry Andric    MEM_ENC.Supplement
44581ad6265SDimitry Andric  );
44681ad6265SDimitry Andric}
447fe6060f1SDimitry Andric
44881ad6265SDimitry Andric// FIXME: What about abs.W?
449fe6060f1SDimitry Andricclass MxCmp_BI<MxType TYPE>
450fe6060f1SDimitry Andric    : MxInst<(outs), (ins TYPE.IOp:$imm, MxAL32:$abs),
451fe6060f1SDimitry Andric             "cmpi."#TYPE.Prefix#"\t$imm, $abs",
452fe6060f1SDimitry Andric             [(set CCR, (MxCmp TYPE.IPat:$imm,
45381ad6265SDimitry Andric                               (load (i32 (MxWrapper tglobaladdr:$abs)))))]> {
45481ad6265SDimitry Andric  defvar AbsEncoding = MxEncAddrMode_abs<"abs", true>;
45581ad6265SDimitry Andric  let Inst = (ascend
45681ad6265SDimitry Andric    (descend 0b00001100,
45706c3fb27SDimitry Andric             !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
45881ad6265SDimitry Andric             AbsEncoding.EA),
45981ad6265SDimitry Andric    // Source (i.e. immediate value) encoding
46081ad6265SDimitry Andric    MxEncAddrMode_i<"imm", TYPE.Size>.Supplement,
46181ad6265SDimitry Andric    // Destination (i.e. memory operand) encoding
46281ad6265SDimitry Andric    AbsEncoding.Supplement
46381ad6265SDimitry Andric  );
46481ad6265SDimitry Andric}
465fe6060f1SDimitry Andric
466fe6060f1SDimitry Andricclass MxCmp_RM<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat,
46781ad6265SDimitry Andric               MxEncMemOp MEM_ENC>
468fe6060f1SDimitry Andric    : MxInst<(outs), (ins TYPE.ROp:$reg, MEMOpd:$mem),
469fe6060f1SDimitry Andric             "cmp."#TYPE.Prefix#"\t$mem, $reg",
47081ad6265SDimitry Andric             [(set CCR, (MxCmp (load MEMPat:$mem), TYPE.ROp:$reg))]> {
47181ad6265SDimitry Andric  let Inst = (ascend
47281ad6265SDimitry Andric    (descend 0b1011,
47381ad6265SDimitry Andric      // REGISTER
47481ad6265SDimitry Andric      (operand "$reg", 3),
47581ad6265SDimitry Andric      // OPMODE
47681ad6265SDimitry Andric      !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_d_EA").Value,
47781ad6265SDimitry Andric      MEM_ENC.EA),
47881ad6265SDimitry Andric    MEM_ENC.Supplement
47981ad6265SDimitry Andric  );
48081ad6265SDimitry Andric}
481fe6060f1SDimitry Andric} // let mayLoad = 1
482fe6060f1SDimitry Andric
483fe6060f1SDimitry Andric} // let Defs = [CCR]
484fe6060f1SDimitry Andric
485fe6060f1SDimitry Andricmulticlass MMxCmp_RM<MxType TYPE> {
48681ad6265SDimitry Andric  def NAME#TYPE.KOp.Letter : MxCmp_RM<TYPE, TYPE.KOp, TYPE.KPat, MxEncAddrMode_k<"mem">>;
48781ad6265SDimitry Andric  def NAME#TYPE.QOp.Letter : MxCmp_RM<TYPE, TYPE.QOp, TYPE.QPat, MxEncAddrMode_q<"mem">>;
48881ad6265SDimitry Andric  def NAME#TYPE.POp.Letter : MxCmp_RM<TYPE, TYPE.POp, TYPE.PPat, MxEncAddrMode_p<"mem">>;
48981ad6265SDimitry Andric  def NAME#TYPE.FOp.Letter : MxCmp_RM<TYPE, TYPE.FOp, TYPE.FPat, MxEncAddrMode_f<"mem">>;
49081ad6265SDimitry Andric  def NAME#TYPE.JOp.Letter : MxCmp_RM<TYPE, TYPE.JOp, TYPE.JPat, MxEncAddrMode_j<"mem">>;
491fe6060f1SDimitry Andric}
492fe6060f1SDimitry Andric
493fe6060f1SDimitry Andricmulticlass MMxCmp_MI<MxType TYPE> {
49481ad6265SDimitry Andric  def NAME#TYPE.KOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.KOp, TYPE.KPat,
49581ad6265SDimitry Andric                                          MxEncAddrMode_k<"mem">>;
49681ad6265SDimitry Andric  def NAME#TYPE.QOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.QOp, TYPE.QPat,
49781ad6265SDimitry Andric                                          MxEncAddrMode_q<"mem">>;
49881ad6265SDimitry Andric  def NAME#TYPE.POp.Letter#"i" : MxCmp_MI<TYPE, TYPE.POp, TYPE.PPat,
49981ad6265SDimitry Andric                                          MxEncAddrMode_p<"mem">>;
50081ad6265SDimitry Andric  def NAME#TYPE.FOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.FOp, TYPE.FPat,
50181ad6265SDimitry Andric                                          MxEncAddrMode_f<"mem">>;
50281ad6265SDimitry Andric  def NAME#TYPE.JOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.JOp, TYPE.JPat,
50381ad6265SDimitry Andric                                          MxEncAddrMode_j<"mem">>;
504fe6060f1SDimitry Andric}
505fe6060f1SDimitry Andric
506fe6060f1SDimitry Andricforeach S = [8, 16, 32] in {
507fe6060f1SDimitry Andric  def CMP#S#di : MxCmp_RI<!cast<MxType>("MxType"#S#"d")>;
508fe6060f1SDimitry Andric  def CMP#S#bi : MxCmp_BI<!cast<MxType>("MxType"#S#"d")>;
509fe6060f1SDimitry Andric} // foreach
510fe6060f1SDimitry Andric
511349cc55cSDimitry Andricdef CMP8dd : MxCmp_RR<MxType8d>;
512349cc55cSDimitry Andricforeach S = [16, 32] in {
513349cc55cSDimitry Andric  def CMP#S#dr : MxCmp_RR<!cast<MxType>("MxType"#S#"r"),
514349cc55cSDimitry Andric                          !cast<MxType>("MxType"#S#"d")>;
515349cc55cSDimitry Andric}
516349cc55cSDimitry Andric
517fe6060f1SDimitry Andric// cmp mem, Dn
518fe6060f1SDimitry Andricdefm CMP8d  : MMxCmp_RM<MxType8d>;
519fe6060f1SDimitry Andricdefm CMP16d : MMxCmp_RM<MxType16d>;
520fe6060f1SDimitry Andricdefm CMP32d : MMxCmp_RM<MxType32d>;
521fe6060f1SDimitry Andric
522fe6060f1SDimitry Andric// cmp #imm, mem
523fe6060f1SDimitry Andricdefm CMP8  : MMxCmp_MI<MxType8d>;
524fe6060f1SDimitry Andricdefm CMP16 : MMxCmp_MI<MxType16d>;
525fe6060f1SDimitry Andricdefm CMP32 : MMxCmp_MI<MxType32d>;
526fe6060f1SDimitry Andric
527fe6060f1SDimitry Andric
528fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
529fe6060f1SDimitry Andric// EXT
530fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
531fe6060f1SDimitry Andric
532fe6060f1SDimitry Andric/// ---------------------------------------------------
533fe6060f1SDimitry Andric///  F  E  D  C  B  A  9 | 8  7  6 | 5  4  3 | 2  1  0
534fe6060f1SDimitry Andric/// ---------------------------------------------------
535fe6060f1SDimitry Andric///  0  1  0  0  1  0  0 |  OPMODE | 0  0  0 |   REG
536fe6060f1SDimitry Andric/// ---------------------------------------------------
537fe6060f1SDimitry Andriclet Defs = [CCR] in
538fe6060f1SDimitry Andriclet Constraints = "$src = $dst" in
539fe6060f1SDimitry Andricclass MxExt<MxType TO, MxType FROM>
540fe6060f1SDimitry Andric    : MxInst<(outs TO.ROp:$dst), (ins TO.ROp:$src),
54181ad6265SDimitry Andric             "ext."#TO.Prefix#"\t$src", []> {
54281ad6265SDimitry Andric  let Inst = (descend 0b0100100,
54381ad6265SDimitry Andric    // OPMODE
54481ad6265SDimitry Andric    !cond(
54581ad6265SDimitry Andric      // byte -> word
54681ad6265SDimitry Andric      !and(!eq(FROM.Size, 8), !eq(TO.Size, 16)): 0b010,
54781ad6265SDimitry Andric      // word -> long
54881ad6265SDimitry Andric      !and(!eq(FROM.Size, 16), !eq(TO.Size, 32)): 0b011,
54981ad6265SDimitry Andric      // byte -> long
55081ad6265SDimitry Andric      !and(!eq(FROM.Size, 8), !eq(TO.Size, 32)): 0b111
55181ad6265SDimitry Andric    ),
55281ad6265SDimitry Andric    0b000,
55381ad6265SDimitry Andric    // REGISTER
55481ad6265SDimitry Andric    (operand "$src", 3)
55581ad6265SDimitry Andric  );
55681ad6265SDimitry Andric}
557fe6060f1SDimitry Andric
558fe6060f1SDimitry Andricdef EXT16 : MxExt<MxType16d, MxType8d>;
559fe6060f1SDimitry Andricdef EXT32 : MxExt<MxType32d, MxType16d>;
560fe6060f1SDimitry Andric
561fe6060f1SDimitry Andricdef : Pat<(sext_inreg i16:$src, i8),  (EXT16 $src)>;
562fe6060f1SDimitry Andricdef : Pat<(sext_inreg i32:$src, i16), (EXT32 $src)>;
563fe6060f1SDimitry Andricdef : Pat<(sext_inreg i32:$src, i8),
564fe6060f1SDimitry Andric          (EXT32 (MOVXd32d16 (EXT16 (EXTRACT_SUBREG $src, MxSubRegIndex16Lo))))>;
565fe6060f1SDimitry Andric
566fe6060f1SDimitry Andric
567fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
568fe6060f1SDimitry Andric// DIV/MUL
569fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
570fe6060f1SDimitry Andric
571fe6060f1SDimitry Andric/// Word operation:
572fe6060f1SDimitry Andric/// ----------------------------------------------------
573fe6060f1SDimitry Andric///  F  E  D  C | B  A  9 | 8  7  6 | 5  4  3 | 2  1  0
574fe6060f1SDimitry Andric/// ----------------------------------------------------
575fe6060f1SDimitry Andric///             |         |         | EFFECTIVE ADDRESS
576fe6060f1SDimitry Andric///  x  x  x  x |   REG   | OP MODE |   MODE  |   REG
577fe6060f1SDimitry Andric/// ----------------------------------------------------
578fe6060f1SDimitry Andriclet Defs = [CCR] in {
579fe6060f1SDimitry Andriclet Constraints = "$src = $dst" in {
58081ad6265SDimitry Andric// $dreg <- $dreg op $dreg
58181ad6265SDimitry Andricclass MxDiMuOp_DD<string MN, bits<4> CMD, bit SIGNED = false,
582fe6060f1SDimitry Andric                  MxOperand DST, MxOperand OPD>
58381ad6265SDimitry Andric    : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> {
58481ad6265SDimitry Andric  let Inst = (descend CMD,
58581ad6265SDimitry Andric    // REGISTER
58681ad6265SDimitry Andric    (operand "$dst", 3),
58781ad6265SDimitry Andric    !if(SIGNED, 0b111, 0b011),
58881ad6265SDimitry Andric    /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3)
58981ad6265SDimitry Andric  );
59081ad6265SDimitry Andric}
591fe6060f1SDimitry Andric
59206c3fb27SDimitry Andric// $dreg <- $dreg op $dreg
593647cbc5dSDimitry Andricclass MxDiMuOp_DD_Long<string MN, SDNode NODE, bits<10> CMD, bit SIGNED = false>
594647cbc5dSDimitry Andric    : MxInst<(outs MxDRD32:$dst), (ins MxDRD32:$src, MxDRD32:$opd), MN#"\t$opd, $dst",
595647cbc5dSDimitry Andric             [(set i32:$dst, CCR, (NODE i32:$src, i32:$opd))]> {
59606c3fb27SDimitry Andric  let Inst = (ascend
59706c3fb27SDimitry Andric    (descend CMD,
59806c3fb27SDimitry Andric      /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3)),
59906c3fb27SDimitry Andric    (descend 0b0,
60006c3fb27SDimitry Andric      // REGISTER
60106c3fb27SDimitry Andric      (operand "$dst", 3),
60206c3fb27SDimitry Andric      !if(SIGNED, 0b1, 0b0),
60306c3fb27SDimitry Andric      /*SIZE*/0b0, 0b0000000,
60406c3fb27SDimitry Andric      // Dr REGISTER
60506c3fb27SDimitry Andric      0b000)
60606c3fb27SDimitry Andric  );
60706c3fb27SDimitry Andric}
60806c3fb27SDimitry Andric
609fe6060f1SDimitry Andric// $reg <- $reg op $imm
61081ad6265SDimitry Andricclass MxDiMuOp_DI<string MN, bits<4> CMD, bit SIGNED = false,
611fe6060f1SDimitry Andric                  MxOperand DST, MxOperand OPD>
61281ad6265SDimitry Andric    : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> {
61381ad6265SDimitry Andric  // FIXME: Support immediates with different widths.
61481ad6265SDimitry Andric  defvar ImmEnc = MxEncAddrMode_i<"opd", 16>;
61581ad6265SDimitry Andric  let Inst = (ascend
61681ad6265SDimitry Andric    (descend CMD,
61781ad6265SDimitry Andric      // REGISTER
61881ad6265SDimitry Andric      (operand "$dst", 3),
61981ad6265SDimitry Andric      !if(SIGNED, 0b111, 0b011), ImmEnc.EA),
62081ad6265SDimitry Andric    ImmEnc.Supplement
62181ad6265SDimitry Andric  );
62281ad6265SDimitry Andric}
623fe6060f1SDimitry Andric} // let Constraints
624fe6060f1SDimitry Andric} // Defs = [CCR]
625fe6060f1SDimitry Andric
626647cbc5dSDimitry Andricmulticlass MxDiMuOp<string MN, bits<4> CMD> {
62781ad6265SDimitry Andric  def "S"#NAME#"d32d16" : MxDiMuOp_DD<MN#"s", CMD, /*SIGNED*/true, MxDRD32, MxDRD16>;
62881ad6265SDimitry Andric  def "U"#NAME#"d32d16" : MxDiMuOp_DD<MN#"u", CMD, /*SIGNED*/false, MxDRD32, MxDRD16>;
629fe6060f1SDimitry Andric
63081ad6265SDimitry Andric  def "S"#NAME#"d32i16" : MxDiMuOp_DI<MN#"s", CMD, /*SIGNED*/true, MxDRD32, Mxi16imm>;
63181ad6265SDimitry Andric  def "U"#NAME#"d32i16" : MxDiMuOp_DI<MN#"u", CMD, /*SIGNED*/false, MxDRD32, Mxi16imm>;
632fe6060f1SDimitry Andric}
633fe6060f1SDimitry Andric
634fe6060f1SDimitry Andricdefm DIV : MxDiMuOp<"div", 0x8>;
635fe6060f1SDimitry Andric
636647cbc5dSDimitry Andricdef SDIVd32d32 : MxDiMuOp_DD_Long<"divs.l", sdiv, 0x131, /*SIGNED*/true>;
637647cbc5dSDimitry Andricdef UDIVd32d32 : MxDiMuOp_DD_Long<"divu.l", udiv, 0x131, /*SIGNED*/false>;
63806c3fb27SDimitry Andric
639fe6060f1SDimitry Andric// This is used to cast immediates to 16-bits for operations which don't
640fe6060f1SDimitry Andric// support smaller immediate sizes.
641fe6060f1SDimitry Andricdef as_i16imm : SDNodeXForm<imm, [{
642fe6060f1SDimitry Andric  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16);
643fe6060f1SDimitry Andric}]>;
644fe6060f1SDimitry Andric
645fe6060f1SDimitry Andric// RR i8
646fe6060f1SDimitry Andricdef : Pat<(sdiv i8:$dst, i8:$opd),
647fe6060f1SDimitry Andric          (EXTRACT_SUBREG
648fe6060f1SDimitry Andric            (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)),
649fe6060f1SDimitry Andric             MxSubRegIndex8Lo)>;
650fe6060f1SDimitry Andric
651fe6060f1SDimitry Andricdef : Pat<(udiv i8:$dst, i8:$opd),
652fe6060f1SDimitry Andric          (EXTRACT_SUBREG
653fe6060f1SDimitry Andric            (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)),
654fe6060f1SDimitry Andric             MxSubRegIndex8Lo)>;
655fe6060f1SDimitry Andric
656fe6060f1SDimitry Andricdef : Pat<(srem i8:$dst, i8:$opd),
657fe6060f1SDimitry Andric          (EXTRACT_SUBREG
658fe6060f1SDimitry Andric            (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)), 8), 8),
659fe6060f1SDimitry Andric             MxSubRegIndex8Lo)>;
660fe6060f1SDimitry Andric
661fe6060f1SDimitry Andricdef : Pat<(urem i8:$dst, i8:$opd),
662fe6060f1SDimitry Andric          (EXTRACT_SUBREG
663fe6060f1SDimitry Andric            (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)), 8), 8),
664fe6060f1SDimitry Andric             MxSubRegIndex8Lo)>;
665fe6060f1SDimitry Andric
666fe6060f1SDimitry Andric// RR i16
667fe6060f1SDimitry Andricdef : Pat<(sdiv i16:$dst, i16:$opd),
668fe6060f1SDimitry Andric          (EXTRACT_SUBREG
669fe6060f1SDimitry Andric            (SDIVd32d16 (MOVSXd32d16 $dst), $opd),
670fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
671fe6060f1SDimitry Andric
672fe6060f1SDimitry Andricdef : Pat<(udiv i16:$dst, i16:$opd),
673fe6060f1SDimitry Andric          (EXTRACT_SUBREG
674fe6060f1SDimitry Andric            (UDIVd32d16 (MOVZXd32d16 $dst), $opd),
675fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
676fe6060f1SDimitry Andric
677fe6060f1SDimitry Andricdef : Pat<(srem i16:$dst, i16:$opd),
678fe6060f1SDimitry Andric          (EXTRACT_SUBREG
679fe6060f1SDimitry Andric            (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d16 $dst), $opd), 8), 8),
680fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
681fe6060f1SDimitry Andric
682fe6060f1SDimitry Andricdef : Pat<(urem i16:$dst, i16:$opd),
683fe6060f1SDimitry Andric          (EXTRACT_SUBREG
684fe6060f1SDimitry Andric            (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d16 $dst), $opd), 8), 8),
685fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
686fe6060f1SDimitry Andric
687fe6060f1SDimitry Andric// RI i8
688647cbc5dSDimitry Andricdef : Pat<(sdiv i8:$dst, Mxi8immSExt8:$opd),
689fe6060f1SDimitry Andric          (EXTRACT_SUBREG
690fe6060f1SDimitry Andric            (SDIVd32i16 (MOVSXd32d8 $dst), (as_i16imm $opd)),
691fe6060f1SDimitry Andric             MxSubRegIndex8Lo)>;
692fe6060f1SDimitry Andric
693647cbc5dSDimitry Andricdef : Pat<(udiv i8:$dst, Mxi8immSExt8:$opd),
694fe6060f1SDimitry Andric          (EXTRACT_SUBREG
695fe6060f1SDimitry Andric            (UDIVd32i16 (MOVZXd32d8 $dst), (as_i16imm $opd)),
696fe6060f1SDimitry Andric             MxSubRegIndex8Lo)>;
697fe6060f1SDimitry Andric
698647cbc5dSDimitry Andricdef : Pat<(srem i8:$dst, Mxi8immSExt8:$opd),
699fe6060f1SDimitry Andric          (EXTRACT_SUBREG
700fe6060f1SDimitry Andric            (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d8 $dst), (as_i16imm $opd)), 8), 8),
701fe6060f1SDimitry Andric             MxSubRegIndex8Lo)>;
702fe6060f1SDimitry Andric
703647cbc5dSDimitry Andricdef : Pat<(urem i8:$dst, Mxi8immSExt8:$opd),
704fe6060f1SDimitry Andric          (EXTRACT_SUBREG
705fe6060f1SDimitry Andric            (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d8 $dst), (as_i16imm $opd)), 8), 8),
706fe6060f1SDimitry Andric             MxSubRegIndex8Lo)>;
707fe6060f1SDimitry Andric
708fe6060f1SDimitry Andric// RI i16
709647cbc5dSDimitry Andricdef : Pat<(sdiv i16:$dst, Mxi16immSExt16:$opd),
710fe6060f1SDimitry Andric          (EXTRACT_SUBREG
711fe6060f1SDimitry Andric            (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd),
712fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
713fe6060f1SDimitry Andric
714647cbc5dSDimitry Andricdef : Pat<(udiv i16:$dst, Mxi16immSExt16:$opd),
715fe6060f1SDimitry Andric          (EXTRACT_SUBREG
716fe6060f1SDimitry Andric            (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd),
717fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
718fe6060f1SDimitry Andric
719647cbc5dSDimitry Andricdef : Pat<(srem i16:$dst, Mxi16immSExt16:$opd),
720fe6060f1SDimitry Andric          (EXTRACT_SUBREG
721fe6060f1SDimitry Andric            (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd), 8), 8),
722fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
723fe6060f1SDimitry Andric
724647cbc5dSDimitry Andricdef : Pat<(urem i16:$dst, Mxi16immSExt16:$opd),
725fe6060f1SDimitry Andric          (EXTRACT_SUBREG
726fe6060f1SDimitry Andric            (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd), 8), 8),
727fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
728fe6060f1SDimitry Andric
729fe6060f1SDimitry Andric
730647cbc5dSDimitry Andricdefm MUL : MxDiMuOp<"mul", 0xC>;
731fe6060f1SDimitry Andric
732647cbc5dSDimitry Andricdef SMULd32d32 : MxDiMuOp_DD_Long<"muls.l", MxSMul, 0x130, /*SIGNED*/true>;
733647cbc5dSDimitry Andricdef UMULd32d32 : MxDiMuOp_DD_Long<"mulu.l", MxUMul, 0x130, /*SIGNED*/false>;
73406c3fb27SDimitry Andric
735fe6060f1SDimitry Andric// RR
736fe6060f1SDimitry Andricdef : Pat<(mul i16:$dst, i16:$opd),
737fe6060f1SDimitry Andric          (EXTRACT_SUBREG
738fe6060f1SDimitry Andric            (SMULd32d16 (MOVXd32d16 $dst), $opd),
739fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
740fe6060f1SDimitry Andric
741fe6060f1SDimitry Andricdef : Pat<(mulhs i16:$dst, i16:$opd),
742fe6060f1SDimitry Andric          (EXTRACT_SUBREG
743fe6060f1SDimitry Andric            (ASR32di (ASR32di (SMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8),
744fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
745fe6060f1SDimitry Andric
746fe6060f1SDimitry Andricdef : Pat<(mulhu i16:$dst, i16:$opd),
747fe6060f1SDimitry Andric          (EXTRACT_SUBREG
748fe6060f1SDimitry Andric            (LSR32di (LSR32di (UMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8),
749fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
750fe6060f1SDimitry Andric
75106c3fb27SDimitry Andricdef : Pat<(mul i32:$dst, i32:$opd), (SMULd32d32 $dst, $opd)>;
75206c3fb27SDimitry Andric
753fe6060f1SDimitry Andric
754fe6060f1SDimitry Andric// RI
755647cbc5dSDimitry Andricdef : Pat<(mul i16:$dst, Mxi16immSExt16:$opd),
756fe6060f1SDimitry Andric          (EXTRACT_SUBREG
757fe6060f1SDimitry Andric            (SMULd32i16 (MOVXd32d16 $dst), imm:$opd),
758fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
759fe6060f1SDimitry Andric
760647cbc5dSDimitry Andricdef : Pat<(mulhs i16:$dst, Mxi16immSExt16:$opd),
761fe6060f1SDimitry Andric          (EXTRACT_SUBREG
762fe6060f1SDimitry Andric            (ASR32di (ASR32di (SMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8),
763fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
764fe6060f1SDimitry Andric
765647cbc5dSDimitry Andricdef : Pat<(mulhu i16:$dst, Mxi16immSExt16:$opd),
766fe6060f1SDimitry Andric          (EXTRACT_SUBREG
767fe6060f1SDimitry Andric            (LSR32di (LSR32di (UMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8),
768fe6060f1SDimitry Andric             MxSubRegIndex16Lo)>;
769fe6060f1SDimitry Andric
770fe6060f1SDimitry Andric
771fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
772*0fca6ea1SDimitry Andric// NEG/NEGX/NOT
773fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
774fe6060f1SDimitry Andric
775fe6060f1SDimitry Andric/// ------------+------------+------+---------+---------
776fe6060f1SDimitry Andric///  F  E  D  C | B  A  9  8 | 7  6 | 5  4  3 | 2  1  0
777fe6060f1SDimitry Andric/// ------------+------------+------+-------------------
778fe6060f1SDimitry Andric///             |            |      | EFFECTIVE ADDRESS
779fe6060f1SDimitry Andric///  0  1  0  0 | x  x  x  x | SIZE |   MODE  |   REG
780fe6060f1SDimitry Andric/// ------------+------------+------+---------+---------
781fe6060f1SDimitry Andriclet Defs = [CCR] in {
782fe6060f1SDimitry Andriclet Constraints = "$src = $dst" in {
783fe6060f1SDimitry Andric
784fe6060f1SDimitry Andricclass MxNeg_D<MxType TYPE>
785fe6060f1SDimitry Andric    : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src),
786fe6060f1SDimitry Andric             "neg."#TYPE.Prefix#"\t$dst",
78781ad6265SDimitry Andric             [(set TYPE.VT:$dst, (ineg TYPE.VT:$src))]> {
78881ad6265SDimitry Andric  let Inst = (descend 0b01000100,
78906c3fb27SDimitry Andric    /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
79081ad6265SDimitry Andric    //MODE without last bit
79181ad6265SDimitry Andric    0b00,
79281ad6265SDimitry Andric    //REGISTER prefixed by D/A bit
79381ad6265SDimitry Andric    (operand "$dst", 4)
79481ad6265SDimitry Andric  );
79581ad6265SDimitry Andric}
796fe6060f1SDimitry Andric
797fe6060f1SDimitry Andriclet Uses = [CCR] in {
798fe6060f1SDimitry Andricclass MxNegX_D<MxType TYPE>
799fe6060f1SDimitry Andric    : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src),
800fe6060f1SDimitry Andric             "negx."#TYPE.Prefix#"\t$dst",
80181ad6265SDimitry Andric             [(set TYPE.VT:$dst, (MxSubX 0, TYPE.VT:$src, CCR))]> {
80281ad6265SDimitry Andric  let Inst = (descend 0b01000000,
80306c3fb27SDimitry Andric    /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
80481ad6265SDimitry Andric    //MODE without last bit
80581ad6265SDimitry Andric    0b00,
80681ad6265SDimitry Andric    //REGISTER prefixed by D/A bit
80781ad6265SDimitry Andric    (operand "$dst", 4)
80881ad6265SDimitry Andric  );
80981ad6265SDimitry Andric}
810fe6060f1SDimitry Andric}
811fe6060f1SDimitry Andric
812*0fca6ea1SDimitry Andricclass MxNot_D<MxType TYPE>
813*0fca6ea1SDimitry Andric    : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src),
814*0fca6ea1SDimitry Andric             "not."#TYPE.Prefix#"\t$dst",
815*0fca6ea1SDimitry Andric             [(set TYPE.VT:$dst, (not TYPE.VT:$src))]> {
816*0fca6ea1SDimitry Andric  let Inst = (descend 0b01000110,
817*0fca6ea1SDimitry Andric    /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
818*0fca6ea1SDimitry Andric    //MODE without last bit
819*0fca6ea1SDimitry Andric    0b00,
820*0fca6ea1SDimitry Andric    //REGISTER prefixed by D/A bit
821*0fca6ea1SDimitry Andric    (operand "$dst", 4)
822*0fca6ea1SDimitry Andric  );
823*0fca6ea1SDimitry Andric}
824*0fca6ea1SDimitry Andric
825fe6060f1SDimitry Andric} // let Constraints
826fe6060f1SDimitry Andric} // let Defs = [CCR]
827fe6060f1SDimitry Andric
828fe6060f1SDimitry Andricforeach S = [8, 16, 32] in {
829fe6060f1SDimitry Andric  def NEG#S#d  : MxNeg_D<!cast<MxType>("MxType"#S#"d")>;
830fe6060f1SDimitry Andric  def NEGX#S#d : MxNegX_D<!cast<MxType>("MxType"#S#"d")>;
831*0fca6ea1SDimitry Andric  def NOT#S#d  : MxNot_D<!cast<MxType>("MxType"#S#"d")>;
832fe6060f1SDimitry Andric}
833fe6060f1SDimitry Andric
834fe6060f1SDimitry Andricdef : Pat<(MxSub 0, i8 :$src), (NEG8d  MxDRD8 :$src)>;
835fe6060f1SDimitry Andricdef : Pat<(MxSub 0, i16:$src), (NEG16d MxDRD16:$src)>;
836fe6060f1SDimitry Andricdef : Pat<(MxSub 0, i32:$src), (NEG32d MxDRD32:$src)>;
83706c3fb27SDimitry Andric// SExt of i1 values.
83806c3fb27SDimitry Andric// Although we specify `ZeroOrOneBooleanContent` for boolean content,
83906c3fb27SDimitry Andric// we're still adding an AND here as we don't know the origin of the i1 value.
84006c3fb27SDimitry Andricdef : Pat<(sext_inreg i8:$src,  i1), (NEG8d  (AND8di  MxDRD8:$src,  1))>;
84106c3fb27SDimitry Andricdef : Pat<(sext_inreg i16:$src, i1), (NEG16d (AND16di MxDRD16:$src, 1))>;
84206c3fb27SDimitry Andricdef : Pat<(sext_inreg i32:$src, i1), (NEG32d (AND32di MxDRD32:$src, 1))>;
843fe6060f1SDimitry Andric
844fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
845fe6060f1SDimitry Andric// no-CCR Patterns
846fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
847fe6060f1SDimitry Andric
848fe6060f1SDimitry Andric/// Basically the reason for this stuff is that add and addc share the same
849fe6060f1SDimitry Andric/// operand types constraints for whatever reasons and I had to define a common
850fe6060f1SDimitry Andric/// MxAdd and MxSub instructions that produce CCR and then pattern-map add and addc
851fe6060f1SDimitry Andric/// to it.
852fe6060f1SDimitry Andric/// NOTE On the other hand I see no reason why I cannot just drop explicit CCR
853fe6060f1SDimitry Andric/// result. Anyway works for now, hopefully I will better understand how this stuff
854fe6060f1SDimitry Andric/// is designed later
855fe6060f1SDimitry Andricforeach N = ["add", "addc"] in {
856fe6060f1SDimitry Andric
857fe6060f1SDimitry Andric  // add reg, reg
858fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd),
859fe6060f1SDimitry Andric            (ADD8dd  MxDRD8 :$src, MxDRD8 :$opd)>;
860fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd),
861349cc55cSDimitry Andric            (ADD16dr MxXRD16:$src, MxDRD16:$opd)>;
862fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd),
863349cc55cSDimitry Andric            (ADD32dr MxXRD32:$src, MxDRD32:$opd)>;
864fe6060f1SDimitry Andric
865fe6060f1SDimitry Andric  // add (An), reg
866fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)),
867fe6060f1SDimitry Andric            (ADD8dj MxDRD8:$src, MxType8.JOp:$opd)>;
868fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)),
869fe6060f1SDimitry Andric            (ADD16dj MxDRD16:$src, MxType16.JOp:$opd)>;
870fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)),
871349cc55cSDimitry Andric            (ADD32dj MxDRD32:$src, MxType32.JOp:$opd)>;
872fe6060f1SDimitry Andric
873fe6060f1SDimitry Andric  // add (i,An), reg
874fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)),
875fe6060f1SDimitry Andric            (ADD8dp MxDRD8:$src, MxType8.POp:$opd)>;
876fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)),
877fe6060f1SDimitry Andric            (ADD16dp MxDRD16:$src, MxType16.POp:$opd)>;
878fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)),
879349cc55cSDimitry Andric            (ADD32dp MxDRD32:$src, MxType32.POp:$opd)>;
880fe6060f1SDimitry Andric
881fe6060f1SDimitry Andric  // add (i,An,Xn), reg
882fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)),
883fe6060f1SDimitry Andric            (ADD8df MxDRD8:$src, MxType8.FOp:$opd)>;
884fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)),
885fe6060f1SDimitry Andric            (ADD16df MxDRD16:$src, MxType16.FOp:$opd)>;
886fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)),
887349cc55cSDimitry Andric            (ADD32df MxDRD32:$src, MxType32.FOp:$opd)>;
888fe6060f1SDimitry Andric
889fe6060f1SDimitry Andric  // add reg, imm
890647cbc5dSDimitry Andric  def : Pat<(!cast<SDNode>(N) i8: $src, Mxi8immSExt8:$opd),
891fe6060f1SDimitry Andric            (ADD8di  MxDRD8 :$src, imm:$opd)>;
892647cbc5dSDimitry Andric  def : Pat<(!cast<SDNode>(N) i16:$src, Mxi16immSExt16:$opd),
893fe6060f1SDimitry Andric            (ADD16di MxDRD16:$src, imm:$opd)>;
894fe6060f1SDimitry Andric
895fe6060f1SDimitry Andric  // LEAp is more complex and thus will be selected over normal ADD32ri but it cannot
896fe6060f1SDimitry Andric  // be used with data registers, here by adding complexity to a simple ADD32ri insts
897fe6060f1SDimitry Andric  // we make sure it will be selected over LEAp
898fe6060f1SDimitry Andric  let AddedComplexity = 15 in {
899647cbc5dSDimitry Andric  def : Pat<(!cast<SDNode>(N) i32:$src, Mxi32immSExt32:$opd),
900349cc55cSDimitry Andric            (ADD32di MxDRD32:$src, imm:$opd)>;
901fe6060f1SDimitry Andric  } // AddedComplexity = 15
902fe6060f1SDimitry Andric
903fe6060f1SDimitry Andric  // add imm, (An)
904fe6060f1SDimitry Andric  def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd),
905fe6060f1SDimitry Andric                   MxType8.JPat:$dst),
906fe6060f1SDimitry Andric            (ADD8ji MxType8.JOp:$dst, imm:$opd)>;
907fe6060f1SDimitry Andric  def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd),
908fe6060f1SDimitry Andric                   MxType16.JPat:$dst),
909fe6060f1SDimitry Andric            (ADD16ji MxType16.JOp:$dst, imm:$opd)>;
910fe6060f1SDimitry Andric  def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd),
911fe6060f1SDimitry Andric                   MxType32.JPat:$dst),
912fe6060f1SDimitry Andric            (ADD32ji MxType32.JOp:$dst, imm:$opd)>;
913fe6060f1SDimitry Andric
914fe6060f1SDimitry Andric} // foreach add, addc
915fe6060f1SDimitry Andric
916fe6060f1SDimitry Andricdef : Pat<(adde i8 :$src, i8 :$opd), (ADDX8dd  MxDRD8 :$src, MxDRD8 :$opd)>;
917fe6060f1SDimitry Andricdef : Pat<(adde i16:$src, i16:$opd), (ADDX16dd MxDRD16:$src, MxDRD16:$opd)>;
918fe6060f1SDimitry Andricdef : Pat<(adde i32:$src, i32:$opd), (ADDX32dd MxDRD32:$src, MxDRD32:$opd)>;
919fe6060f1SDimitry Andric
920fe6060f1SDimitry Andric
921fe6060f1SDimitry Andric
922fe6060f1SDimitry Andricforeach N = ["sub", "subc"] in {
923fe6060f1SDimitry Andric
924fe6060f1SDimitry Andric  // sub reg, reg
925fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd),
926fe6060f1SDimitry Andric            (SUB8dd  MxDRD8 :$src, MxDRD8 :$opd)>;
927fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd),
928fe6060f1SDimitry Andric            (SUB16dd MxDRD16:$src, MxDRD16:$opd)>;
929fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd),
930349cc55cSDimitry Andric            (SUB32dd MxDRD32:$src, MxDRD32:$opd)>;
931fe6060f1SDimitry Andric
932fe6060f1SDimitry Andric
933fe6060f1SDimitry Andric  // sub (An), reg
934fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)),
935fe6060f1SDimitry Andric            (SUB8dj MxDRD8:$src, MxType8.JOp:$opd)>;
936fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)),
937fe6060f1SDimitry Andric            (SUB16dj MxDRD16:$src, MxType16.JOp:$opd)>;
938fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)),
939349cc55cSDimitry Andric            (SUB32dj MxDRD32:$src, MxType32.JOp:$opd)>;
940fe6060f1SDimitry Andric
941fe6060f1SDimitry Andric  // sub (i,An), reg
942fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)),
943fe6060f1SDimitry Andric            (SUB8dp MxDRD8:$src, MxType8.POp:$opd)>;
944fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)),
945fe6060f1SDimitry Andric            (SUB16dp MxDRD16:$src, MxType16.POp:$opd)>;
946fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)),
947349cc55cSDimitry Andric            (SUB32dp MxDRD32:$src, MxType32.POp:$opd)>;
948fe6060f1SDimitry Andric
949fe6060f1SDimitry Andric  // sub (i,An,Xn), reg
950fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)),
951fe6060f1SDimitry Andric            (SUB8df MxDRD8:$src, MxType8.FOp:$opd)>;
952fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)),
953fe6060f1SDimitry Andric            (SUB16df MxDRD16:$src, MxType16.FOp:$opd)>;
954fe6060f1SDimitry Andric  def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)),
955349cc55cSDimitry Andric            (SUB32df MxDRD32:$src, MxType32.FOp:$opd)>;
956fe6060f1SDimitry Andric
957fe6060f1SDimitry Andric  // sub reg, imm
958647cbc5dSDimitry Andric  def : Pat<(!cast<SDNode>(N) i8 :$src, Mxi8immSExt8 :$opd),
959fe6060f1SDimitry Andric            (SUB8di  MxDRD8 :$src, imm:$opd)>;
960647cbc5dSDimitry Andric  def : Pat<(!cast<SDNode>(N) i16:$src, Mxi16immSExt16:$opd),
961fe6060f1SDimitry Andric            (SUB16di MxDRD16:$src, imm:$opd)>;
962647cbc5dSDimitry Andric  def : Pat<(!cast<SDNode>(N) i32:$src, Mxi32immSExt32:$opd),
963349cc55cSDimitry Andric            (SUB32di MxDRD32:$src, imm:$opd)>;
964fe6060f1SDimitry Andric
965fe6060f1SDimitry Andric  // sub imm, (An)
966fe6060f1SDimitry Andric  def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd),
967fe6060f1SDimitry Andric                   MxType8.JPat:$dst),
968fe6060f1SDimitry Andric            (SUB8ji MxType8.JOp:$dst, imm:$opd)>;
969fe6060f1SDimitry Andric  def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd),
970fe6060f1SDimitry Andric                   MxType16.JPat:$dst),
971fe6060f1SDimitry Andric            (SUB16ji MxType16.JOp:$dst, imm:$opd)>;
972fe6060f1SDimitry Andric  def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd),
973fe6060f1SDimitry Andric                   MxType32.JPat:$dst),
974fe6060f1SDimitry Andric            (SUB32ji MxType32.JOp:$dst, imm:$opd)>;
975fe6060f1SDimitry Andric
976fe6060f1SDimitry Andric} // foreach sub, subx
977fe6060f1SDimitry Andric
978fe6060f1SDimitry Andricdef : Pat<(sube i8 :$src, i8 :$opd), (SUBX8dd  MxDRD8 :$src, MxDRD8 :$opd)>;
979fe6060f1SDimitry Andricdef : Pat<(sube i16:$src, i16:$opd), (SUBX16dd MxDRD16:$src, MxDRD16:$opd)>;
980fe6060f1SDimitry Andricdef : Pat<(sube i32:$src, i32:$opd), (SUBX32dd MxDRD32:$src, MxDRD32:$opd)>;
981fe6060f1SDimitry Andric
982fe6060f1SDimitry Andricmulticlass BitwisePat<string INST, SDNode OP> {
983fe6060f1SDimitry Andric  // op reg, reg
984fe6060f1SDimitry Andric  def : Pat<(OP i8 :$src, i8 :$opd),
985fe6060f1SDimitry Andric            (!cast<MxInst>(INST#"8dd")  MxDRD8 :$src, MxDRD8 :$opd)>;
986fe6060f1SDimitry Andric  def : Pat<(OP i16:$src, i16:$opd),
987fe6060f1SDimitry Andric            (!cast<MxInst>(INST#"16dd") MxDRD16:$src, MxDRD16:$opd)>;
988fe6060f1SDimitry Andric  def : Pat<(OP i32:$src, i32:$opd),
989fe6060f1SDimitry Andric            (!cast<MxInst>(INST#"32dd") MxDRD32:$src, MxDRD32:$opd)>;
990fe6060f1SDimitry Andric  // op reg, imm
991647cbc5dSDimitry Andric  def : Pat<(OP i8: $src, Mxi8immSExt8 :$opd),
992fe6060f1SDimitry Andric            (!cast<MxInst>(INST#"8di")  MxDRD8 :$src, imm:$opd)>;
993647cbc5dSDimitry Andric  def : Pat<(OP i16:$src, Mxi16immSExt16:$opd),
994fe6060f1SDimitry Andric            (!cast<MxInst>(INST#"16di") MxDRD16:$src, imm:$opd)>;
995647cbc5dSDimitry Andric  def : Pat<(OP i32:$src, Mxi32immSExt32:$opd),
996fe6060f1SDimitry Andric            (!cast<MxInst>(INST#"32di") MxDRD32:$src, imm:$opd)>;
997fe6060f1SDimitry Andric}
998fe6060f1SDimitry Andric
999fe6060f1SDimitry Andricdefm : BitwisePat<"AND", and>;
1000fe6060f1SDimitry Andricdefm : BitwisePat<"OR",  or>;
1001fe6060f1SDimitry Andricdefm : BitwisePat<"XOR", xor>;
100206c3fb27SDimitry Andric
100306c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
100406c3fb27SDimitry Andric// Floating point arithmetic instruction
100506c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
100606c3fb27SDimitry Andric
100706c3fb27SDimitry Andriclet Defs = [FPS] in
100806c3fb27SDimitry Andricclass MxFArithBase_FF<dag outs, dag ins, string asm, string rounding,
100906c3fb27SDimitry Andric                      list<dag> patterns>
101006c3fb27SDimitry Andric    : MxInst<outs, ins, asm, patterns> {
101106c3fb27SDimitry Andric  let Uses = !if(!eq(rounding, ""), [FPC], []);
101206c3fb27SDimitry Andric
101306c3fb27SDimitry Andric  let Predicates = !if(!eq(rounding, ""), [AtLeastM68881], [AtLeastM68040]);
101406c3fb27SDimitry Andric}
101506c3fb27SDimitry Andric
101606c3fb27SDimitry Andricclass MxFPOpModeSelector<string rounding, bits<7> single, bits<7> double,
101706c3fb27SDimitry Andric                         bits<7> extended> {
101806c3fb27SDimitry Andric  bits<7> Mode = !cond(!eq(rounding, "s"): single,
101906c3fb27SDimitry Andric                       !eq(rounding, "d"): double,
102006c3fb27SDimitry Andric                       !eq(rounding, ""): extended);
102106c3fb27SDimitry Andric}
102206c3fb27SDimitry Andric
102306c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
102406c3fb27SDimitry Andric// Unary floating point instruction
102506c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
102606c3fb27SDimitry Andric
102706c3fb27SDimitry Andricclass MxFUnary_FF<MxOpBundle Opnd, string rounding,
102806c3fb27SDimitry Andric                  string mnemonic, bits<7> opmode>
102906c3fb27SDimitry Andric    : MxFArithBase_FF<(outs Opnd.Op:$dst), (ins Opnd.Op:$src),
103006c3fb27SDimitry Andric                    "f"#rounding#mnemonic#".x\t$src, $dst", rounding, [(null_frag)]> {
103106c3fb27SDimitry Andric  let Inst = (ascend
103206c3fb27SDimitry Andric  (descend 0b1111,
103306c3fb27SDimitry Andric    /*COPROCESSOR ID*/0b001,
103406c3fb27SDimitry Andric    0b000,
103506c3fb27SDimitry Andric    /*MODE+REGISTER*/0b000000),
103606c3fb27SDimitry Andric  (descend 0b0, /* R/M */ 0b0, 0b0,
103706c3fb27SDimitry Andric    /*SOURCE SPECIFIER*/
103806c3fb27SDimitry Andric    (operand "$src", 3),
103906c3fb27SDimitry Andric    /*DESTINATION*/
104006c3fb27SDimitry Andric    (operand "$dst", 3),
104106c3fb27SDimitry Andric    /*OPMODE*/
104206c3fb27SDimitry Andric    opmode)
104306c3fb27SDimitry Andric  );
104406c3fb27SDimitry Andric}
104506c3fb27SDimitry Andric
104606c3fb27SDimitry Andricmulticlass MxFUnaryOp<string mnemonic, bits<7> single, bits<7> double,
104706c3fb27SDimitry Andric                      bits<7> extended> {
104806c3fb27SDimitry Andric  foreach rounding = ["", "s", "d"] in {
104906c3fb27SDimitry Andric    defvar opmode = MxFPOpModeSelector<rounding, single, double, extended>.Mode;
105006c3fb27SDimitry Andric
105106c3fb27SDimitry Andric    def F # !toupper(rounding) # !substr(NAME, 1) # "80fp_fp"
105206c3fb27SDimitry Andric      : MxFUnary_FF<MxOp80AddrMode_fpr, rounding, mnemonic, opmode>;
105306c3fb27SDimitry Andric
105406c3fb27SDimitry Andric    let isCodeGenOnly = 1 in
105506c3fb27SDimitry Andric    foreach size = [32, 64] in
105606c3fb27SDimitry Andric      def F # !toupper(rounding) # !substr(NAME, 1) # size # "fp_fp"
105706c3fb27SDimitry Andric        : MxFUnary_FF<!cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr"),
105806c3fb27SDimitry Andric                      rounding, mnemonic, opmode>;
105906c3fb27SDimitry Andric  }
106006c3fb27SDimitry Andric}
106106c3fb27SDimitry Andric
106206c3fb27SDimitry Andricdefm FABS : MxFUnaryOp<"abs", 0b1011000, 0b1011100, 0b0011000>;
106306c3fb27SDimitry Andricdefm FNEG : MxFUnaryOp<"neg", 0b1011010, 0b1011110, 0b0011010>;
106406c3fb27SDimitry Andric
106506c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
106606c3fb27SDimitry Andric// Binary floating point instruction
106706c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
106806c3fb27SDimitry Andric
106906c3fb27SDimitry Andriclet Constraints = "$src = $dst" in
107006c3fb27SDimitry Andricclass MxFBinary_FF<MxOpBundle Opnd, string rounding,
107106c3fb27SDimitry Andric                   string mnemonic, bits<7> opmode>
107206c3fb27SDimitry Andric    : MxFArithBase_FF<(outs Opnd.Op:$dst), (ins Opnd.Op:$src, Opnd.Op:$opd),
107306c3fb27SDimitry Andric                      "f"#rounding#mnemonic#".x\t$opd, $dst", rounding, [(null_frag)]> {
107406c3fb27SDimitry Andric  let Inst = (ascend
107506c3fb27SDimitry Andric  (descend 0b1111,
107606c3fb27SDimitry Andric    /*COPROCESSOR ID*/0b001,
107706c3fb27SDimitry Andric    0b000,
107806c3fb27SDimitry Andric    /*MODE+REGISTER*/0b000000),
107906c3fb27SDimitry Andric  (descend 0b0, /* R/M */ 0b0, 0b0,
108006c3fb27SDimitry Andric    /*SOURCE SPECIFIER*/
108106c3fb27SDimitry Andric    (operand "$opd", 3),
108206c3fb27SDimitry Andric    /*DESTINATION*/
108306c3fb27SDimitry Andric    (operand "$dst", 3),
108406c3fb27SDimitry Andric    /*OPMODE*/
108506c3fb27SDimitry Andric    opmode)
108606c3fb27SDimitry Andric  );
108706c3fb27SDimitry Andric}
108806c3fb27SDimitry Andric
108906c3fb27SDimitry Andricmulticlass MxFBinaryOp<string mnemonic, bits<7> single, bits<7> double,
109006c3fb27SDimitry Andric                      bits<7> extended> {
109106c3fb27SDimitry Andric  foreach rounding = ["", "s", "d"] in {
109206c3fb27SDimitry Andric    defvar opmode = MxFPOpModeSelector<rounding, single, double, extended>.Mode;
109306c3fb27SDimitry Andric
109406c3fb27SDimitry Andric    def F # !toupper(rounding) # !substr(NAME, 1) # "80fp_fp"
109506c3fb27SDimitry Andric      : MxFBinary_FF<MxOp80AddrMode_fpr, rounding, mnemonic, opmode>;
109606c3fb27SDimitry Andric
109706c3fb27SDimitry Andric    let isCodeGenOnly = 1 in
109806c3fb27SDimitry Andric    foreach size = [32, 64] in
109906c3fb27SDimitry Andric      def F # !toupper(rounding) # !substr(NAME, 1) # size # "fp_fp"
110006c3fb27SDimitry Andric        : MxFBinary_FF<!cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr"),
110106c3fb27SDimitry Andric                        rounding, mnemonic, opmode>;
110206c3fb27SDimitry Andric  }
110306c3fb27SDimitry Andric}
110406c3fb27SDimitry Andric
110506c3fb27SDimitry Andricdefm FADD : MxFBinaryOp<"add", 0b1100010, 0b1100110, 0b0100010>;
110606c3fb27SDimitry Andricdefm FSUB : MxFBinaryOp<"sub", 0b1101000, 0b1101100, 0b0101000>;
110706c3fb27SDimitry Andricdefm FMUL : MxFBinaryOp<"mul", 0b1100011, 0b1100111, 0b0100011>;
110806c3fb27SDimitry Andricdefm FDIV : MxFBinaryOp<"div", 0b1100000, 0b1100100, 0b0100000>;
1109