xref: /freebsd/contrib/llvm-project/llvm/lib/Target/M68k/M68kInstrControl.td (revision ec0ea6efa1ad229d75c394c1a9b9cac33af2b1d3)
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  [x]     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", [], MxEncFixed<0x4E71>>;
47}
48
49
50//===----------------------------------------------------------------------===//
51// Conditions
52//===----------------------------------------------------------------------===//
53
54/// CC—Carry clear      GE—Greater than or equal
55/// LS—Lower or same    PL—Plus
56/// CS—Carry set        GT—Greater than
57/// LT—Less than        T—Always true*
58/// EQ—Equal            HI—Higher
59/// MI—Minus            VC—Overflow clear
60/// F—Never true*       LE—Less than or equal
61/// NE—Not equal        VS—Overflow set
62///
63/// *Not applicable to the Bcc instructions.
64def MxCCt  : MxBead4Bits<0b0000>;
65def MxCCf  : MxBead4Bits<0b0001>;
66def MxCChi : MxBead4Bits<0b0010>;
67def MxCCls : MxBead4Bits<0b0011>;
68def MxCCcc : MxBead4Bits<0b0100>;
69def MxCCcs : MxBead4Bits<0b0101>;
70def MxCCne : MxBead4Bits<0b0110>;
71def MxCCeq : MxBead4Bits<0b0111>;
72def MxCCvc : MxBead4Bits<0b1000>;
73def MxCCvs : MxBead4Bits<0b1001>;
74def MxCCpl : MxBead4Bits<0b1010>;
75def MxCCmi : MxBead4Bits<0b1011>;
76def MxCCge : MxBead4Bits<0b1100>;
77def MxCClt : MxBead4Bits<0b1101>;
78def MxCCgt : MxBead4Bits<0b1110>;
79def MxCCle : MxBead4Bits<0b1111>;
80
81/// --------------------------------+---------+---------
82///  F  E  D  C | B  A  9  8 | 7  6 | 5  4  3 | 2  1  0
83/// --------------------------------+---------+---------
84///  0  1  0  1 | CONDITION  | 1  1 |   MODE  |   REG
85/// ----------------------------------------------------
86class MxSccEncoding<MxEncEA EA, MxEncExt EXT, MxBead4Bits CC>
87    : MxEncoding<EA.Reg, EA.DA, EA.Mode, MxBead2Bits<0b11>, CC, MxBead4Bits<0b0101>,
88                 EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>;
89
90let Uses = [CCR] in {
91class MxSccR<string CC>
92    : MxInst<(outs MxDRD8:$dst), (ins), "s"#CC#"\t$dst",
93             [(set i8:$dst, (MxSetCC !cast<PatLeaf>("MxCOND"#CC), CCR))],
94             MxSccEncoding<MxEncEAd_0, MxExtEmpty,
95                           !cast<MxBead4Bits>("MxCC"#CC)>>;
96
97class MxSccM<string CC, MxOperand MEMOpd, ComplexPattern MEMPat,
98             MxEncEA EA, MxEncExt EXT>
99    : MxInst<(outs), (ins MEMOpd:$dst), "s"#CC#"\t$dst",
100             [(store (MxSetCC !cast<PatLeaf>("MxCOND"#CC), CCR), MEMPat:$dst)],
101             MxSccEncoding<EA, EXT, !cast<MxBead4Bits>("MxCC"#CC)>>;
102}
103
104foreach cc = [ "cc", "ls", "lt", "eq", "mi", "f", "ne", "ge",
105               "cs", "pl", "gt", "t", "hi", "vc", "le", "vs"] in {
106def SET#"d8"#cc : MxSccR<cc>;
107def SET#"j8"#cc : MxSccM<cc, MxType8.JOp, MxType8.JPat, MxEncEAj_0, MxExtEmpty>;
108def SET#"p8"#cc : MxSccM<cc, MxType8.POp, MxType8.PPat, MxEncEAp_0, MxExtI16_0>;
109}
110
111//===----------------------------------------------------------------------===//
112// Jumps
113//===----------------------------------------------------------------------===//
114
115///------------------------------+---------+---------
116/// F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0
117///------------------------------+---------+---------
118/// 0  1  0  0  1  1  1  0  1  1 |  MODE   |   REG
119///------------------------------+---------+---------
120let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in
121class MxJMP<MxOperand LOCOp, ComplexPattern LOCPat, MxEncEA EA, MxEncExt EXT>
122    : MxInst<(outs), (ins LOCOp:$dst), "jmp\t$dst", [(brind iPTR:$dst)],
123             MxEncoding<EA.Reg, EA.DA, EA.Mode, MxBead2Bits<0b11>,
124                        MxBead4Bits<0b1110>, MxBead4Bits<0b0100>,
125                        EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>;
126
127def JMP32j : MxJMP<MxARI32, MxCP_ARI, MxEncEAj_0, MxExtEmpty>;
128
129
130// FIXME Support 16 bit indirect jump.
131// Currently M68k does not allow 16 bit indirect jumps use sext operands
132// def JMP16r     : MxInst<(outs), (ins M68k_ARI16:$dst),
133//                             "jmp\t$dst",
134//                             [(brind AR16:$dst)]>;
135
136//===----------------------------------------------------------------------===//
137// Branches
138//===----------------------------------------------------------------------===//
139
140/// --------------------------------------------------
141///  F  E  D  C | B  A  9  8 | 7  6  5  4  3  2  1  0
142/// --------------------------------------------------
143///  0  1  1  0 | CONDITION |   8-BIT DISPLACEMENT
144/// --------------------------------------------------
145///  16-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $00
146/// --------------------------------------------------
147///  32-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $FF
148/// --------------------------------------------------
149let isBranch = 1, isTerminator = 1, Uses = [CCR] in
150class MxBcc<string cc, Operand TARGET, MxType TYPE, MxEncoding ENC = MxEncEmpty>
151    : MxInst<(outs), (ins TARGET:$dst), "b"#cc#"\t$dst", [], ENC>;
152
153foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
154               "cs", "pl", "gt", "hi", "vc", "le", "vs"] in {
155  def B#cc#"8"
156    : MxBcc<cc, MxBrTarget8, MxType8,
157            MxEncoding<MxBead8Disp<0>,
158                       !cast<MxBead4Bits>("MxCC"#cc), MxBead4Bits<0x6>>>;
159  def B#cc#"16"
160    : MxBcc<cc, MxBrTarget16, MxType16,
161            MxEncoding<MxBead4Bits<0x0>,
162                       MxBead4Bits<0x0>, !cast<MxBead4Bits>("MxCC"#cc),
163                       MxBead4Bits<0x6>, MxBead16Imm<0>>>;
164}
165
166foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
167               "cs", "pl", "gt", "hi", "vc", "le", "vs"] in {
168def : Pat<(MxBrCond bb:$target, !cast<PatLeaf>("MxCOND"#cc), CCR),
169          (!cast<Instruction>("B"#cc#"8") MxBrTarget8:$target)>;
170}
171
172/// -------------------------------------------------
173///  F  E  D  C  B  A  9  8 | 7  6  5  4  3  2  1  0
174/// -------------------------------------------------
175///  0  1  1  0  0  0  0  0 |   8-BIT DISPLACEMENT
176/// -------------------------------------------------
177///  16-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $00
178/// -------------------------------------------------
179///  32-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $FF
180/// -------------------------------------------------
181let isBranch = 1, isTerminator = 1, isBarrier=1 in
182class MxBra<Operand TARGET, MxType TYPE, MxEncoding ENC = MxEncEmpty>
183    : MxInst<(outs), (ins TARGET:$dst), "bra\t$dst", [], ENC>;
184
185def BRA8  : MxBra<MxBrTarget8, MxType8,
186                  MxEncoding<MxBead8Disp<0>, MxBead4Bits<0x0>,
187                             MxBead4Bits<0x6>>>;
188def BRA16 : MxBra<MxBrTarget16, MxType16,
189                  MxEncoding<MxBead4Bits<0x0>, MxBead4Bits<0x0>,
190                             MxBead4Bits<0x0>, MxBead4Bits<0x6>,
191                             MxBead16Imm<0>>>;
192
193def : Pat<(br bb:$target), (BRA8 MxBrTarget8:$target)>;
194
195
196//===----------------------------------------------------------------------===//
197// Call
198//===----------------------------------------------------------------------===//
199
200// All calls clobber the non-callee saved registers. %SP is marked as
201// a use to prevent stack-pointer assignments that appear immediately
202// before calls from potentially appearing dead. Uses for argument
203// registers are added manually.
204let Uses = [SP] in
205let isCall = 1 in
206///------------------------------+---------+---------
207/// F  E  D  C  B  A  9  8  7  6 | 5  4  3 | 2  1  0
208///------------------------------+---------+---------
209/// 0  1  0  0  1  1  1  0  1  0 |  MODE   |   REG
210///------------------------------+---------+---------
211class MxCall<MxOperand LOCOp, MxEncEA EA, MxEncExt EXT>
212    : MxInst<(outs), (ins LOCOp:$dst), "jsr\t$dst", [],
213             MxEncoding<EA.Reg, EA.DA, EA.Mode, MxBead2Bits<0b10>,
214                        MxBead4Bits<0b1110>, MxBead4Bits<0b0100>,
215                        EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>;
216
217def CALLk : MxCall<MxPCI32, MxEncEAk,   MxExtBrief_0>;
218def CALLq : MxCall<MxPCD32, MxEncEAq,   MxExtI16_0>;
219def CALLb : MxCall<MxAL32,  MxEncEAb,   MxExtI32_0>;
220def CALLj : MxCall<MxARI32, MxEncEAj_0, MxExtEmpty>;
221
222multiclass CallPat<MxCall callOp, Predicate pred> {
223  let Predicates = [pred] in {
224    def : Pat<(MxCall (i32 tglobaladdr:$dst)),  (callOp tglobaladdr:$dst)>;
225    def : Pat<(MxCall (i32 texternalsym:$dst)), (callOp texternalsym:$dst)>;
226    def : Pat<(MxCall (i32 imm:$dst)),          (callOp imm:$dst)>;
227  }
228}
229
230defm : CallPat<CALLq, IsPIC>;
231defm : CallPat<CALLb, IsNotPIC>;
232
233def : Pat<(MxCall iPTR:$dst), (CALLj MxARI32:$dst)>;
234
235//===----------------------------------------------------------------------===//
236// Tail Call
237//===----------------------------------------------------------------------===//
238
239let isCodeGenOnly = 1 in {
240let Uses = [SP] in {
241let isCall = 1, isTerminator = 1, isBarrier = 1 in {
242
243let isReturn = 1 in
244def TCRETURNq : MxPseudo<(outs), (ins MxPCD32:$dst,    i32imm:$adj)>;
245def TAILJMPq  : MxPseudo<(outs), (ins MxPCD32:$dst)>;
246
247// NOTE j does not mean load and jump M68k jmp just calculates EA and jumps
248// and it is using Mem form like (An) thus j letter.
249let isReturn = 1 in
250def TCRETURNj : MxPseudo<(outs), (ins MxARI32_TC:$dst, i32imm:$adj)>;
251def TAILJMPj  : MxPseudo<(outs), (ins MxARI32_TC:$dst)>;
252} // isCall = 1, isTerminator = 1, isBarrier = 1
253} // Uses = [SP]
254} // isCodeGenOnly = 1
255
256//===----------------------------------------------------------------------===//
257// Return
258//===----------------------------------------------------------------------===//
259
260// TODO Implement LINK/UNLK
261
262let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 in {
263
264def RTS : MxInst<(outs), (ins), "rts", [], MxEncFixed<0x4E75>>;
265
266let isCodeGenOnly = 1 in
267def RET : MxPseudo<(outs), (ins i32imm:$adj, variable_ops),
268                   [(MxRet timm:$adj)]>;
269} // isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1
270
271//===----------------------------------------------------------------------===//
272// SETCC_C Patterns
273//===----------------------------------------------------------------------===//
274
275// Use subx to materialize carry bit.
276let Uses = [CCR], Defs = [CCR], isPseudo = 1 in {
277// FIXME These are pseudo ops that should be replaced with Pat<> patterns.
278// However, Pat<> can't replicate the destination reg into the inputs of the
279// result.
280def SETCS_C8d : MxPseudo<(outs MxDRD8:$dst), (ins),
281                         [(set MxDRD8:$dst, (MxSetCC_C MxCONDcs, CCR))]>;
282def SETCS_C16d : MxPseudo<(outs MxDRD16:$dst), (ins),
283                          [(set MxDRD16:$dst, (MxSetCC_C MxCONDcs, CCR))]>;
284def SETCS_C32d : MxPseudo<(outs MxXRD32:$dst), (ins),
285                          [(set MxXRD32:$dst, (MxSetCC_C MxCONDcs, CCR))]>;
286} // Uses = [CCR], Defs = [CCR], isPseudo = 1
287
288
289def : Pat<(i16 (anyext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C16d)>;
290def : Pat<(i32 (anyext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C32d)>;
291
292def : Pat<(i16 (sext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C16d)>;
293def : Pat<(i32 (sext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C32d)>;
294
295// We canonicalize 'scs' to "(and (subx reg,reg), 1)" on the hope that the and
296// will be eliminated and that the subx can be extended up to a wider type.  When
297// this happens, it is great.  However, if we are left with an 8-bit subx and an
298// and, we might as well just match it as a setb.
299def : Pat<(and (i8 (MxSetCC_C MxCONDcs, CCR)), 1), (SETd8cs)>;
300
301// (add OP, SETB) -> (addx OP, (move 0))
302def : Pat<(add (and (i8 (MxSetCC_C MxCONDcs, CCR)), 1), MxDRD8:$op),
303          (ADDX8dd MxDRD8:$op, (MOV8di 0))>;
304def : Pat<(add (and (i32 (MxSetCC_C MxCONDcs, CCR)), 1), MxXRD32:$op),
305          (ADDX32dd MxDRD32:$op, (MOV32ri 0))>;
306
307// (sub OP, SETB) -> (subx OP, (move 0))
308def : Pat<(sub MxDRD8:$op, (and (i8 (MxSetCC_C MxCONDcs, CCR)), 1)),
309          (SUBX8dd MxDRD8:$op, (MOV8di 0))>;
310def : Pat<(sub MxXRD32:$op, (and (i32 (MxSetCC_C MxCONDcs, CCR)), 1)),
311          (SUBX32dd MxDRD32:$op, (MOV32ri 0))>;
312
313// (sub OP, SETCC_CARRY) -> (addx OP, (move 0))
314def : Pat<(sub MxDRD8:$op, (i8 (MxSetCC_C MxCONDcs, CCR))),
315          (ADDX8dd MxDRD8:$op, (MOV8di 0))>;
316def : Pat<(sub MxXRD32:$op, (i32 (MxSetCC_C MxCONDcs, CCR))),
317          (ADDX32dd MxDRD32:$op, (MOV32ri 0))>;
318