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 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 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 4504eeddc0SDimitry 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 11304eeddc0SDimitry 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 * 14604eeddc0SDimitry 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 15404eeddc0SDimitry 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 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 21704eeddc0SDimitry 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 2240eae32dcSDimitry 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 333*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 363*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 3910eae32dcSDimitry 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 4350eae32dcSDimitry 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 4780eae32dcSDimitry 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 56604eeddc0SDimitry 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 60204eeddc0SDimitry 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