mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-12 14:17:59 +00:00
b1058310c1
Summary: Previous behaviour of 'R' and 'm' has been preserved for now. They will be improved in subsequent commits. The offset permitted by ZC varies according to the subtarget since it is intended to match the restrictions of the pref, ll, and sc instructions. The restrictions on these instructions are: * For microMIPS: 12-bit signed offset. * For Mips32r6/Mips64r6: 9-bit signed offset. * Otherwise: 16-bit signed offset. Reviewers: vkalintiris Reviewed By: vkalintiris Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D8414 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233063 91177308-0d34-0410-b5e6-96231b3b80d8
248 lines
7.6 KiB
C++
248 lines
7.6 KiB
C++
//===-- MipsISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips --------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines an instruction selector for the MIPS target.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MipsISelDAGToDAG.h"
|
|
#include "MCTargetDesc/MipsBaseInfo.h"
|
|
#include "Mips.h"
|
|
#include "Mips16ISelDAGToDAG.h"
|
|
#include "MipsMachineFunction.h"
|
|
#include "MipsRegisterInfo.h"
|
|
#include "MipsSEISelDAGToDAG.h"
|
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
|
#include "llvm/IR/CFG.h"
|
|
#include "llvm/IR/GlobalValue.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/Intrinsics.h"
|
|
#include "llvm/IR/Type.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "mips-isel"
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Instruction Selector Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MipsDAGToDAGISel - MIPS specific code to select MIPS machine
|
|
// instructions for SelectionDAG operations.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool MipsDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
|
|
Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget());
|
|
bool Ret = SelectionDAGISel::runOnMachineFunction(MF);
|
|
|
|
processFunctionAfterISel(MF);
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/// getGlobalBaseReg - Output the instructions required to put the
|
|
/// GOT address into a register.
|
|
SDNode *MipsDAGToDAGISel::getGlobalBaseReg() {
|
|
unsigned GlobalBaseReg = MF->getInfo<MipsFunctionInfo>()->getGlobalBaseReg();
|
|
return CurDAG->getRegister(GlobalBaseReg,
|
|
getTargetLowering()->getPointerTy()).getNode();
|
|
}
|
|
|
|
/// ComplexPattern used on MipsInstrInfo
|
|
/// Used on Mips Load/Store instructions
|
|
bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
|
|
SDValue &Offset) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectAddrRegReg(SDValue Addr, SDValue &Base,
|
|
SDValue &Offset) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base,
|
|
SDValue &Offset) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base,
|
|
SDValue &Offset) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
|
|
SDValue &Offset) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
|
|
SDValue &Offset) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base,
|
|
SDValue &Offset) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
|
|
SDValue &Offset, SDValue &Alias) {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatUimm1(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatUimm2(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
|
|
llvm_unreachable("Unimplemented function.");
|
|
return false;
|
|
}
|
|
|
|
/// Select instructions not customized! Used for
|
|
/// expanded, promoted and normal instructions
|
|
SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
|
|
unsigned Opcode = Node->getOpcode();
|
|
|
|
// Dump information about the Node being selected
|
|
DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");
|
|
|
|
// If we have a custom node, we already have selected!
|
|
if (Node->isMachineOpcode()) {
|
|
DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
|
|
Node->setNodeId(-1);
|
|
return nullptr;
|
|
}
|
|
|
|
// See if subclasses can handle this node.
|
|
std::pair<bool, SDNode*> Ret = selectNode(Node);
|
|
|
|
if (Ret.first)
|
|
return Ret.second;
|
|
|
|
switch(Opcode) {
|
|
default: break;
|
|
|
|
// Get target GOT address.
|
|
case ISD::GLOBAL_OFFSET_TABLE:
|
|
return getGlobalBaseReg();
|
|
|
|
#ifndef NDEBUG
|
|
case ISD::LOAD:
|
|
case ISD::STORE:
|
|
assert((Subtarget->systemSupportsUnalignedAccess() ||
|
|
cast<MemSDNode>(Node)->getMemoryVT().getSizeInBits() / 8 <=
|
|
cast<MemSDNode>(Node)->getAlignment()) &&
|
|
"Unexpected unaligned loads/stores.");
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
// Select the default instruction
|
|
SDNode *ResNode = SelectCode(Node);
|
|
|
|
DEBUG(errs() << "=> ");
|
|
if (ResNode == nullptr || ResNode == Node)
|
|
DEBUG(Node->dump(CurDAG));
|
|
else
|
|
DEBUG(ResNode->dump(CurDAG));
|
|
DEBUG(errs() << "\n");
|
|
return ResNode;
|
|
}
|
|
|
|
bool MipsDAGToDAGISel::
|
|
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
|
|
std::vector<SDValue> &OutOps) {
|
|
// All memory constraints can at least accept raw pointers.
|
|
switch(ConstraintID) {
|
|
default:
|
|
llvm_unreachable("Unexpected asm memory constraint");
|
|
case InlineAsm::Constraint_i:
|
|
case InlineAsm::Constraint_m:
|
|
case InlineAsm::Constraint_R:
|
|
case InlineAsm::Constraint_ZC:
|
|
OutOps.push_back(Op);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|