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