xref: /freebsd/contrib/llvm-project/llvm/lib/Target/M68k/M68kInstrControl.td (revision ebacd8013fe5f7fdf9f6a5b286f6680dd2891036)
1//===-- M68kInstrControl.td - Control Flow Instructions ----*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file describes the M68k jump, return, call, and related instructions.
11/// Here is the current status of the file:
12///
13///  Machine:
14///
15///       BRA   [x]     BSR  [ ]     Bcc [~]     DBcc [ ]     FBcc [ ]
16///       FDBcc [ ]     FNOP [ ]     FPn [ ]     FScc [ ]     FTST [ ]
17///       JMP   [~]     JSR  [x]     NOP [x]     RTD  [!]     RTR  [ ]
18///       RTS   [x]     Scc  [~]     TST [ ]
19///
20///  Pseudo:
21///
22///          RET [x]
23///    TCRETURNj [x]   TCRETURNq [x]
24///     TAILJMPj [x]    TAILJMPq [x]
25///
26///  Map:
27///
28///   [ ] - was not touched at all
29///   [!] - requires extarnal stuff implemented
30///   [~] - in progress but usable
31///   [x] - done
32///
33///
34///                                   NOTE
35///      Though branch and jump instructions are using memory operands they
36///      DO NOT read the jump address from memory, they just calculate EA
37///      and jump there.
38///
39//===----------------------------------------------------------------------===//
40
41//===----------------------------------------------------------------------===//
42// NOP
43//===----------------------------------------------------------------------===//
44
45let hasSideEffects = 0 in {
46  def NOP : MxInst<(outs), (ins), "nop", []> {
47    let Inst = (descend 0b0100, 0b1110, 0b0111, 0b0001);
48  }
49}
50
51
52//===----------------------------------------------------------------------===//
53// Conditions
54//===----------------------------------------------------------------------===//
55
56/// CC—Carry clear      GE—Greater than or equal
57/// LS—Lower or same    PL—Plus
58/// CS—Carry set        GT—Greater than
59/// LT—Less than        T—Always true*
60/// EQ—Equal            HI—Higher
61/// MI—Minus            VC—Overflow clear
62/// F—Never true*       LE—Less than or equal
63/// NE—Not equal        VS—Overflow set
64///
65/// *Not applicable to the Bcc instructions.
66class MxEncCondOp<bits<4> cond> {
67  dag Value = (descend cond);
68}
69
70def MxCCt  : MxEncCondOp<0b0000>;
71def MxCCf  : MxEncCondOp<0b0001>;
72def MxCChi : MxEncCondOp<0b0010>;
73def MxCCls : MxEncCondOp<0b0011>;
74def MxCCcc : MxEncCondOp<0b0100>;
75def MxCCcs : MxEncCondOp<0b0101>;
76def MxCCne : MxEncCondOp<0b0110>;
77def MxCCeq : MxEncCondOp<0b0111>;
78def MxCCvc : MxEncCondOp<0b1000>;
79def MxCCvs : MxEncCondOp<0b1001>;
80def MxCCpl : MxEncCondOp<0b1010>;
81def MxCCmi : MxEncCondOp<0b1011>;
82def MxCCge : MxEncCondOp<0b1100>;
83def MxCClt : MxEncCondOp<0b1101>;
84def MxCCgt : MxEncCondOp<0b1110>;
85def MxCCle : MxEncCondOp<0b1111>;
86
87
88
89/// --------------------------------+---------+---------
90///  F  E  D  C | B  A  9  8 | 7  6 | 5  4  3 | 2  1  0
91/// --------------------------------+---------+---------
92///  0  1  0  1 | CONDITION  | 1  1 |   MODE  |   REG
93/// ----------------------------------------------------
94
95let Uses = [CCR] in {
96class MxSccR<string CC>
97    : MxInst<(outs MxDRD8:$dst), (ins), "s"#CC#"\t$dst",
98             [(set i8:$dst, (MxSetCC !cast<PatLeaf>("MxCOND"#CC), CCR))]> {
99  let Inst = (descend 0b0101, !cast<MxEncCondOp>("MxCC"#CC).Value, 0b11,
100              /*MODE without last bit*/0b00,
101              /*REGISTER prefixed with D/A bit*/(operand "$dst", 4));
102}
103
104class MxSccM<string CC, MxOperand MEMOpd, ComplexPattern MEMPat, MxEncMemOp DST_ENC>
105    : MxInst<(outs), (ins MEMOpd:$dst), "s"#CC#"\t$dst",
106             [(store (MxSetCC !cast<PatLeaf>("MxCOND"#CC), CCR), MEMPat:$dst)]> {
107  let Inst =
108    (ascend
109      (descend 0b0101, !cast<MxEncCondOp>("MxCC"#CC).Value, 0b11, DST_ENC.EA),
110      DST_ENC.Supplement
111    );
112}
113}
114
115foreach cc = [ "cc", "ls", "lt", "eq", "mi", "f", "ne", "ge",
116               "cs", "pl", "gt", "t", "hi", "vc", "le", "vs"] in {
117def SET#"d8"#cc : MxSccR<cc>;
118def SET#"j8"#cc : MxSccM<cc, MxType8.JOp, MxType8.JPat, MxEncAddrMode_j<"dst">>;
119def SET#"p8"#cc : MxSccM<cc, MxType8.POp, MxType8.PPat, MxEncAddrMode_p<"dst">>;
120}
121
122//===----------------------------------------------------------------------===//
123// Jumps
124//===----------------------------------------------------------------------===//
125
126///------------------------------+---------+---------
127/// F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0
128///------------------------------+---------+---------
129/// 0  1  0  0  1  1  1  0  1  1 |  MODE   |   REG
130///------------------------------+---------+---------
131let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in
132class MxJMP<MxOperand LOCOp, MxEncMemOp DST_ENC>
133    : MxInst<(outs), (ins LOCOp:$dst), "jmp\t$dst", [(brind iPTR:$dst)]> {
134  let Inst =
135    (ascend
136      (descend 0b0100, 0b1110, 0b11, DST_ENC.EA),
137      DST_ENC.Supplement
138    );
139}
140
141def JMP32j : MxJMP<MxARI32, MxEncAddrMode_j<"dst">>;
142
143
144// FIXME Support 16 bit indirect jump.
145// Currently M68k does not allow 16 bit indirect jumps use sext operands
146// def JMP16r     : MxInst<(outs), (ins M68k_ARI16:$dst),
147//                             "jmp\t$dst",
148//                             [(brind AR16:$dst)]>;
149
150//===----------------------------------------------------------------------===//
151// Branches
152//===----------------------------------------------------------------------===//
153
154/// --------------------------------------------------
155///  F  E  D  C | B  A  9  8 | 7  6  5  4  3  2  1  0
156/// --------------------------------------------------
157///  0  1  1  0 | CONDITION |   8-BIT DISPLACEMENT
158/// --------------------------------------------------
159///  16-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $00
160/// --------------------------------------------------
161///  32-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $FF
162/// --------------------------------------------------
163let isBranch = 1, isTerminator = 1, Uses = [CCR] in
164class MxBcc<string cc, Operand TARGET, dag disp_8, dag disp_16_32>
165    : MxInst<(outs), (ins TARGET:$dst), "b"#cc#"\t$dst", []> {
166  // FIXME: If we want to avoid supplying disp_16_32 with empty
167  //        (ascend) for 16/32 bits variants, we can use conditional
168  //        bang operator like this:
169  //        ```
170  //        class MxBcc<string cc, Operand TARGET, int SIZE>
171  //        ...
172  //        let Inst = !cond(
173  //            !eq(SIZE, 8):   /* encoding for Bcc8  */
174  //            !eq(SIZE, 16):  /* encoding for Bcc16 */
175  //            !eq(SIZE, 32):  /* encoding for Bcc32 */
176  //        );
177  let Inst =
178      (ascend
179        (descend 0b0110, !cast<MxEncCondOp>("MxCC"#cc).Value, disp_8),
180        disp_16_32
181      );
182}
183
184foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
185               "cs", "pl", "gt", "hi", "vc", "le", "vs"] in {
186  def B#cc#"8"
187    : MxBcc<cc, MxBrTarget8,
188            (operand "$dst", 8, (encoder "encodePCRelImm<8>")), (ascend)>;
189
190  def B#cc#"16"
191    : MxBcc<cc, MxBrTarget16, (descend 0b0000, 0b0000),
192            (operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
193}
194
195foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
196               "cs", "pl", "gt", "hi", "vc", "le", "vs"] in {
197def : Pat<(MxBrCond bb:$target, !cast<PatLeaf>("MxCOND"#cc), CCR),
198          (!cast<Instruction>("B"#cc#"8") MxBrTarget8:$target)>;
199}
200
201/// -------------------------------------------------
202///  F  E  D  C  B  A  9  8 | 7  6  5  4  3  2  1  0
203/// -------------------------------------------------
204///  0  1  1  0  0  0  0  0 |   8-BIT DISPLACEMENT
205/// -------------------------------------------------
206///  16-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $00
207/// -------------------------------------------------
208///  32-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $FF
209/// -------------------------------------------------
210let isBranch = 1, isTerminator = 1, isBarrier = 1 in
211class MxBra<Operand TARGET, dag disp_8, dag disp_16_32>
212    : MxInst<(outs), (ins TARGET:$dst), "bra\t$dst", []> {
213  let Inst =
214    (ascend
215      (descend 0b0110, 0b0000, disp_8),
216      disp_16_32
217    );
218}
219
220def BRA8  : MxBra<MxBrTarget8,
221                  (operand "$dst", 8, (encoder "encodePCRelImm<8>")), (ascend)>;
222
223def BRA16 : MxBra<MxBrTarget16, (descend 0b0000, 0b0000),
224                  (operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
225
226def : Pat<(br bb:$target), (BRA8 MxBrTarget8:$target)>;
227
228
229//===----------------------------------------------------------------------===//
230// Call
231//===----------------------------------------------------------------------===//
232
233// All calls clobber the non-callee saved registers. %SP is marked as
234// a use to prevent stack-pointer assignments that appear immediately
235// before calls from potentially appearing dead. Uses for argument
236// registers are added manually.
237let Uses = [SP] in
238let isCall = 1 in
239///------------------------------+---------+---------
240/// F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0
241///------------------------------+---------+---------
242/// 0  1  0  0  1  1  1  0  1  0 |  MODE   |   REG
243///------------------------------+---------+---------
244class MxCall<MxOperand LOCOp, MxEncMemOp DST_ENC>
245    : MxInst<(outs), (ins LOCOp:$dst), "jsr\t$dst", []> {
246  let Inst =
247    (ascend
248      (descend 0b0100, 0b1110, 0b10, DST_ENC.EA),
249      DST_ENC.Supplement
250    );
251}
252
253def CALLk : MxCall<MxPCI32, MxEncAddrMode_k<"dst">>;
254def CALLq : MxCall<MxPCD32, MxEncAddrMode_q<"dst">>;
255def CALLb : MxCall<MxAL32,  MxEncAddrMode_abs<"dst", true>>;
256def CALLj : MxCall<MxARI32, MxEncAddrMode_j<"dst">>;
257
258multiclass CallPat<MxCall callOp, Predicate pred> {
259  let Predicates = [pred] in {
260    def : Pat<(MxCall (i32 tglobaladdr:$dst)),  (callOp tglobaladdr:$dst)>;
261    def : Pat<(MxCall (i32 texternalsym:$dst)), (callOp texternalsym:$dst)>;
262    def : Pat<(MxCall (i32 imm:$dst)),          (callOp imm:$dst)>;
263  }
264}
265
266defm : CallPat<CALLq, IsPIC>;
267defm : CallPat<CALLb, IsNotPIC>;
268
269def : Pat<(MxCall iPTR:$dst), (CALLj MxARI32:$dst)>;
270
271//===----------------------------------------------------------------------===//
272// Tail Call
273//===----------------------------------------------------------------------===//
274
275let isCodeGenOnly = 1 in {
276let Uses = [SP] in {
277let isCall = 1, isTerminator = 1, isBarrier = 1 in {
278
279let isReturn = 1 in
280def TCRETURNq : MxPseudo<(outs), (ins MxPCD32:$dst,    i32imm:$adj)>;
281def TAILJMPq  : MxPseudo<(outs), (ins MxPCD32:$dst)>;
282
283// NOTE j does not mean load and jump M68k jmp just calculates EA and jumps
284// and it is using Mem form like (An) thus j letter.
285let isReturn = 1 in
286def TCRETURNj : MxPseudo<(outs), (ins MxARI32_TC:$dst, i32imm:$adj)>;
287def TAILJMPj  : MxPseudo<(outs), (ins MxARI32_TC:$dst)>;
288} // isCall = 1, isTerminator = 1, isBarrier = 1
289} // Uses = [SP]
290} // isCodeGenOnly = 1
291
292//===----------------------------------------------------------------------===//
293// Return
294//===----------------------------------------------------------------------===//
295
296// TODO Implement LINK/UNLK
297
298let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 in {
299
300def RTS : MxInst<(outs), (ins), "rts", []> {
301  let Inst = (descend 0b0100, 0b1110, 0b0111, 0b0101);
302}
303
304let isCodeGenOnly = 1 in
305def RET : MxPseudo<(outs), (ins i32imm:$adj, variable_ops),
306                   [(MxRet timm:$adj)]>;
307} // isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1
308
309//===----------------------------------------------------------------------===//
310// SETCC_C Patterns
311//===----------------------------------------------------------------------===//
312
313// Use subx to materialize carry bit.
314let Uses = [CCR], Defs = [CCR], isPseudo = 1 in {
315// FIXME These are pseudo ops that should be replaced with Pat<> patterns.
316// However, Pat<> can't replicate the destination reg into the inputs of the
317// result.
318def SETCS_C8d : MxPseudo<(outs MxDRD8:$dst), (ins),
319                         [(set MxDRD8:$dst, (MxSetCC_C MxCONDcs, CCR))]>;
320def SETCS_C16d : MxPseudo<(outs MxDRD16:$dst), (ins),
321                          [(set MxDRD16:$dst, (MxSetCC_C MxCONDcs, CCR))]>;
322def SETCS_C32d : MxPseudo<(outs MxXRD32:$dst), (ins),
323                          [(set MxXRD32:$dst, (MxSetCC_C MxCONDcs, CCR))]>;
324} // Uses = [CCR], Defs = [CCR], isPseudo = 1
325
326
327def : Pat<(i16 (anyext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C16d)>;
328def : Pat<(i32 (anyext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C32d)>;
329
330def : Pat<(i16 (sext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C16d)>;
331def : Pat<(i32 (sext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C32d)>;
332
333// We canonicalize 'scs' to "(and (subx reg,reg), 1)" on the hope that the and
334// will be eliminated and that the subx can be extended up to a wider type.  When
335// this happens, it is great.  However, if we are left with an 8-bit subx and an
336// and, we might as well just match it as a setb.
337def : Pat<(and (i8 (MxSetCC_C MxCONDcs, CCR)), 1), (SETd8cs)>;
338
339// (add OP, SETB) -> (addx OP, (move 0))
340def : Pat<(add (and (i8 (MxSetCC_C MxCONDcs, CCR)), 1), MxDRD8:$op),
341          (ADDX8dd MxDRD8:$op, (MOV8di 0))>;
342def : Pat<(add (and (i32 (MxSetCC_C MxCONDcs, CCR)), 1), MxXRD32:$op),
343          (ADDX32dd MxDRD32:$op, (MOV32ri 0))>;
344
345// (sub OP, SETB) -> (subx OP, (move 0))
346def : Pat<(sub MxDRD8:$op, (and (i8 (MxSetCC_C MxCONDcs, CCR)), 1)),
347          (SUBX8dd MxDRD8:$op, (MOV8di 0))>;
348def : Pat<(sub MxXRD32:$op, (and (i32 (MxSetCC_C MxCONDcs, CCR)), 1)),
349          (SUBX32dd MxDRD32:$op, (MOV32ri 0))>;
350
351// (sub OP, SETCC_CARRY) -> (addx OP, (move 0))
352def : Pat<(sub MxDRD8:$op, (i8 (MxSetCC_C MxCONDcs, CCR))),
353          (ADDX8dd MxDRD8:$op, (MOV8di 0))>;
354def : Pat<(sub MxXRD32:$op, (i32 (MxSetCC_C MxCONDcs, CCR))),
355          (ADDX32dd MxDRD32:$op, (MOV32ri 0))>;
356