1 //===-- M68kInstrInfo.h - M68k Instruction Information ----------*- C++ -*-===//
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 contains the M68k implementation of the TargetInstrInfo class.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_LIB_TARGET_M68K_M68KINSTRINFO_H
15 #define LLVM_LIB_TARGET_M68K_M68KINSTRINFO_H
16 
17 #include "M68k.h"
18 #include "M68kRegisterInfo.h"
19 
20 #include "MCTargetDesc/M68kBaseInfo.h"
21 
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/TargetInstrInfo.h"
24 
25 #define GET_INSTRINFO_HEADER
26 #include "M68kGenInstrInfo.inc"
27 
28 namespace llvm {
29 
30 class M68kSubtarget;
31 
32 namespace M68k {
33 // These MUST be kept in sync with codes definitions in M68kInstrInfo.td
34 enum CondCode {
35   COND_T = 0,   // True
36   COND_F = 1,   // False
37   COND_HI = 2,  // High
38   COND_LS = 3,  // Less or Same
39   COND_CC = 4,  // Carry Clear
40   COND_CS = 5,  // Carry Set
41   COND_NE = 6,  // Not Equal
42   COND_EQ = 7,  // Equal
43   COND_VC = 8,  // Overflow Clear
44   COND_VS = 9,  // Overflow Set
45   COND_PL = 10, // Plus
46   COND_MI = 11, // Minus
47   COND_GE = 12, // Greater or Equal
48   COND_LT = 13, // Less Than
49   COND_GT = 14, // Greater Than
50   COND_LE = 15, // Less or Equal
51   LAST_VALID_COND = COND_LE,
52   COND_INVALID
53 };
54 
55 // FIXME would be nice tablegen to generate these predicates and converters
56 // mb tag based
57 
58 static inline M68k::CondCode GetOppositeBranchCondition(M68k::CondCode CC) {
59   switch (CC) {
60   default:
61     llvm_unreachable("Illegal condition code!");
62   case M68k::COND_T:
63     return M68k::COND_F;
64   case M68k::COND_F:
65     return M68k::COND_T;
66   case M68k::COND_HI:
67     return M68k::COND_LS;
68   case M68k::COND_LS:
69     return M68k::COND_HI;
70   case M68k::COND_CC:
71     return M68k::COND_CS;
72   case M68k::COND_CS:
73     return M68k::COND_CC;
74   case M68k::COND_NE:
75     return M68k::COND_EQ;
76   case M68k::COND_EQ:
77     return M68k::COND_NE;
78   case M68k::COND_VC:
79     return M68k::COND_VS;
80   case M68k::COND_VS:
81     return M68k::COND_VC;
82   case M68k::COND_PL:
83     return M68k::COND_MI;
84   case M68k::COND_MI:
85     return M68k::COND_PL;
86   case M68k::COND_GE:
87     return M68k::COND_LT;
88   case M68k::COND_LT:
89     return M68k::COND_GE;
90   case M68k::COND_GT:
91     return M68k::COND_LE;
92   case M68k::COND_LE:
93     return M68k::COND_GT;
94   }
95 }
96 
97 static inline unsigned GetCondBranchFromCond(M68k::CondCode CC) {
98   switch (CC) {
99   default:
100     llvm_unreachable("Illegal condition code!");
101   case M68k::COND_EQ:
102     return M68k::Beq8;
103   case M68k::COND_NE:
104     return M68k::Bne8;
105   case M68k::COND_LT:
106     return M68k::Blt8;
107   case M68k::COND_LE:
108     return M68k::Ble8;
109   case M68k::COND_GT:
110     return M68k::Bgt8;
111   case M68k::COND_GE:
112     return M68k::Bge8;
113   case M68k::COND_CS:
114     return M68k::Bcs8;
115   case M68k::COND_LS:
116     return M68k::Bls8;
117   case M68k::COND_HI:
118     return M68k::Bhi8;
119   case M68k::COND_CC:
120     return M68k::Bcc8;
121   case M68k::COND_MI:
122     return M68k::Bmi8;
123   case M68k::COND_PL:
124     return M68k::Bpl8;
125   case M68k::COND_VS:
126     return M68k::Bvs8;
127   case M68k::COND_VC:
128     return M68k::Bvc8;
129   }
130 }
131 
132 static inline M68k::CondCode GetCondFromBranchOpc(unsigned Opcode) {
133   switch (Opcode) {
134   default:
135     return M68k::COND_INVALID;
136   case M68k::Beq8:
137     return M68k::COND_EQ;
138   case M68k::Bne8:
139     return M68k::COND_NE;
140   case M68k::Blt8:
141     return M68k::COND_LT;
142   case M68k::Ble8:
143     return M68k::COND_LE;
144   case M68k::Bgt8:
145     return M68k::COND_GT;
146   case M68k::Bge8:
147     return M68k::COND_GE;
148   case M68k::Bcs8:
149     return M68k::COND_CS;
150   case M68k::Bls8:
151     return M68k::COND_LS;
152   case M68k::Bhi8:
153     return M68k::COND_HI;
154   case M68k::Bcc8:
155     return M68k::COND_CC;
156   case M68k::Bmi8:
157     return M68k::COND_MI;
158   case M68k::Bpl8:
159     return M68k::COND_PL;
160   case M68k::Bvs8:
161     return M68k::COND_VS;
162   case M68k::Bvc8:
163     return M68k::COND_VC;
164   }
165 }
166 
167 static inline unsigned IsCMP(unsigned Op) {
168   switch (Op) {
169   default:
170     return false;
171   case M68k::CMP8dd:
172   case M68k::CMP8df:
173   case M68k::CMP8di:
174   case M68k::CMP8dj:
175   case M68k::CMP8dp:
176   case M68k::CMP16dr:
177   case M68k::CMP16df:
178   case M68k::CMP16di:
179   case M68k::CMP16dj:
180   case M68k::CMP16dp:
181     return true;
182   }
183 }
184 
185 static inline bool IsSETCC(unsigned SETCC) {
186   switch (SETCC) {
187   default:
188     return false;
189   case M68k::SETd8eq:
190   case M68k::SETd8ne:
191   case M68k::SETd8lt:
192   case M68k::SETd8ge:
193   case M68k::SETd8le:
194   case M68k::SETd8gt:
195   case M68k::SETd8cs:
196   case M68k::SETd8cc:
197   case M68k::SETd8ls:
198   case M68k::SETd8hi:
199   case M68k::SETd8pl:
200   case M68k::SETd8mi:
201   case M68k::SETd8vc:
202   case M68k::SETd8vs:
203   case M68k::SETj8eq:
204   case M68k::SETj8ne:
205   case M68k::SETj8lt:
206   case M68k::SETj8ge:
207   case M68k::SETj8le:
208   case M68k::SETj8gt:
209   case M68k::SETj8cs:
210   case M68k::SETj8cc:
211   case M68k::SETj8ls:
212   case M68k::SETj8hi:
213   case M68k::SETj8pl:
214   case M68k::SETj8mi:
215   case M68k::SETj8vc:
216   case M68k::SETj8vs:
217   case M68k::SETp8eq:
218   case M68k::SETp8ne:
219   case M68k::SETp8lt:
220   case M68k::SETp8ge:
221   case M68k::SETp8le:
222   case M68k::SETp8gt:
223   case M68k::SETp8cs:
224   case M68k::SETp8cc:
225   case M68k::SETp8ls:
226   case M68k::SETp8hi:
227   case M68k::SETp8pl:
228   case M68k::SETp8mi:
229   case M68k::SETp8vc:
230   case M68k::SETp8vs:
231     return true;
232   }
233 }
234 
235 } // namespace M68k
236 
237 class M68kInstrInfo : public M68kGenInstrInfo {
238   virtual void anchor();
239 
240 protected:
241   const M68kSubtarget &Subtarget;
242   const M68kRegisterInfo RI;
243 
244 public:
245   explicit M68kInstrInfo(const M68kSubtarget &STI);
246 
247   static const M68kInstrInfo *create(M68kSubtarget &STI);
248 
249   /// TargetInstrInfo is a superset of MRegister info. As such, whenever a
250   /// client has an instance of instruction info, it should always be able to
251   /// get register info as well (through this method).
252   const M68kRegisterInfo &getRegisterInfo() const { return RI; };
253 
254   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
255                      MachineBasicBlock *&FBB,
256                      SmallVectorImpl<MachineOperand> &Cond,
257                      bool AllowModify) const override;
258 
259   bool AnalyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
260                          MachineBasicBlock *&FBB,
261                          SmallVectorImpl<MachineOperand> &Cond,
262                          bool AllowModify) const;
263 
264   unsigned removeBranch(MachineBasicBlock &MBB,
265                         int *BytesRemoved = nullptr) const override;
266 
267   unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
268                         MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
269                         const DebugLoc &DL,
270                         int *BytesAdded = nullptr) const override;
271 
272   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
273                    const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
274                    bool KillSrc) const override;
275 
276   bool getStackSlotRange(const TargetRegisterClass *RC, unsigned SubIdx,
277                          unsigned &Size, unsigned &Offset,
278                          const MachineFunction &MF) const override;
279 
280   void storeRegToStackSlot(MachineBasicBlock &MBB,
281                            MachineBasicBlock::iterator MI, Register SrcReg,
282                            bool IsKill, int FrameIndex,
283                            const TargetRegisterClass *RC,
284                            const TargetRegisterInfo *TRI) const override;
285 
286   void loadRegFromStackSlot(MachineBasicBlock &MBB,
287                             MachineBasicBlock::iterator MI, Register DestReg,
288                             int FrameIndex, const TargetRegisterClass *RC,
289                             const TargetRegisterInfo *TRI) const override;
290 
291   bool expandPostRAPseudo(MachineInstr &MI) const override;
292 
293   bool isPCRelRegisterOperandLegal(const MachineOperand &MO) const override;
294 
295   /// Add appropriate SExt nodes
296   void AddSExt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
297                DebugLoc DL, unsigned Reg, MVT From, MVT To) const;
298 
299   /// Add appropriate ZExt nodes
300   void AddZExt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
301                DebugLoc DL, unsigned Reg, MVT From, MVT To) const;
302 
303   /// Move across register classes without extension
304   bool ExpandMOVX_RR(MachineInstrBuilder &MIB, MVT MVTDst, MVT MVTSrc) const;
305 
306   /// Move from register and extend
307   bool ExpandMOVSZX_RR(MachineInstrBuilder &MIB, bool IsSigned, MVT MVTDst,
308                        MVT MVTSrc) const;
309 
310   /// Move from memory and extend
311   bool ExpandMOVSZX_RM(MachineInstrBuilder &MIB, bool IsSigned,
312                        const MCInstrDesc &Desc, MVT MVTDst, MVT MVTSrc) const;
313 
314   /// Push/Pop to/from stack
315   bool ExpandPUSH_POP(MachineInstrBuilder &MIB, const MCInstrDesc &Desc,
316                       bool IsPush) const;
317 
318   /// Moves to/from CCR
319   bool ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const;
320 
321   /// Expand all MOVEM pseudos into real MOVEMs
322   bool ExpandMOVEM(MachineInstrBuilder &MIB, const MCInstrDesc &Desc,
323                    bool IsRM) const;
324 
325   /// Return a virtual register initialized with the the global base register
326   /// value. Output instructions required to initialize the register in the
327   /// function entry block, if necessary.
328   unsigned getGlobalBaseReg(MachineFunction *MF) const;
329 
330   std::pair<unsigned, unsigned>
331   decomposeMachineOperandsTargetFlags(unsigned TF) const override;
332 
333   ArrayRef<std::pair<unsigned, const char *>>
334   getSerializableDirectMachineOperandTargetFlags() const override;
335 };
336 
337 } // namespace llvm
338 
339 #endif // LLVM_LIB_TARGET_M68K_M68KINSTRINFO_H
340