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, 285 Register VReg) const override; 286 287 void loadRegFromStackSlot(MachineBasicBlock &MBB, 288 MachineBasicBlock::iterator MI, Register DestReg, 289 int FrameIndex, const TargetRegisterClass *RC, 290 const TargetRegisterInfo *TRI, 291 Register VReg) const override; 292 293 bool expandPostRAPseudo(MachineInstr &MI) const override; 294 295 bool isPCRelRegisterOperandLegal(const MachineOperand &MO) const override; 296 297 /// Add appropriate SExt nodes 298 void AddSExt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 299 DebugLoc DL, unsigned Reg, MVT From, MVT To) const; 300 301 /// Add appropriate ZExt nodes 302 void AddZExt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, 303 DebugLoc DL, unsigned Reg, MVT From, MVT To) const; 304 305 /// Move across register classes without extension 306 bool ExpandMOVX_RR(MachineInstrBuilder &MIB, MVT MVTDst, MVT MVTSrc) const; 307 308 /// Move from register and extend 309 bool ExpandMOVSZX_RR(MachineInstrBuilder &MIB, bool IsSigned, MVT MVTDst, 310 MVT MVTSrc) const; 311 312 /// Move from memory and extend 313 bool ExpandMOVSZX_RM(MachineInstrBuilder &MIB, bool IsSigned, 314 const MCInstrDesc &Desc, MVT MVTDst, MVT MVTSrc) const; 315 316 /// Push/Pop to/from stack 317 bool ExpandPUSH_POP(MachineInstrBuilder &MIB, const MCInstrDesc &Desc, 318 bool IsPush) const; 319 320 /// Moves to/from CCR 321 bool ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const; 322 323 /// Expand all MOVEM pseudos into real MOVEMs 324 bool ExpandMOVEM(MachineInstrBuilder &MIB, const MCInstrDesc &Desc, 325 bool IsRM) const; 326 327 /// Return a virtual register initialized with the global base register 328 /// value. Output instructions required to initialize the register in the 329 /// function entry block, if necessary. 330 unsigned getGlobalBaseReg(MachineFunction *MF) const; 331 332 std::pair<unsigned, unsigned> 333 decomposeMachineOperandsTargetFlags(unsigned TF) const override; 334 335 ArrayRef<std::pair<unsigned, const char *>> 336 getSerializableDirectMachineOperandTargetFlags() const override; 337 }; 338 339 } // namespace llvm 340 341 #endif // LLVM_LIB_TARGET_M68K_M68KINSTRINFO_H 342