forked from OSchip/llvm-project
618 lines
20 KiB
C++
618 lines
20 KiB
C++
//===-- CSKYInstrInfo.h - CSKY 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the CSKY implementation of the TargetInstrInfo class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "CSKYInstrInfo.h"
|
|
#include "CSKYConstantPoolValue.h"
|
|
#include "CSKYMachineFunctionInfo.h"
|
|
#include "CSKYTargetMachine.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
|
|
#define DEBUG_TYPE "csky-instr-info"
|
|
|
|
using namespace llvm;
|
|
|
|
#define GET_INSTRINFO_CTOR_DTOR
|
|
#include "CSKYGenInstrInfo.inc"
|
|
|
|
CSKYInstrInfo::CSKYInstrInfo(CSKYSubtarget &STI)
|
|
: CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN, CSKY::ADJCALLSTACKUP), STI(STI) {
|
|
v2sf = STI.hasFPUv2SingleFloat();
|
|
v2df = STI.hasFPUv2DoubleFloat();
|
|
v3sf = STI.hasFPUv3SingleFloat();
|
|
v3df = STI.hasFPUv3DoubleFloat();
|
|
}
|
|
|
|
static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
|
|
SmallVectorImpl<MachineOperand> &Cond) {
|
|
// Block ends with fall-through condbranch.
|
|
assert(LastInst.getDesc().isConditionalBranch() &&
|
|
"Unknown conditional branch");
|
|
Target = LastInst.getOperand(1).getMBB();
|
|
Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
|
|
Cond.push_back(LastInst.getOperand(0));
|
|
}
|
|
|
|
bool CSKYInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
|
|
MachineBasicBlock *&TBB,
|
|
MachineBasicBlock *&FBB,
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
|
bool AllowModify) const {
|
|
TBB = FBB = nullptr;
|
|
Cond.clear();
|
|
|
|
// If the block has no terminators, it just falls into the block after it.
|
|
MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
|
|
if (I == MBB.end() || !isUnpredicatedTerminator(*I))
|
|
return false;
|
|
|
|
// Count the number of terminators and find the first unconditional or
|
|
// indirect branch.
|
|
MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
|
|
int NumTerminators = 0;
|
|
for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
|
|
J++) {
|
|
NumTerminators++;
|
|
if (J->getDesc().isUnconditionalBranch() ||
|
|
J->getDesc().isIndirectBranch()) {
|
|
FirstUncondOrIndirectBr = J.getReverse();
|
|
}
|
|
}
|
|
|
|
// If AllowModify is true, we can erase any terminators after
|
|
// FirstUncondOrIndirectBR.
|
|
if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
|
|
while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
|
|
std::next(FirstUncondOrIndirectBr)->eraseFromParent();
|
|
NumTerminators--;
|
|
}
|
|
I = FirstUncondOrIndirectBr;
|
|
}
|
|
|
|
// We can't handle blocks that end in an indirect branch.
|
|
if (I->getDesc().isIndirectBranch())
|
|
return true;
|
|
|
|
// We can't handle blocks with more than 2 terminators.
|
|
if (NumTerminators > 2)
|
|
return true;
|
|
|
|
// Handle a single unconditional branch.
|
|
if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
|
|
TBB = getBranchDestBlock(*I);
|
|
return false;
|
|
}
|
|
|
|
// Handle a single conditional branch.
|
|
if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
|
|
parseCondBranch(*I, TBB, Cond);
|
|
return false;
|
|
}
|
|
|
|
// Handle a conditional branch followed by an unconditional branch.
|
|
if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
|
|
I->getDesc().isUnconditionalBranch()) {
|
|
parseCondBranch(*std::prev(I), TBB, Cond);
|
|
FBB = getBranchDestBlock(*I);
|
|
return false;
|
|
}
|
|
|
|
// Otherwise, we can't handle this.
|
|
return true;
|
|
}
|
|
|
|
unsigned CSKYInstrInfo::removeBranch(MachineBasicBlock &MBB,
|
|
int *BytesRemoved) const {
|
|
if (BytesRemoved)
|
|
*BytesRemoved = 0;
|
|
MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
|
|
if (I == MBB.end())
|
|
return 0;
|
|
|
|
if (!I->getDesc().isUnconditionalBranch() &&
|
|
!I->getDesc().isConditionalBranch())
|
|
return 0;
|
|
|
|
// Remove the branch.
|
|
if (BytesRemoved)
|
|
*BytesRemoved += getInstSizeInBytes(*I);
|
|
I->eraseFromParent();
|
|
|
|
I = MBB.end();
|
|
|
|
if (I == MBB.begin())
|
|
return 1;
|
|
--I;
|
|
if (!I->getDesc().isConditionalBranch())
|
|
return 1;
|
|
|
|
// Remove the branch.
|
|
if (BytesRemoved)
|
|
*BytesRemoved += getInstSizeInBytes(*I);
|
|
I->eraseFromParent();
|
|
return 2;
|
|
}
|
|
|
|
MachineBasicBlock *
|
|
CSKYInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
|
|
assert(MI.getDesc().isBranch() && "Unexpected opcode!");
|
|
// The branch target is always the last operand.
|
|
int NumOp = MI.getNumExplicitOperands();
|
|
assert(MI.getOperand(NumOp - 1).isMBB() && "Expected MBB!");
|
|
return MI.getOperand(NumOp - 1).getMBB();
|
|
}
|
|
|
|
unsigned CSKYInstrInfo::insertBranch(
|
|
MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
|
|
ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
|
|
if (BytesAdded)
|
|
*BytesAdded = 0;
|
|
|
|
// Shouldn't be a fall through.
|
|
assert(TBB && "insertBranch must not be told to insert a fallthrough");
|
|
assert((Cond.size() == 2 || Cond.size() == 0) &&
|
|
"CSKY branch conditions have two components!");
|
|
|
|
// Unconditional branch.
|
|
if (Cond.empty()) {
|
|
MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(TBB);
|
|
if (BytesAdded)
|
|
*BytesAdded += getInstSizeInBytes(MI);
|
|
return 1;
|
|
}
|
|
|
|
// Either a one or two-way conditional branch.
|
|
unsigned Opc = Cond[0].getImm();
|
|
MachineInstr &CondMI = *BuildMI(&MBB, DL, get(Opc)).add(Cond[1]).addMBB(TBB);
|
|
if (BytesAdded)
|
|
*BytesAdded += getInstSizeInBytes(CondMI);
|
|
|
|
// One-way conditional branch.
|
|
if (!FBB)
|
|
return 1;
|
|
|
|
// Two-way conditional branch.
|
|
MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(FBB);
|
|
if (BytesAdded)
|
|
*BytesAdded += getInstSizeInBytes(MI);
|
|
return 2;
|
|
}
|
|
|
|
static unsigned getOppositeBranchOpc(unsigned Opcode) {
|
|
switch (Opcode) {
|
|
default:
|
|
llvm_unreachable("Unknown conditional branch!");
|
|
case CSKY::BT32:
|
|
return CSKY::BF32;
|
|
case CSKY::BT16:
|
|
return CSKY::BF16;
|
|
case CSKY::BF32:
|
|
return CSKY::BT32;
|
|
case CSKY::BF16:
|
|
return CSKY::BT16;
|
|
case CSKY::BHZ32:
|
|
return CSKY::BLSZ32;
|
|
case CSKY::BHSZ32:
|
|
return CSKY::BLZ32;
|
|
case CSKY::BLZ32:
|
|
return CSKY::BHSZ32;
|
|
case CSKY::BLSZ32:
|
|
return CSKY::BHZ32;
|
|
case CSKY::BNEZ32:
|
|
return CSKY::BEZ32;
|
|
case CSKY::BEZ32:
|
|
return CSKY::BNEZ32;
|
|
}
|
|
}
|
|
|
|
bool CSKYInstrInfo::reverseBranchCondition(
|
|
SmallVectorImpl<MachineOperand> &Cond) const {
|
|
assert((Cond.size() == 2) && "Invalid branch condition!");
|
|
Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm()));
|
|
return false;
|
|
}
|
|
|
|
Register CSKYInstrInfo::movImm(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MBBI,
|
|
const DebugLoc &DL, uint64_t Val,
|
|
MachineInstr::MIFlag Flag) const {
|
|
if (!isInt<32>(Val))
|
|
report_fatal_error("Should only materialize 32-bit constants.");
|
|
|
|
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
|
|
|
|
Register DstReg;
|
|
if (STI.hasE2()) {
|
|
DstReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
|
|
|
|
if (isUInt<16>(Val)) {
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::MOVI32), DstReg)
|
|
.addImm(Val & 0xFFFF)
|
|
.setMIFlags(Flag);
|
|
} else if (isShiftedUInt<16, 16>(Val)) {
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg)
|
|
.addImm((Val >> 16) & 0xFFFF)
|
|
.setMIFlags(Flag);
|
|
} else {
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg)
|
|
.addImm((Val >> 16) & 0xFFFF)
|
|
.setMIFlags(Flag);
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::ORI32), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm(Val & 0xFFFF)
|
|
.setMIFlags(Flag);
|
|
}
|
|
|
|
} else {
|
|
DstReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);
|
|
if (isUInt<8>(Val)) {
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
|
|
.addImm(Val & 0xFF)
|
|
.setMIFlags(Flag);
|
|
} else if (isUInt<16>(Val)) {
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
|
|
.addImm((Val >> 8) & 0xFF)
|
|
.setMIFlags(Flag);
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm(8)
|
|
.setMIFlags(Flag);
|
|
if ((Val & 0xFF) != 0)
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm(Val & 0xFF)
|
|
.setMIFlags(Flag);
|
|
} else if (isUInt<24>(Val)) {
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
|
|
.addImm((Val >> 16) & 0xFF)
|
|
.setMIFlags(Flag);
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm(8)
|
|
.setMIFlags(Flag);
|
|
if (((Val >> 8) & 0xFF) != 0)
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm((Val >> 8) & 0xFF)
|
|
.setMIFlags(Flag);
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm(8)
|
|
.setMIFlags(Flag);
|
|
if ((Val & 0xFF) != 0)
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm(Val & 0xFF)
|
|
.setMIFlags(Flag);
|
|
} else {
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
|
|
.addImm((Val >> 24) & 0xFF)
|
|
.setMIFlags(Flag);
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm(8)
|
|
.setMIFlags(Flag);
|
|
if (((Val >> 16) & 0xFF) != 0)
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm((Val >> 16) & 0xFF)
|
|
.setMIFlags(Flag);
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm(8)
|
|
.setMIFlags(Flag);
|
|
if (((Val >> 8) & 0xFF) != 0)
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm((Val >> 8) & 0xFF)
|
|
.setMIFlags(Flag);
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm(8)
|
|
.setMIFlags(Flag);
|
|
if ((Val & 0xFF) != 0)
|
|
BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
|
|
.addReg(DstReg)
|
|
.addImm(Val & 0xFF)
|
|
.setMIFlags(Flag);
|
|
}
|
|
}
|
|
|
|
return DstReg;
|
|
}
|
|
|
|
unsigned CSKYInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const {
|
|
switch (MI.getOpcode()) {
|
|
default:
|
|
return 0;
|
|
case CSKY::LD16B:
|
|
case CSKY::LD16H:
|
|
case CSKY::LD16W:
|
|
case CSKY::LD32B:
|
|
case CSKY::LD32BS:
|
|
case CSKY::LD32H:
|
|
case CSKY::LD32HS:
|
|
case CSKY::LD32W:
|
|
case CSKY::FLD_S:
|
|
case CSKY::FLD_D:
|
|
case CSKY::f2FLD_S:
|
|
case CSKY::f2FLD_D:
|
|
case CSKY::RESTORE_CARRY:
|
|
break;
|
|
}
|
|
|
|
if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
|
|
MI.getOperand(2).getImm() == 0) {
|
|
FrameIndex = MI.getOperand(1).getIndex();
|
|
return MI.getOperand(0).getReg();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned CSKYInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const {
|
|
switch (MI.getOpcode()) {
|
|
default:
|
|
return 0;
|
|
case CSKY::ST16B:
|
|
case CSKY::ST16H:
|
|
case CSKY::ST16W:
|
|
case CSKY::ST32B:
|
|
case CSKY::ST32H:
|
|
case CSKY::ST32W:
|
|
case CSKY::FST_S:
|
|
case CSKY::FST_D:
|
|
case CSKY::f2FST_S:
|
|
case CSKY::f2FST_D:
|
|
case CSKY::SPILL_CARRY:
|
|
break;
|
|
}
|
|
|
|
if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
|
|
MI.getOperand(2).getImm() == 0) {
|
|
FrameIndex = MI.getOperand(1).getIndex();
|
|
return MI.getOperand(0).getReg();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CSKYInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I,
|
|
Register SrcReg, bool IsKill, int FI,
|
|
const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI) const {
|
|
DebugLoc DL;
|
|
if (I != MBB.end())
|
|
DL = I->getDebugLoc();
|
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
unsigned Opcode = 0;
|
|
|
|
if (CSKY::GPRRegClass.hasSubClassEq(RC)) {
|
|
Opcode = CSKY::ST32W; // Optimize for 16bit
|
|
} else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {
|
|
Opcode = CSKY::SPILL_CARRY;
|
|
CFI->setSpillsCR();
|
|
} else if (v2sf && CSKY::sFPR32RegClass.hasSubClassEq(RC))
|
|
Opcode = CSKY::FST_S;
|
|
else if (v2df && CSKY::sFPR64RegClass.hasSubClassEq(RC))
|
|
Opcode = CSKY::FST_D;
|
|
else if (v3sf && CSKY::FPR32RegClass.hasSubClassEq(RC))
|
|
Opcode = CSKY::f2FST_S;
|
|
else if (v3df && CSKY::FPR64RegClass.hasSubClassEq(RC))
|
|
Opcode = CSKY::f2FST_D;
|
|
else {
|
|
llvm_unreachable("Unknown RegisterClass");
|
|
}
|
|
|
|
MachineMemOperand *MMO = MF.getMachineMemOperand(
|
|
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
|
|
MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
|
|
|
|
BuildMI(MBB, I, DL, get(Opcode))
|
|
.addReg(SrcReg, getKillRegState(IsKill))
|
|
.addFrameIndex(FI)
|
|
.addImm(0)
|
|
.addMemOperand(MMO);
|
|
}
|
|
|
|
void CSKYInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I,
|
|
Register DestReg, int FI,
|
|
const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI) const {
|
|
DebugLoc DL;
|
|
if (I != MBB.end())
|
|
DL = I->getDebugLoc();
|
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
unsigned Opcode = 0;
|
|
|
|
if (CSKY::GPRRegClass.hasSubClassEq(RC)) {
|
|
Opcode = CSKY::LD32W;
|
|
} else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {
|
|
Opcode = CSKY::RESTORE_CARRY;
|
|
CFI->setSpillsCR();
|
|
} else if (v2sf && CSKY::sFPR32RegClass.hasSubClassEq(RC))
|
|
Opcode = CSKY::FLD_S;
|
|
else if (v2df && CSKY::sFPR64RegClass.hasSubClassEq(RC))
|
|
Opcode = CSKY::FLD_D;
|
|
else if (v3sf && CSKY::FPR32RegClass.hasSubClassEq(RC))
|
|
Opcode = CSKY::f2FLD_S;
|
|
else if (v3df && CSKY::FPR64RegClass.hasSubClassEq(RC))
|
|
Opcode = CSKY::f2FLD_D;
|
|
else {
|
|
llvm_unreachable("Unknown RegisterClass");
|
|
}
|
|
|
|
MachineMemOperand *MMO = MF.getMachineMemOperand(
|
|
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
|
|
MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
|
|
|
|
BuildMI(MBB, I, DL, get(Opcode), DestReg)
|
|
.addFrameIndex(FI)
|
|
.addImm(0)
|
|
.addMemOperand(MMO);
|
|
}
|
|
|
|
void CSKYInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I,
|
|
const DebugLoc &DL, MCRegister DestReg,
|
|
MCRegister SrcReg, bool KillSrc) const {
|
|
if (CSKY::GPRRegClass.contains(SrcReg) &&
|
|
CSKY::CARRYRegClass.contains(DestReg)) {
|
|
if (STI.hasE2()) {
|
|
BuildMI(MBB, I, DL, get(CSKY::BTSTI32), DestReg)
|
|
.addReg(SrcReg, getKillRegState(KillSrc))
|
|
.addImm(0);
|
|
} else {
|
|
assert(SrcReg < CSKY::R8);
|
|
BuildMI(MBB, I, DL, get(CSKY::BTSTI16), DestReg)
|
|
.addReg(SrcReg, getKillRegState(KillSrc))
|
|
.addImm(0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (CSKY::CARRYRegClass.contains(SrcReg) &&
|
|
CSKY::GPRRegClass.contains(DestReg)) {
|
|
|
|
if (STI.hasE2()) {
|
|
BuildMI(MBB, I, DL, get(CSKY::MVC32), DestReg)
|
|
.addReg(SrcReg, getKillRegState(KillSrc));
|
|
} else {
|
|
assert(DestReg < CSKY::R16);
|
|
assert(DestReg < CSKY::R8);
|
|
BuildMI(MBB, I, DL, get(CSKY::MOVI16), DestReg).addImm(0);
|
|
BuildMI(MBB, I, DL, get(CSKY::ADDC16))
|
|
.addReg(DestReg, RegState::Define)
|
|
.addReg(SrcReg, RegState::Define)
|
|
.addReg(DestReg, getKillRegState(true))
|
|
.addReg(DestReg, getKillRegState(true))
|
|
.addReg(SrcReg, getKillRegState(true));
|
|
BuildMI(MBB, I, DL, get(CSKY::BTSTI16))
|
|
.addReg(SrcReg, RegState::Define | getDeadRegState(KillSrc))
|
|
.addReg(DestReg)
|
|
.addImm(0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
unsigned Opcode = 0;
|
|
if (CSKY::GPRRegClass.contains(DestReg, SrcReg))
|
|
Opcode = STI.hasE2() ? CSKY::MOV32 : CSKY::MOV16;
|
|
else if (v2sf && CSKY::sFPR32RegClass.contains(DestReg, SrcReg))
|
|
Opcode = CSKY::FMOV_S;
|
|
else if (v3sf && CSKY::FPR32RegClass.contains(DestReg, SrcReg))
|
|
Opcode = CSKY::f2FMOV_S;
|
|
else if (v2df && CSKY::sFPR64RegClass.contains(DestReg, SrcReg))
|
|
Opcode = CSKY::FMOV_D;
|
|
else if (v3df && CSKY::FPR64RegClass.contains(DestReg, SrcReg))
|
|
Opcode = CSKY::f2FMOV_D;
|
|
else if (v2sf && CSKY::sFPR32RegClass.contains(SrcReg) &&
|
|
CSKY::GPRRegClass.contains(DestReg))
|
|
Opcode = CSKY::FMFVRL;
|
|
else if (v3sf && CSKY::FPR32RegClass.contains(SrcReg) &&
|
|
CSKY::GPRRegClass.contains(DestReg))
|
|
Opcode = CSKY::f2FMFVRL;
|
|
else if (v2df && CSKY::sFPR64RegClass.contains(SrcReg) &&
|
|
CSKY::GPRRegClass.contains(DestReg))
|
|
Opcode = CSKY::FMFVRL_D;
|
|
else if (v3df && CSKY::FPR64RegClass.contains(SrcReg) &&
|
|
CSKY::GPRRegClass.contains(DestReg))
|
|
Opcode = CSKY::f2FMFVRL_D;
|
|
else if (v2sf && CSKY::GPRRegClass.contains(SrcReg) &&
|
|
CSKY::sFPR32RegClass.contains(DestReg))
|
|
Opcode = CSKY::FMTVRL;
|
|
else if (v3sf && CSKY::GPRRegClass.contains(SrcReg) &&
|
|
CSKY::FPR32RegClass.contains(DestReg))
|
|
Opcode = CSKY::f2FMTVRL;
|
|
else if (v2df && CSKY::GPRRegClass.contains(SrcReg) &&
|
|
CSKY::sFPR64RegClass.contains(DestReg))
|
|
Opcode = CSKY::FMTVRL_D;
|
|
else if (v3df && CSKY::GPRRegClass.contains(SrcReg) &&
|
|
CSKY::FPR64RegClass.contains(DestReg))
|
|
Opcode = CSKY::f2FMTVRL_D;
|
|
else {
|
|
LLVM_DEBUG(dbgs() << "src = " << SrcReg << ", dst = " << DestReg);
|
|
LLVM_DEBUG(I->dump());
|
|
llvm_unreachable("Unknown RegisterClass");
|
|
}
|
|
|
|
BuildMI(MBB, I, DL, get(Opcode), DestReg)
|
|
.addReg(SrcReg, getKillRegState(KillSrc));
|
|
}
|
|
|
|
Register CSKYInstrInfo::getGlobalBaseReg(MachineFunction &MF) const {
|
|
CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
|
|
MachineConstantPool *MCP = MF.getConstantPool();
|
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
|
|
Register GlobalBaseReg = CFI->getGlobalBaseReg();
|
|
if (GlobalBaseReg != 0)
|
|
return GlobalBaseReg;
|
|
|
|
// Insert a pseudo instruction to set the GlobalBaseReg into the first
|
|
// MBB of the function
|
|
MachineBasicBlock &FirstMBB = MF.front();
|
|
MachineBasicBlock::iterator MBBI = FirstMBB.begin();
|
|
DebugLoc DL;
|
|
|
|
CSKYConstantPoolValue *CPV = CSKYConstantPoolSymbol::Create(
|
|
Type::getInt32Ty(MF.getFunction().getContext()), "_GLOBAL_OFFSET_TABLE_",
|
|
0, CSKYCP::ADDR);
|
|
|
|
unsigned CPI = MCP->getConstantPoolIndex(CPV, Align(4));
|
|
|
|
MachineMemOperand *MO =
|
|
MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
|
|
MachineMemOperand::MOLoad, 4, Align(4));
|
|
BuildMI(FirstMBB, MBBI, DL, get(CSKY::LRW32), CSKY::R28)
|
|
.addConstantPoolIndex(CPI)
|
|
.addMemOperand(MO);
|
|
|
|
GlobalBaseReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
|
|
BuildMI(FirstMBB, MBBI, DL, get(TargetOpcode::COPY), GlobalBaseReg)
|
|
.addReg(CSKY::R28);
|
|
|
|
CFI->setGlobalBaseReg(GlobalBaseReg);
|
|
return GlobalBaseReg;
|
|
}
|
|
|
|
unsigned CSKYInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
|
|
switch (MI.getOpcode()) {
|
|
default:
|
|
return MI.getDesc().getSize();
|
|
case CSKY::CONSTPOOL_ENTRY:
|
|
return MI.getOperand(2).getImm();
|
|
case CSKY::SPILL_CARRY:
|
|
case CSKY::RESTORE_CARRY:
|
|
case CSKY::PseudoTLSLA32:
|
|
return 8;
|
|
case TargetOpcode::INLINEASM_BR:
|
|
case TargetOpcode::INLINEASM: {
|
|
const MachineFunction *MF = MI.getParent()->getParent();
|
|
const char *AsmStr = MI.getOperand(0).getSymbolName();
|
|
return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
|
|
}
|
|
}
|
|
}
|