1349cc55cSDimitry Andric //===-- CSKYInstrInfo.h - CSKY Instruction Information --------*- C++ -*---===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric //
9349cc55cSDimitry Andric // This file contains the CSKY implementation of the TargetInstrInfo class.
10349cc55cSDimitry Andric //
11349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
12349cc55cSDimitry Andric
13349cc55cSDimitry Andric #include "CSKYInstrInfo.h"
1404eeddc0SDimitry Andric #include "CSKYConstantPoolValue.h"
150eae32dcSDimitry Andric #include "CSKYMachineFunctionInfo.h"
160eae32dcSDimitry Andric #include "CSKYTargetMachine.h"
1781ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
18349cc55cSDimitry Andric #include "llvm/MC/MCContext.h"
19349cc55cSDimitry Andric
20349cc55cSDimitry Andric #define DEBUG_TYPE "csky-instr-info"
21349cc55cSDimitry Andric
22349cc55cSDimitry Andric using namespace llvm;
23349cc55cSDimitry Andric
24349cc55cSDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
25349cc55cSDimitry Andric #include "CSKYGenInstrInfo.inc"
26349cc55cSDimitry Andric
CSKYInstrInfo(CSKYSubtarget & STI)27349cc55cSDimitry Andric CSKYInstrInfo::CSKYInstrInfo(CSKYSubtarget &STI)
28349cc55cSDimitry Andric : CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN, CSKY::ADJCALLSTACKUP), STI(STI) {
2904eeddc0SDimitry Andric v2sf = STI.hasFPUv2SingleFloat();
3004eeddc0SDimitry Andric v2df = STI.hasFPUv2DoubleFloat();
3104eeddc0SDimitry Andric v3sf = STI.hasFPUv3SingleFloat();
3204eeddc0SDimitry Andric v3df = STI.hasFPUv3DoubleFloat();
3304eeddc0SDimitry Andric }
3404eeddc0SDimitry Andric
parseCondBranch(MachineInstr & LastInst,MachineBasicBlock * & Target,SmallVectorImpl<MachineOperand> & Cond)3504eeddc0SDimitry Andric static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
3604eeddc0SDimitry Andric SmallVectorImpl<MachineOperand> &Cond) {
3704eeddc0SDimitry Andric // Block ends with fall-through condbranch.
3804eeddc0SDimitry Andric assert(LastInst.getDesc().isConditionalBranch() &&
3904eeddc0SDimitry Andric "Unknown conditional branch");
4004eeddc0SDimitry Andric Target = LastInst.getOperand(1).getMBB();
4104eeddc0SDimitry Andric Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
4204eeddc0SDimitry Andric Cond.push_back(LastInst.getOperand(0));
4304eeddc0SDimitry Andric }
4404eeddc0SDimitry Andric
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const4504eeddc0SDimitry Andric bool CSKYInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
4604eeddc0SDimitry Andric MachineBasicBlock *&TBB,
4704eeddc0SDimitry Andric MachineBasicBlock *&FBB,
4804eeddc0SDimitry Andric SmallVectorImpl<MachineOperand> &Cond,
4904eeddc0SDimitry Andric bool AllowModify) const {
5004eeddc0SDimitry Andric TBB = FBB = nullptr;
5104eeddc0SDimitry Andric Cond.clear();
5204eeddc0SDimitry Andric
5304eeddc0SDimitry Andric // If the block has no terminators, it just falls into the block after it.
5404eeddc0SDimitry Andric MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
5504eeddc0SDimitry Andric if (I == MBB.end() || !isUnpredicatedTerminator(*I))
5604eeddc0SDimitry Andric return false;
5704eeddc0SDimitry Andric
5804eeddc0SDimitry Andric // Count the number of terminators and find the first unconditional or
5904eeddc0SDimitry Andric // indirect branch.
6004eeddc0SDimitry Andric MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
6104eeddc0SDimitry Andric int NumTerminators = 0;
6204eeddc0SDimitry Andric for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
6304eeddc0SDimitry Andric J++) {
6404eeddc0SDimitry Andric NumTerminators++;
6504eeddc0SDimitry Andric if (J->getDesc().isUnconditionalBranch() ||
6604eeddc0SDimitry Andric J->getDesc().isIndirectBranch()) {
6704eeddc0SDimitry Andric FirstUncondOrIndirectBr = J.getReverse();
6804eeddc0SDimitry Andric }
6904eeddc0SDimitry Andric }
7004eeddc0SDimitry Andric
7104eeddc0SDimitry Andric // If AllowModify is true, we can erase any terminators after
7204eeddc0SDimitry Andric // FirstUncondOrIndirectBR.
7304eeddc0SDimitry Andric if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
7404eeddc0SDimitry Andric while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
7504eeddc0SDimitry Andric std::next(FirstUncondOrIndirectBr)->eraseFromParent();
7604eeddc0SDimitry Andric NumTerminators--;
7704eeddc0SDimitry Andric }
7804eeddc0SDimitry Andric I = FirstUncondOrIndirectBr;
7904eeddc0SDimitry Andric }
8004eeddc0SDimitry Andric
8104eeddc0SDimitry Andric // We can't handle blocks that end in an indirect branch.
8204eeddc0SDimitry Andric if (I->getDesc().isIndirectBranch())
8304eeddc0SDimitry Andric return true;
8404eeddc0SDimitry Andric
8504eeddc0SDimitry Andric // We can't handle blocks with more than 2 terminators.
8604eeddc0SDimitry Andric if (NumTerminators > 2)
8704eeddc0SDimitry Andric return true;
8804eeddc0SDimitry Andric
8904eeddc0SDimitry Andric // Handle a single unconditional branch.
9004eeddc0SDimitry Andric if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
9104eeddc0SDimitry Andric TBB = getBranchDestBlock(*I);
9204eeddc0SDimitry Andric return false;
9304eeddc0SDimitry Andric }
9404eeddc0SDimitry Andric
9504eeddc0SDimitry Andric // Handle a single conditional branch.
9604eeddc0SDimitry Andric if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
9704eeddc0SDimitry Andric parseCondBranch(*I, TBB, Cond);
9804eeddc0SDimitry Andric return false;
9904eeddc0SDimitry Andric }
10004eeddc0SDimitry Andric
10104eeddc0SDimitry Andric // Handle a conditional branch followed by an unconditional branch.
10204eeddc0SDimitry Andric if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
10304eeddc0SDimitry Andric I->getDesc().isUnconditionalBranch()) {
10404eeddc0SDimitry Andric parseCondBranch(*std::prev(I), TBB, Cond);
10504eeddc0SDimitry Andric FBB = getBranchDestBlock(*I);
10604eeddc0SDimitry Andric return false;
10704eeddc0SDimitry Andric }
10804eeddc0SDimitry Andric
10904eeddc0SDimitry Andric // Otherwise, we can't handle this.
11004eeddc0SDimitry Andric return true;
11104eeddc0SDimitry Andric }
11204eeddc0SDimitry Andric
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const11304eeddc0SDimitry Andric unsigned CSKYInstrInfo::removeBranch(MachineBasicBlock &MBB,
11404eeddc0SDimitry Andric int *BytesRemoved) const {
11504eeddc0SDimitry Andric if (BytesRemoved)
11604eeddc0SDimitry Andric *BytesRemoved = 0;
11704eeddc0SDimitry Andric MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
11804eeddc0SDimitry Andric if (I == MBB.end())
11904eeddc0SDimitry Andric return 0;
12004eeddc0SDimitry Andric
12104eeddc0SDimitry Andric if (!I->getDesc().isUnconditionalBranch() &&
12204eeddc0SDimitry Andric !I->getDesc().isConditionalBranch())
12304eeddc0SDimitry Andric return 0;
12404eeddc0SDimitry Andric
12504eeddc0SDimitry Andric // Remove the branch.
12604eeddc0SDimitry Andric if (BytesRemoved)
12704eeddc0SDimitry Andric *BytesRemoved += getInstSizeInBytes(*I);
12804eeddc0SDimitry Andric I->eraseFromParent();
12904eeddc0SDimitry Andric
13004eeddc0SDimitry Andric I = MBB.end();
13104eeddc0SDimitry Andric
13204eeddc0SDimitry Andric if (I == MBB.begin())
13304eeddc0SDimitry Andric return 1;
13404eeddc0SDimitry Andric --I;
13504eeddc0SDimitry Andric if (!I->getDesc().isConditionalBranch())
13604eeddc0SDimitry Andric return 1;
13704eeddc0SDimitry Andric
13804eeddc0SDimitry Andric // Remove the branch.
13904eeddc0SDimitry Andric if (BytesRemoved)
14004eeddc0SDimitry Andric *BytesRemoved += getInstSizeInBytes(*I);
14104eeddc0SDimitry Andric I->eraseFromParent();
14204eeddc0SDimitry Andric return 2;
14304eeddc0SDimitry Andric }
14404eeddc0SDimitry Andric
14504eeddc0SDimitry Andric MachineBasicBlock *
getBranchDestBlock(const MachineInstr & MI) const14604eeddc0SDimitry Andric CSKYInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
14704eeddc0SDimitry Andric assert(MI.getDesc().isBranch() && "Unexpected opcode!");
14804eeddc0SDimitry Andric // The branch target is always the last operand.
14904eeddc0SDimitry Andric int NumOp = MI.getNumExplicitOperands();
15004eeddc0SDimitry Andric assert(MI.getOperand(NumOp - 1).isMBB() && "Expected MBB!");
15104eeddc0SDimitry Andric return MI.getOperand(NumOp - 1).getMBB();
15204eeddc0SDimitry Andric }
15304eeddc0SDimitry Andric
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const15404eeddc0SDimitry Andric unsigned CSKYInstrInfo::insertBranch(
15504eeddc0SDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
15604eeddc0SDimitry Andric ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
15704eeddc0SDimitry Andric if (BytesAdded)
15804eeddc0SDimitry Andric *BytesAdded = 0;
15904eeddc0SDimitry Andric
16004eeddc0SDimitry Andric // Shouldn't be a fall through.
16104eeddc0SDimitry Andric assert(TBB && "insertBranch must not be told to insert a fallthrough");
16204eeddc0SDimitry Andric assert((Cond.size() == 2 || Cond.size() == 0) &&
16304eeddc0SDimitry Andric "CSKY branch conditions have two components!");
16404eeddc0SDimitry Andric
16504eeddc0SDimitry Andric // Unconditional branch.
16604eeddc0SDimitry Andric if (Cond.empty()) {
16704eeddc0SDimitry Andric MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(TBB);
16804eeddc0SDimitry Andric if (BytesAdded)
16904eeddc0SDimitry Andric *BytesAdded += getInstSizeInBytes(MI);
17004eeddc0SDimitry Andric return 1;
17104eeddc0SDimitry Andric }
17204eeddc0SDimitry Andric
17304eeddc0SDimitry Andric // Either a one or two-way conditional branch.
17404eeddc0SDimitry Andric unsigned Opc = Cond[0].getImm();
17504eeddc0SDimitry Andric MachineInstr &CondMI = *BuildMI(&MBB, DL, get(Opc)).add(Cond[1]).addMBB(TBB);
17604eeddc0SDimitry Andric if (BytesAdded)
17704eeddc0SDimitry Andric *BytesAdded += getInstSizeInBytes(CondMI);
17804eeddc0SDimitry Andric
17904eeddc0SDimitry Andric // One-way conditional branch.
18004eeddc0SDimitry Andric if (!FBB)
18104eeddc0SDimitry Andric return 1;
18204eeddc0SDimitry Andric
18304eeddc0SDimitry Andric // Two-way conditional branch.
18404eeddc0SDimitry Andric MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(FBB);
18504eeddc0SDimitry Andric if (BytesAdded)
18604eeddc0SDimitry Andric *BytesAdded += getInstSizeInBytes(MI);
18704eeddc0SDimitry Andric return 2;
18804eeddc0SDimitry Andric }
18904eeddc0SDimitry Andric
getOppositeBranchOpc(unsigned Opcode)19004eeddc0SDimitry Andric static unsigned getOppositeBranchOpc(unsigned Opcode) {
19104eeddc0SDimitry Andric switch (Opcode) {
19204eeddc0SDimitry Andric default:
19304eeddc0SDimitry Andric llvm_unreachable("Unknown conditional branch!");
19404eeddc0SDimitry Andric case CSKY::BT32:
19504eeddc0SDimitry Andric return CSKY::BF32;
19604eeddc0SDimitry Andric case CSKY::BT16:
19704eeddc0SDimitry Andric return CSKY::BF16;
19804eeddc0SDimitry Andric case CSKY::BF32:
19904eeddc0SDimitry Andric return CSKY::BT32;
20004eeddc0SDimitry Andric case CSKY::BF16:
20104eeddc0SDimitry Andric return CSKY::BT16;
20204eeddc0SDimitry Andric case CSKY::BHZ32:
20304eeddc0SDimitry Andric return CSKY::BLSZ32;
20404eeddc0SDimitry Andric case CSKY::BHSZ32:
20504eeddc0SDimitry Andric return CSKY::BLZ32;
20604eeddc0SDimitry Andric case CSKY::BLZ32:
20704eeddc0SDimitry Andric return CSKY::BHSZ32;
20804eeddc0SDimitry Andric case CSKY::BLSZ32:
20904eeddc0SDimitry Andric return CSKY::BHZ32;
21004eeddc0SDimitry Andric case CSKY::BNEZ32:
21104eeddc0SDimitry Andric return CSKY::BEZ32;
21204eeddc0SDimitry Andric case CSKY::BEZ32:
21304eeddc0SDimitry Andric return CSKY::BNEZ32;
21404eeddc0SDimitry Andric }
21504eeddc0SDimitry Andric }
21604eeddc0SDimitry Andric
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const21704eeddc0SDimitry Andric bool CSKYInstrInfo::reverseBranchCondition(
21804eeddc0SDimitry Andric SmallVectorImpl<MachineOperand> &Cond) const {
21904eeddc0SDimitry Andric assert((Cond.size() == 2) && "Invalid branch condition!");
22004eeddc0SDimitry Andric Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm()));
22104eeddc0SDimitry Andric return false;
222349cc55cSDimitry Andric }
2230eae32dcSDimitry Andric
movImm(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,uint64_t Val,MachineInstr::MIFlag Flag) const2240eae32dcSDimitry Andric Register CSKYInstrInfo::movImm(MachineBasicBlock &MBB,
2250eae32dcSDimitry Andric MachineBasicBlock::iterator MBBI,
22681ad6265SDimitry Andric const DebugLoc &DL, uint64_t Val,
2270eae32dcSDimitry Andric MachineInstr::MIFlag Flag) const {
22881ad6265SDimitry Andric if (!isInt<32>(Val))
22981ad6265SDimitry Andric report_fatal_error("Should only materialize 32-bit constants.");
2300eae32dcSDimitry Andric
2310eae32dcSDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
2320eae32dcSDimitry Andric
2330eae32dcSDimitry Andric Register DstReg;
2340eae32dcSDimitry Andric if (STI.hasE2()) {
2350eae32dcSDimitry Andric DstReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
2360eae32dcSDimitry Andric
2370eae32dcSDimitry Andric if (isUInt<16>(Val)) {
2380eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVI32), DstReg)
2390eae32dcSDimitry Andric .addImm(Val & 0xFFFF)
2400eae32dcSDimitry Andric .setMIFlags(Flag);
2410eae32dcSDimitry Andric } else if (isShiftedUInt<16, 16>(Val)) {
2420eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg)
2430eae32dcSDimitry Andric .addImm((Val >> 16) & 0xFFFF)
2440eae32dcSDimitry Andric .setMIFlags(Flag);
2450eae32dcSDimitry Andric } else {
2460eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg)
2470eae32dcSDimitry Andric .addImm((Val >> 16) & 0xFFFF)
2480eae32dcSDimitry Andric .setMIFlags(Flag);
2490eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ORI32), DstReg)
2500eae32dcSDimitry Andric .addReg(DstReg)
2510eae32dcSDimitry Andric .addImm(Val & 0xFFFF)
2520eae32dcSDimitry Andric .setMIFlags(Flag);
2530eae32dcSDimitry Andric }
2540eae32dcSDimitry Andric
2550eae32dcSDimitry Andric } else {
2560eae32dcSDimitry Andric DstReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);
2570eae32dcSDimitry Andric if (isUInt<8>(Val)) {
2580eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
2590eae32dcSDimitry Andric .addImm(Val & 0xFF)
2600eae32dcSDimitry Andric .setMIFlags(Flag);
2610eae32dcSDimitry Andric } else if (isUInt<16>(Val)) {
2620eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
2630eae32dcSDimitry Andric .addImm((Val >> 8) & 0xFF)
2640eae32dcSDimitry Andric .setMIFlags(Flag);
2650eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
2660eae32dcSDimitry Andric .addReg(DstReg)
2670eae32dcSDimitry Andric .addImm(8)
2680eae32dcSDimitry Andric .setMIFlags(Flag);
2690eae32dcSDimitry Andric if ((Val & 0xFF) != 0)
2700eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
2710eae32dcSDimitry Andric .addReg(DstReg)
2720eae32dcSDimitry Andric .addImm(Val & 0xFF)
2730eae32dcSDimitry Andric .setMIFlags(Flag);
2740eae32dcSDimitry Andric } else if (isUInt<24>(Val)) {
2750eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
2760eae32dcSDimitry Andric .addImm((Val >> 16) & 0xFF)
2770eae32dcSDimitry Andric .setMIFlags(Flag);
2780eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
2790eae32dcSDimitry Andric .addReg(DstReg)
2800eae32dcSDimitry Andric .addImm(8)
2810eae32dcSDimitry Andric .setMIFlags(Flag);
2820eae32dcSDimitry Andric if (((Val >> 8) & 0xFF) != 0)
2830eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
2840eae32dcSDimitry Andric .addReg(DstReg)
2850eae32dcSDimitry Andric .addImm((Val >> 8) & 0xFF)
2860eae32dcSDimitry Andric .setMIFlags(Flag);
2870eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
2880eae32dcSDimitry Andric .addReg(DstReg)
2890eae32dcSDimitry Andric .addImm(8)
2900eae32dcSDimitry Andric .setMIFlags(Flag);
2910eae32dcSDimitry Andric if ((Val & 0xFF) != 0)
2920eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
2930eae32dcSDimitry Andric .addReg(DstReg)
2940eae32dcSDimitry Andric .addImm(Val & 0xFF)
2950eae32dcSDimitry Andric .setMIFlags(Flag);
2960eae32dcSDimitry Andric } else {
2970eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
2980eae32dcSDimitry Andric .addImm((Val >> 24) & 0xFF)
2990eae32dcSDimitry Andric .setMIFlags(Flag);
3000eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
3010eae32dcSDimitry Andric .addReg(DstReg)
3020eae32dcSDimitry Andric .addImm(8)
3030eae32dcSDimitry Andric .setMIFlags(Flag);
3040eae32dcSDimitry Andric if (((Val >> 16) & 0xFF) != 0)
3050eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
3060eae32dcSDimitry Andric .addReg(DstReg)
3070eae32dcSDimitry Andric .addImm((Val >> 16) & 0xFF)
3080eae32dcSDimitry Andric .setMIFlags(Flag);
3090eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
3100eae32dcSDimitry Andric .addReg(DstReg)
3110eae32dcSDimitry Andric .addImm(8)
3120eae32dcSDimitry Andric .setMIFlags(Flag);
3130eae32dcSDimitry Andric if (((Val >> 8) & 0xFF) != 0)
3140eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
3150eae32dcSDimitry Andric .addReg(DstReg)
3160eae32dcSDimitry Andric .addImm((Val >> 8) & 0xFF)
3170eae32dcSDimitry Andric .setMIFlags(Flag);
3180eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
3190eae32dcSDimitry Andric .addReg(DstReg)
3200eae32dcSDimitry Andric .addImm(8)
3210eae32dcSDimitry Andric .setMIFlags(Flag);
3220eae32dcSDimitry Andric if ((Val & 0xFF) != 0)
3230eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
3240eae32dcSDimitry Andric .addReg(DstReg)
3250eae32dcSDimitry Andric .addImm(Val & 0xFF)
3260eae32dcSDimitry Andric .setMIFlags(Flag);
3270eae32dcSDimitry Andric }
3280eae32dcSDimitry Andric }
3290eae32dcSDimitry Andric
3300eae32dcSDimitry Andric return DstReg;
3310eae32dcSDimitry Andric }
3320eae32dcSDimitry Andric
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const333*0fca6ea1SDimitry Andric Register CSKYInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
3340eae32dcSDimitry Andric int &FrameIndex) const {
3350eae32dcSDimitry Andric switch (MI.getOpcode()) {
3360eae32dcSDimitry Andric default:
3370eae32dcSDimitry Andric return 0;
3380eae32dcSDimitry Andric case CSKY::LD16B:
3390eae32dcSDimitry Andric case CSKY::LD16H:
3400eae32dcSDimitry Andric case CSKY::LD16W:
3410eae32dcSDimitry Andric case CSKY::LD32B:
3420eae32dcSDimitry Andric case CSKY::LD32BS:
3430eae32dcSDimitry Andric case CSKY::LD32H:
3440eae32dcSDimitry Andric case CSKY::LD32HS:
3450eae32dcSDimitry Andric case CSKY::LD32W:
34604eeddc0SDimitry Andric case CSKY::FLD_S:
34704eeddc0SDimitry Andric case CSKY::FLD_D:
34804eeddc0SDimitry Andric case CSKY::f2FLD_S:
34904eeddc0SDimitry Andric case CSKY::f2FLD_D:
3500eae32dcSDimitry Andric case CSKY::RESTORE_CARRY:
3510eae32dcSDimitry Andric break;
3520eae32dcSDimitry Andric }
3530eae32dcSDimitry Andric
3540eae32dcSDimitry Andric if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
3550eae32dcSDimitry Andric MI.getOperand(2).getImm() == 0) {
3560eae32dcSDimitry Andric FrameIndex = MI.getOperand(1).getIndex();
3570eae32dcSDimitry Andric return MI.getOperand(0).getReg();
3580eae32dcSDimitry Andric }
3590eae32dcSDimitry Andric
3600eae32dcSDimitry Andric return 0;
3610eae32dcSDimitry Andric }
3620eae32dcSDimitry Andric
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const363*0fca6ea1SDimitry Andric Register CSKYInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
3640eae32dcSDimitry Andric int &FrameIndex) const {
3650eae32dcSDimitry Andric switch (MI.getOpcode()) {
3660eae32dcSDimitry Andric default:
3670eae32dcSDimitry Andric return 0;
3680eae32dcSDimitry Andric case CSKY::ST16B:
3690eae32dcSDimitry Andric case CSKY::ST16H:
3700eae32dcSDimitry Andric case CSKY::ST16W:
3710eae32dcSDimitry Andric case CSKY::ST32B:
3720eae32dcSDimitry Andric case CSKY::ST32H:
3730eae32dcSDimitry Andric case CSKY::ST32W:
37404eeddc0SDimitry Andric case CSKY::FST_S:
37504eeddc0SDimitry Andric case CSKY::FST_D:
37604eeddc0SDimitry Andric case CSKY::f2FST_S:
37704eeddc0SDimitry Andric case CSKY::f2FST_D:
3780eae32dcSDimitry Andric case CSKY::SPILL_CARRY:
3790eae32dcSDimitry Andric break;
3800eae32dcSDimitry Andric }
3810eae32dcSDimitry Andric
3820eae32dcSDimitry Andric if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
3830eae32dcSDimitry Andric MI.getOperand(2).getImm() == 0) {
3840eae32dcSDimitry Andric FrameIndex = MI.getOperand(1).getIndex();
3850eae32dcSDimitry Andric return MI.getOperand(0).getReg();
3860eae32dcSDimitry Andric }
3870eae32dcSDimitry Andric
3880eae32dcSDimitry Andric return 0;
3890eae32dcSDimitry Andric }
3900eae32dcSDimitry Andric
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register SrcReg,bool IsKill,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const3910eae32dcSDimitry Andric void CSKYInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
3920eae32dcSDimitry Andric MachineBasicBlock::iterator I,
3930eae32dcSDimitry Andric Register SrcReg, bool IsKill, int FI,
3940eae32dcSDimitry Andric const TargetRegisterClass *RC,
395bdd1243dSDimitry Andric const TargetRegisterInfo *TRI,
396bdd1243dSDimitry Andric Register VReg) const {
3970eae32dcSDimitry Andric DebugLoc DL;
3980eae32dcSDimitry Andric if (I != MBB.end())
3990eae32dcSDimitry Andric DL = I->getDebugLoc();
4000eae32dcSDimitry Andric
4010eae32dcSDimitry Andric MachineFunction &MF = *MBB.getParent();
4020eae32dcSDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
4030eae32dcSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
4040eae32dcSDimitry Andric
4050eae32dcSDimitry Andric unsigned Opcode = 0;
4060eae32dcSDimitry Andric
4070eae32dcSDimitry Andric if (CSKY::GPRRegClass.hasSubClassEq(RC)) {
4080eae32dcSDimitry Andric Opcode = CSKY::ST32W; // Optimize for 16bit
4090eae32dcSDimitry Andric } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {
4100eae32dcSDimitry Andric Opcode = CSKY::SPILL_CARRY;
4110eae32dcSDimitry Andric CFI->setSpillsCR();
41204eeddc0SDimitry Andric } else if (v2sf && CSKY::sFPR32RegClass.hasSubClassEq(RC))
41304eeddc0SDimitry Andric Opcode = CSKY::FST_S;
41404eeddc0SDimitry Andric else if (v2df && CSKY::sFPR64RegClass.hasSubClassEq(RC))
41504eeddc0SDimitry Andric Opcode = CSKY::FST_D;
41604eeddc0SDimitry Andric else if (v3sf && CSKY::FPR32RegClass.hasSubClassEq(RC))
41704eeddc0SDimitry Andric Opcode = CSKY::f2FST_S;
41804eeddc0SDimitry Andric else if (v3df && CSKY::FPR64RegClass.hasSubClassEq(RC))
41904eeddc0SDimitry Andric Opcode = CSKY::f2FST_D;
42004eeddc0SDimitry Andric else {
4210eae32dcSDimitry Andric llvm_unreachable("Unknown RegisterClass");
4220eae32dcSDimitry Andric }
4230eae32dcSDimitry Andric
4240eae32dcSDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand(
4250eae32dcSDimitry Andric MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
4260eae32dcSDimitry Andric MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
4270eae32dcSDimitry Andric
4280eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(Opcode))
4290eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(IsKill))
4300eae32dcSDimitry Andric .addFrameIndex(FI)
4310eae32dcSDimitry Andric .addImm(0)
4320eae32dcSDimitry Andric .addMemOperand(MMO);
4330eae32dcSDimitry Andric }
4340eae32dcSDimitry Andric
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register DestReg,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const4350eae32dcSDimitry Andric void CSKYInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
4360eae32dcSDimitry Andric MachineBasicBlock::iterator I,
4370eae32dcSDimitry Andric Register DestReg, int FI,
4380eae32dcSDimitry Andric const TargetRegisterClass *RC,
439bdd1243dSDimitry Andric const TargetRegisterInfo *TRI,
440bdd1243dSDimitry Andric Register VReg) const {
4410eae32dcSDimitry Andric DebugLoc DL;
4420eae32dcSDimitry Andric if (I != MBB.end())
4430eae32dcSDimitry Andric DL = I->getDebugLoc();
4440eae32dcSDimitry Andric
4450eae32dcSDimitry Andric MachineFunction &MF = *MBB.getParent();
4460eae32dcSDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
4470eae32dcSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
4480eae32dcSDimitry Andric
4490eae32dcSDimitry Andric unsigned Opcode = 0;
4500eae32dcSDimitry Andric
4510eae32dcSDimitry Andric if (CSKY::GPRRegClass.hasSubClassEq(RC)) {
4520eae32dcSDimitry Andric Opcode = CSKY::LD32W;
4530eae32dcSDimitry Andric } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {
4540eae32dcSDimitry Andric Opcode = CSKY::RESTORE_CARRY;
4550eae32dcSDimitry Andric CFI->setSpillsCR();
45604eeddc0SDimitry Andric } else if (v2sf && CSKY::sFPR32RegClass.hasSubClassEq(RC))
45704eeddc0SDimitry Andric Opcode = CSKY::FLD_S;
45804eeddc0SDimitry Andric else if (v2df && CSKY::sFPR64RegClass.hasSubClassEq(RC))
45904eeddc0SDimitry Andric Opcode = CSKY::FLD_D;
46004eeddc0SDimitry Andric else if (v3sf && CSKY::FPR32RegClass.hasSubClassEq(RC))
46104eeddc0SDimitry Andric Opcode = CSKY::f2FLD_S;
46204eeddc0SDimitry Andric else if (v3df && CSKY::FPR64RegClass.hasSubClassEq(RC))
46304eeddc0SDimitry Andric Opcode = CSKY::f2FLD_D;
46404eeddc0SDimitry Andric else {
4650eae32dcSDimitry Andric llvm_unreachable("Unknown RegisterClass");
4660eae32dcSDimitry Andric }
4670eae32dcSDimitry Andric
4680eae32dcSDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand(
4690eae32dcSDimitry Andric MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
4700eae32dcSDimitry Andric MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
4710eae32dcSDimitry Andric
4720eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(Opcode), DestReg)
4730eae32dcSDimitry Andric .addFrameIndex(FI)
4740eae32dcSDimitry Andric .addImm(0)
4750eae32dcSDimitry Andric .addMemOperand(MMO);
4760eae32dcSDimitry Andric }
4770eae32dcSDimitry Andric
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,MCRegister DestReg,MCRegister SrcReg,bool KillSrc) const4780eae32dcSDimitry Andric void CSKYInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
4790eae32dcSDimitry Andric MachineBasicBlock::iterator I,
4800eae32dcSDimitry Andric const DebugLoc &DL, MCRegister DestReg,
4810eae32dcSDimitry Andric MCRegister SrcReg, bool KillSrc) const {
4820eae32dcSDimitry Andric if (CSKY::GPRRegClass.contains(SrcReg) &&
4830eae32dcSDimitry Andric CSKY::CARRYRegClass.contains(DestReg)) {
4840eae32dcSDimitry Andric if (STI.hasE2()) {
4850eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::BTSTI32), DestReg)
4860eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc))
4870eae32dcSDimitry Andric .addImm(0);
4880eae32dcSDimitry Andric } else {
4890eae32dcSDimitry Andric assert(SrcReg < CSKY::R8);
4900eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::BTSTI16), DestReg)
4910eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc))
4920eae32dcSDimitry Andric .addImm(0);
4930eae32dcSDimitry Andric }
4940eae32dcSDimitry Andric return;
4950eae32dcSDimitry Andric }
4960eae32dcSDimitry Andric
4970eae32dcSDimitry Andric if (CSKY::CARRYRegClass.contains(SrcReg) &&
4980eae32dcSDimitry Andric CSKY::GPRRegClass.contains(DestReg)) {
4990eae32dcSDimitry Andric
5000eae32dcSDimitry Andric if (STI.hasE2()) {
5010eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::MVC32), DestReg)
5020eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc));
5030eae32dcSDimitry Andric } else {
5040eae32dcSDimitry Andric assert(DestReg < CSKY::R16);
5050eae32dcSDimitry Andric assert(DestReg < CSKY::R8);
5060eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::MOVI16), DestReg).addImm(0);
5070eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::ADDC16))
5080eae32dcSDimitry Andric .addReg(DestReg, RegState::Define)
5090eae32dcSDimitry Andric .addReg(SrcReg, RegState::Define)
5100eae32dcSDimitry Andric .addReg(DestReg, getKillRegState(true))
5110eae32dcSDimitry Andric .addReg(DestReg, getKillRegState(true))
5120eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(true));
5130eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::BTSTI16))
5140eae32dcSDimitry Andric .addReg(SrcReg, RegState::Define | getDeadRegState(KillSrc))
5150eae32dcSDimitry Andric .addReg(DestReg)
5160eae32dcSDimitry Andric .addImm(0);
5170eae32dcSDimitry Andric }
5180eae32dcSDimitry Andric return;
5190eae32dcSDimitry Andric }
5200eae32dcSDimitry Andric
5210eae32dcSDimitry Andric unsigned Opcode = 0;
5220eae32dcSDimitry Andric if (CSKY::GPRRegClass.contains(DestReg, SrcReg))
523fcaf7f86SDimitry Andric Opcode = STI.hasE2() ? CSKY::MOV32 : CSKY::MOV16;
52404eeddc0SDimitry Andric else if (v2sf && CSKY::sFPR32RegClass.contains(DestReg, SrcReg))
52504eeddc0SDimitry Andric Opcode = CSKY::FMOV_S;
52604eeddc0SDimitry Andric else if (v3sf && CSKY::FPR32RegClass.contains(DestReg, SrcReg))
52704eeddc0SDimitry Andric Opcode = CSKY::f2FMOV_S;
52804eeddc0SDimitry Andric else if (v2df && CSKY::sFPR64RegClass.contains(DestReg, SrcReg))
52904eeddc0SDimitry Andric Opcode = CSKY::FMOV_D;
53004eeddc0SDimitry Andric else if (v3df && CSKY::FPR64RegClass.contains(DestReg, SrcReg))
53104eeddc0SDimitry Andric Opcode = CSKY::f2FMOV_D;
53204eeddc0SDimitry Andric else if (v2sf && CSKY::sFPR32RegClass.contains(SrcReg) &&
53304eeddc0SDimitry Andric CSKY::GPRRegClass.contains(DestReg))
53404eeddc0SDimitry Andric Opcode = CSKY::FMFVRL;
53504eeddc0SDimitry Andric else if (v3sf && CSKY::FPR32RegClass.contains(SrcReg) &&
53604eeddc0SDimitry Andric CSKY::GPRRegClass.contains(DestReg))
53704eeddc0SDimitry Andric Opcode = CSKY::f2FMFVRL;
53804eeddc0SDimitry Andric else if (v2df && CSKY::sFPR64RegClass.contains(SrcReg) &&
53904eeddc0SDimitry Andric CSKY::GPRRegClass.contains(DestReg))
54004eeddc0SDimitry Andric Opcode = CSKY::FMFVRL_D;
54104eeddc0SDimitry Andric else if (v3df && CSKY::FPR64RegClass.contains(SrcReg) &&
54204eeddc0SDimitry Andric CSKY::GPRRegClass.contains(DestReg))
54304eeddc0SDimitry Andric Opcode = CSKY::f2FMFVRL_D;
54404eeddc0SDimitry Andric else if (v2sf && CSKY::GPRRegClass.contains(SrcReg) &&
54504eeddc0SDimitry Andric CSKY::sFPR32RegClass.contains(DestReg))
54604eeddc0SDimitry Andric Opcode = CSKY::FMTVRL;
54704eeddc0SDimitry Andric else if (v3sf && CSKY::GPRRegClass.contains(SrcReg) &&
54804eeddc0SDimitry Andric CSKY::FPR32RegClass.contains(DestReg))
54904eeddc0SDimitry Andric Opcode = CSKY::f2FMTVRL;
55004eeddc0SDimitry Andric else if (v2df && CSKY::GPRRegClass.contains(SrcReg) &&
55104eeddc0SDimitry Andric CSKY::sFPR64RegClass.contains(DestReg))
55204eeddc0SDimitry Andric Opcode = CSKY::FMTVRL_D;
55304eeddc0SDimitry Andric else if (v3df && CSKY::GPRRegClass.contains(SrcReg) &&
55404eeddc0SDimitry Andric CSKY::FPR64RegClass.contains(DestReg))
55504eeddc0SDimitry Andric Opcode = CSKY::f2FMTVRL_D;
5560eae32dcSDimitry Andric else {
5570eae32dcSDimitry Andric LLVM_DEBUG(dbgs() << "src = " << SrcReg << ", dst = " << DestReg);
5580eae32dcSDimitry Andric LLVM_DEBUG(I->dump());
5590eae32dcSDimitry Andric llvm_unreachable("Unknown RegisterClass");
5600eae32dcSDimitry Andric }
5610eae32dcSDimitry Andric
5620eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(Opcode), DestReg)
5630eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc));
5640eae32dcSDimitry Andric }
56504eeddc0SDimitry Andric
getGlobalBaseReg(MachineFunction & MF) const56604eeddc0SDimitry Andric Register CSKYInstrInfo::getGlobalBaseReg(MachineFunction &MF) const {
56704eeddc0SDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
56804eeddc0SDimitry Andric MachineConstantPool *MCP = MF.getConstantPool();
56904eeddc0SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo();
57004eeddc0SDimitry Andric
57104eeddc0SDimitry Andric Register GlobalBaseReg = CFI->getGlobalBaseReg();
57204eeddc0SDimitry Andric if (GlobalBaseReg != 0)
57304eeddc0SDimitry Andric return GlobalBaseReg;
57404eeddc0SDimitry Andric
57504eeddc0SDimitry Andric // Insert a pseudo instruction to set the GlobalBaseReg into the first
57604eeddc0SDimitry Andric // MBB of the function
57704eeddc0SDimitry Andric MachineBasicBlock &FirstMBB = MF.front();
57804eeddc0SDimitry Andric MachineBasicBlock::iterator MBBI = FirstMBB.begin();
57904eeddc0SDimitry Andric DebugLoc DL;
58004eeddc0SDimitry Andric
58104eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolSymbol::Create(
58204eeddc0SDimitry Andric Type::getInt32Ty(MF.getFunction().getContext()), "_GLOBAL_OFFSET_TABLE_",
58304eeddc0SDimitry Andric 0, CSKYCP::ADDR);
58404eeddc0SDimitry Andric
58504eeddc0SDimitry Andric unsigned CPI = MCP->getConstantPoolIndex(CPV, Align(4));
58604eeddc0SDimitry Andric
58704eeddc0SDimitry Andric MachineMemOperand *MO =
58804eeddc0SDimitry Andric MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
58904eeddc0SDimitry Andric MachineMemOperand::MOLoad, 4, Align(4));
59004eeddc0SDimitry Andric BuildMI(FirstMBB, MBBI, DL, get(CSKY::LRW32), CSKY::R28)
59104eeddc0SDimitry Andric .addConstantPoolIndex(CPI)
59204eeddc0SDimitry Andric .addMemOperand(MO);
59304eeddc0SDimitry Andric
59404eeddc0SDimitry Andric GlobalBaseReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
59504eeddc0SDimitry Andric BuildMI(FirstMBB, MBBI, DL, get(TargetOpcode::COPY), GlobalBaseReg)
59604eeddc0SDimitry Andric .addReg(CSKY::R28);
59704eeddc0SDimitry Andric
59804eeddc0SDimitry Andric CFI->setGlobalBaseReg(GlobalBaseReg);
59904eeddc0SDimitry Andric return GlobalBaseReg;
60004eeddc0SDimitry Andric }
60104eeddc0SDimitry Andric
getInstSizeInBytes(const MachineInstr & MI) const60204eeddc0SDimitry Andric unsigned CSKYInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
60304eeddc0SDimitry Andric switch (MI.getOpcode()) {
60404eeddc0SDimitry Andric default:
60504eeddc0SDimitry Andric return MI.getDesc().getSize();
60604eeddc0SDimitry Andric case CSKY::CONSTPOOL_ENTRY:
60704eeddc0SDimitry Andric return MI.getOperand(2).getImm();
60804eeddc0SDimitry Andric case CSKY::SPILL_CARRY:
60904eeddc0SDimitry Andric case CSKY::RESTORE_CARRY:
61004eeddc0SDimitry Andric case CSKY::PseudoTLSLA32:
61104eeddc0SDimitry Andric return 8;
61204eeddc0SDimitry Andric case TargetOpcode::INLINEASM_BR:
61304eeddc0SDimitry Andric case TargetOpcode::INLINEASM: {
61404eeddc0SDimitry Andric const MachineFunction *MF = MI.getParent()->getParent();
61504eeddc0SDimitry Andric const char *AsmStr = MI.getOperand(0).getSymbolName();
61604eeddc0SDimitry Andric return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
61704eeddc0SDimitry Andric }
61804eeddc0SDimitry Andric }
61904eeddc0SDimitry Andric }
620