forked from OSchip/llvm-project
340 lines
9.5 KiB
C++
340 lines
9.5 KiB
C++
//===-- M68kInstrInfo.h - M68k Instruction Information ----------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This file contains the M68k implementation of the TargetInstrInfo class.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_TARGET_M68K_M68KINSTRINFO_H
|
|
#define LLVM_LIB_TARGET_M68K_M68KINSTRINFO_H
|
|
|
|
#include "M68k.h"
|
|
#include "M68kRegisterInfo.h"
|
|
|
|
#include "MCTargetDesc/M68kBaseInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
|
|
|
#define GET_INSTRINFO_HEADER
|
|
#include "M68kGenInstrInfo.inc"
|
|
|
|
namespace llvm {
|
|
|
|
class M68kSubtarget;
|
|
|
|
namespace M68k {
|
|
// These MUST be kept in sync with codes definitions in M68kInstrInfo.td
|
|
enum CondCode {
|
|
COND_T = 0, // True
|
|
COND_F = 1, // False
|
|
COND_HI = 2, // High
|
|
COND_LS = 3, // Less or Same
|
|
COND_CC = 4, // Carry Clear
|
|
COND_CS = 5, // Carry Set
|
|
COND_NE = 6, // Not Equal
|
|
COND_EQ = 7, // Equal
|
|
COND_VC = 8, // Overflow Clear
|
|
COND_VS = 9, // Overflow Set
|
|
COND_PL = 10, // Plus
|
|
COND_MI = 11, // Minus
|
|
COND_GE = 12, // Greater or Equal
|
|
COND_LT = 13, // Less Than
|
|
COND_GT = 14, // Greater Than
|
|
COND_LE = 15, // Less or Equal
|
|
LAST_VALID_COND = COND_LE,
|
|
COND_INVALID
|
|
};
|
|
|
|
// FIXME would be nice tablegen to generate these predicates and converters
|
|
// mb tag based
|
|
|
|
static inline M68k::CondCode GetOppositeBranchCondition(M68k::CondCode CC) {
|
|
switch (CC) {
|
|
default:
|
|
llvm_unreachable("Illegal condition code!");
|
|
case M68k::COND_T:
|
|
return M68k::COND_F;
|
|
case M68k::COND_F:
|
|
return M68k::COND_T;
|
|
case M68k::COND_HI:
|
|
return M68k::COND_LS;
|
|
case M68k::COND_LS:
|
|
return M68k::COND_HI;
|
|
case M68k::COND_CC:
|
|
return M68k::COND_CS;
|
|
case M68k::COND_CS:
|
|
return M68k::COND_CC;
|
|
case M68k::COND_NE:
|
|
return M68k::COND_EQ;
|
|
case M68k::COND_EQ:
|
|
return M68k::COND_NE;
|
|
case M68k::COND_VC:
|
|
return M68k::COND_VS;
|
|
case M68k::COND_VS:
|
|
return M68k::COND_VC;
|
|
case M68k::COND_PL:
|
|
return M68k::COND_MI;
|
|
case M68k::COND_MI:
|
|
return M68k::COND_PL;
|
|
case M68k::COND_GE:
|
|
return M68k::COND_LT;
|
|
case M68k::COND_LT:
|
|
return M68k::COND_GE;
|
|
case M68k::COND_GT:
|
|
return M68k::COND_LE;
|
|
case M68k::COND_LE:
|
|
return M68k::COND_GT;
|
|
}
|
|
}
|
|
|
|
static inline unsigned GetCondBranchFromCond(M68k::CondCode CC) {
|
|
switch (CC) {
|
|
default:
|
|
llvm_unreachable("Illegal condition code!");
|
|
case M68k::COND_EQ:
|
|
return M68k::Beq8;
|
|
case M68k::COND_NE:
|
|
return M68k::Bne8;
|
|
case M68k::COND_LT:
|
|
return M68k::Blt8;
|
|
case M68k::COND_LE:
|
|
return M68k::Ble8;
|
|
case M68k::COND_GT:
|
|
return M68k::Bgt8;
|
|
case M68k::COND_GE:
|
|
return M68k::Bge8;
|
|
case M68k::COND_CS:
|
|
return M68k::Bcs8;
|
|
case M68k::COND_LS:
|
|
return M68k::Bls8;
|
|
case M68k::COND_HI:
|
|
return M68k::Bhi8;
|
|
case M68k::COND_CC:
|
|
return M68k::Bcc8;
|
|
case M68k::COND_MI:
|
|
return M68k::Bmi8;
|
|
case M68k::COND_PL:
|
|
return M68k::Bpl8;
|
|
case M68k::COND_VS:
|
|
return M68k::Bvs8;
|
|
case M68k::COND_VC:
|
|
return M68k::Bvc8;
|
|
}
|
|
}
|
|
|
|
static inline M68k::CondCode GetCondFromBranchOpc(unsigned Opcode) {
|
|
switch (Opcode) {
|
|
default:
|
|
return M68k::COND_INVALID;
|
|
case M68k::Beq8:
|
|
return M68k::COND_EQ;
|
|
case M68k::Bne8:
|
|
return M68k::COND_NE;
|
|
case M68k::Blt8:
|
|
return M68k::COND_LT;
|
|
case M68k::Ble8:
|
|
return M68k::COND_LE;
|
|
case M68k::Bgt8:
|
|
return M68k::COND_GT;
|
|
case M68k::Bge8:
|
|
return M68k::COND_GE;
|
|
case M68k::Bcs8:
|
|
return M68k::COND_CS;
|
|
case M68k::Bls8:
|
|
return M68k::COND_LS;
|
|
case M68k::Bhi8:
|
|
return M68k::COND_HI;
|
|
case M68k::Bcc8:
|
|
return M68k::COND_CC;
|
|
case M68k::Bmi8:
|
|
return M68k::COND_MI;
|
|
case M68k::Bpl8:
|
|
return M68k::COND_PL;
|
|
case M68k::Bvs8:
|
|
return M68k::COND_VS;
|
|
case M68k::Bvc8:
|
|
return M68k::COND_VC;
|
|
}
|
|
}
|
|
|
|
static inline unsigned IsCMP(unsigned Op) {
|
|
switch (Op) {
|
|
default:
|
|
return false;
|
|
case M68k::CMP8dd:
|
|
case M68k::CMP8df:
|
|
case M68k::CMP8di:
|
|
case M68k::CMP8dj:
|
|
case M68k::CMP8dp:
|
|
case M68k::CMP16dr:
|
|
case M68k::CMP16df:
|
|
case M68k::CMP16di:
|
|
case M68k::CMP16dj:
|
|
case M68k::CMP16dp:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
static inline bool IsSETCC(unsigned SETCC) {
|
|
switch (SETCC) {
|
|
default:
|
|
return false;
|
|
case M68k::SETd8eq:
|
|
case M68k::SETd8ne:
|
|
case M68k::SETd8lt:
|
|
case M68k::SETd8ge:
|
|
case M68k::SETd8le:
|
|
case M68k::SETd8gt:
|
|
case M68k::SETd8cs:
|
|
case M68k::SETd8cc:
|
|
case M68k::SETd8ls:
|
|
case M68k::SETd8hi:
|
|
case M68k::SETd8pl:
|
|
case M68k::SETd8mi:
|
|
case M68k::SETd8vc:
|
|
case M68k::SETd8vs:
|
|
case M68k::SETj8eq:
|
|
case M68k::SETj8ne:
|
|
case M68k::SETj8lt:
|
|
case M68k::SETj8ge:
|
|
case M68k::SETj8le:
|
|
case M68k::SETj8gt:
|
|
case M68k::SETj8cs:
|
|
case M68k::SETj8cc:
|
|
case M68k::SETj8ls:
|
|
case M68k::SETj8hi:
|
|
case M68k::SETj8pl:
|
|
case M68k::SETj8mi:
|
|
case M68k::SETj8vc:
|
|
case M68k::SETj8vs:
|
|
case M68k::SETp8eq:
|
|
case M68k::SETp8ne:
|
|
case M68k::SETp8lt:
|
|
case M68k::SETp8ge:
|
|
case M68k::SETp8le:
|
|
case M68k::SETp8gt:
|
|
case M68k::SETp8cs:
|
|
case M68k::SETp8cc:
|
|
case M68k::SETp8ls:
|
|
case M68k::SETp8hi:
|
|
case M68k::SETp8pl:
|
|
case M68k::SETp8mi:
|
|
case M68k::SETp8vc:
|
|
case M68k::SETp8vs:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
} // namespace M68k
|
|
|
|
class M68kInstrInfo : public M68kGenInstrInfo {
|
|
virtual void anchor();
|
|
|
|
protected:
|
|
const M68kSubtarget &Subtarget;
|
|
const M68kRegisterInfo RI;
|
|
|
|
public:
|
|
explicit M68kInstrInfo(const M68kSubtarget &STI);
|
|
|
|
static const M68kInstrInfo *create(M68kSubtarget &STI);
|
|
|
|
/// TargetInstrInfo is a superset of MRegister info. As such, whenever a
|
|
/// client has an instance of instruction info, it should always be able to
|
|
/// get register info as well (through this method).
|
|
const M68kRegisterInfo &getRegisterInfo() const { return RI; };
|
|
|
|
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
|
MachineBasicBlock *&FBB,
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
|
bool AllowModify) const override;
|
|
|
|
bool AnalyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
|
MachineBasicBlock *&FBB,
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
|
bool AllowModify) const;
|
|
|
|
unsigned removeBranch(MachineBasicBlock &MBB,
|
|
int *BytesRemoved = nullptr) const override;
|
|
|
|
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
|
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
|
|
const DebugLoc &DL,
|
|
int *BytesAdded = nullptr) const override;
|
|
|
|
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
|
const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
|
|
bool KillSrc) const override;
|
|
|
|
bool getStackSlotRange(const TargetRegisterClass *RC, unsigned SubIdx,
|
|
unsigned &Size, unsigned &Offset,
|
|
const MachineFunction &MF) const override;
|
|
|
|
void storeRegToStackSlot(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MI, Register SrcReg,
|
|
bool IsKill, int FrameIndex,
|
|
const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI) const override;
|
|
|
|
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MI, Register DestReg,
|
|
int FrameIndex, const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI) const override;
|
|
|
|
bool expandPostRAPseudo(MachineInstr &MI) const override;
|
|
|
|
bool isPCRelRegisterOperandLegal(const MachineOperand &MO) const override;
|
|
|
|
/// Add appropriate SExt nodes
|
|
void AddSExt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
|
DebugLoc DL, unsigned Reg, MVT From, MVT To) const;
|
|
|
|
/// Add appropriate ZExt nodes
|
|
void AddZExt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
|
DebugLoc DL, unsigned Reg, MVT From, MVT To) const;
|
|
|
|
/// Move across register classes without extension
|
|
bool ExpandMOVX_RR(MachineInstrBuilder &MIB, MVT MVTDst, MVT MVTSrc) const;
|
|
|
|
/// Move from register and extend
|
|
bool ExpandMOVSZX_RR(MachineInstrBuilder &MIB, bool IsSigned, MVT MVTDst,
|
|
MVT MVTSrc) const;
|
|
|
|
/// Move from memory and extend
|
|
bool ExpandMOVSZX_RM(MachineInstrBuilder &MIB, bool IsSigned,
|
|
const MCInstrDesc &Desc, MVT MVTDst, MVT MVTSrc) const;
|
|
|
|
/// Push/Pop to/from stack
|
|
bool ExpandPUSH_POP(MachineInstrBuilder &MIB, const MCInstrDesc &Desc,
|
|
bool IsPush) const;
|
|
|
|
/// Moves to/from CCR
|
|
bool ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const;
|
|
|
|
/// Expand all MOVEM pseudos into real MOVEMs
|
|
bool ExpandMOVEM(MachineInstrBuilder &MIB, const MCInstrDesc &Desc,
|
|
bool IsRM) const;
|
|
|
|
/// Return a virtual register initialized with the the global base register
|
|
/// value. Output instructions required to initialize the register in the
|
|
/// function entry block, if necessary.
|
|
unsigned getGlobalBaseReg(MachineFunction *MF) const;
|
|
|
|
std::pair<unsigned, unsigned>
|
|
decomposeMachineOperandsTargetFlags(unsigned TF) const override;
|
|
|
|
ArrayRef<std::pair<unsigned, const char *>>
|
|
getSerializableDirectMachineOperandTargetFlags() const override;
|
|
};
|
|
|
|
} // namespace llvm
|
|
|
|
#endif // LLVM_LIB_TARGET_M68K_M68KINSTRINFO_H
|