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" 14*0eae32dcSDimitry Andric #include "CSKYMachineFunctionInfo.h" 15*0eae32dcSDimitry Andric #include "CSKYTargetMachine.h" 16349cc55cSDimitry Andric #include "llvm/MC/MCContext.h" 17349cc55cSDimitry Andric 18349cc55cSDimitry Andric #define DEBUG_TYPE "csky-instr-info" 19349cc55cSDimitry Andric 20349cc55cSDimitry Andric using namespace llvm; 21349cc55cSDimitry Andric 22349cc55cSDimitry Andric #define GET_INSTRINFO_CTOR_DTOR 23349cc55cSDimitry Andric #include "CSKYGenInstrInfo.inc" 24349cc55cSDimitry Andric 25349cc55cSDimitry Andric CSKYInstrInfo::CSKYInstrInfo(CSKYSubtarget &STI) 26349cc55cSDimitry Andric : CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN, CSKY::ADJCALLSTACKUP), STI(STI) { 27349cc55cSDimitry Andric } 28*0eae32dcSDimitry Andric 29*0eae32dcSDimitry Andric Register CSKYInstrInfo::movImm(MachineBasicBlock &MBB, 30*0eae32dcSDimitry Andric MachineBasicBlock::iterator MBBI, 31*0eae32dcSDimitry Andric const DebugLoc &DL, int64_t Val, 32*0eae32dcSDimitry Andric MachineInstr::MIFlag Flag) const { 33*0eae32dcSDimitry Andric assert(isUInt<32>(Val) && "should be uint32"); 34*0eae32dcSDimitry Andric 35*0eae32dcSDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 36*0eae32dcSDimitry Andric 37*0eae32dcSDimitry Andric Register DstReg; 38*0eae32dcSDimitry Andric if (STI.hasE2()) { 39*0eae32dcSDimitry Andric DstReg = MRI.createVirtualRegister(&CSKY::GPRRegClass); 40*0eae32dcSDimitry Andric 41*0eae32dcSDimitry Andric if (isUInt<16>(Val)) { 42*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVI32), DstReg) 43*0eae32dcSDimitry Andric .addImm(Val & 0xFFFF) 44*0eae32dcSDimitry Andric .setMIFlags(Flag); 45*0eae32dcSDimitry Andric } else if (isShiftedUInt<16, 16>(Val)) { 46*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg) 47*0eae32dcSDimitry Andric .addImm((Val >> 16) & 0xFFFF) 48*0eae32dcSDimitry Andric .setMIFlags(Flag); 49*0eae32dcSDimitry Andric } else { 50*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg) 51*0eae32dcSDimitry Andric .addImm((Val >> 16) & 0xFFFF) 52*0eae32dcSDimitry Andric .setMIFlags(Flag); 53*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ORI32), DstReg) 54*0eae32dcSDimitry Andric .addReg(DstReg) 55*0eae32dcSDimitry Andric .addImm(Val & 0xFFFF) 56*0eae32dcSDimitry Andric .setMIFlags(Flag); 57*0eae32dcSDimitry Andric } 58*0eae32dcSDimitry Andric 59*0eae32dcSDimitry Andric } else { 60*0eae32dcSDimitry Andric DstReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass); 61*0eae32dcSDimitry Andric if (isUInt<8>(Val)) { 62*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) 63*0eae32dcSDimitry Andric .addImm(Val & 0xFF) 64*0eae32dcSDimitry Andric .setMIFlags(Flag); 65*0eae32dcSDimitry Andric } else if (isUInt<16>(Val)) { 66*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) 67*0eae32dcSDimitry Andric .addImm((Val >> 8) & 0xFF) 68*0eae32dcSDimitry Andric .setMIFlags(Flag); 69*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 70*0eae32dcSDimitry Andric .addReg(DstReg) 71*0eae32dcSDimitry Andric .addImm(8) 72*0eae32dcSDimitry Andric .setMIFlags(Flag); 73*0eae32dcSDimitry Andric if ((Val & 0xFF) != 0) 74*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 75*0eae32dcSDimitry Andric .addReg(DstReg) 76*0eae32dcSDimitry Andric .addImm(Val & 0xFF) 77*0eae32dcSDimitry Andric .setMIFlags(Flag); 78*0eae32dcSDimitry Andric } else if (isUInt<24>(Val)) { 79*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) 80*0eae32dcSDimitry Andric .addImm((Val >> 16) & 0xFF) 81*0eae32dcSDimitry Andric .setMIFlags(Flag); 82*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 83*0eae32dcSDimitry Andric .addReg(DstReg) 84*0eae32dcSDimitry Andric .addImm(8) 85*0eae32dcSDimitry Andric .setMIFlags(Flag); 86*0eae32dcSDimitry Andric if (((Val >> 8) & 0xFF) != 0) 87*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 88*0eae32dcSDimitry Andric .addReg(DstReg) 89*0eae32dcSDimitry Andric .addImm((Val >> 8) & 0xFF) 90*0eae32dcSDimitry Andric .setMIFlags(Flag); 91*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 92*0eae32dcSDimitry Andric .addReg(DstReg) 93*0eae32dcSDimitry Andric .addImm(8) 94*0eae32dcSDimitry Andric .setMIFlags(Flag); 95*0eae32dcSDimitry Andric if ((Val & 0xFF) != 0) 96*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 97*0eae32dcSDimitry Andric .addReg(DstReg) 98*0eae32dcSDimitry Andric .addImm(Val & 0xFF) 99*0eae32dcSDimitry Andric .setMIFlags(Flag); 100*0eae32dcSDimitry Andric } else { 101*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) 102*0eae32dcSDimitry Andric .addImm((Val >> 24) & 0xFF) 103*0eae32dcSDimitry Andric .setMIFlags(Flag); 104*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 105*0eae32dcSDimitry Andric .addReg(DstReg) 106*0eae32dcSDimitry Andric .addImm(8) 107*0eae32dcSDimitry Andric .setMIFlags(Flag); 108*0eae32dcSDimitry Andric if (((Val >> 16) & 0xFF) != 0) 109*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 110*0eae32dcSDimitry Andric .addReg(DstReg) 111*0eae32dcSDimitry Andric .addImm((Val >> 16) & 0xFF) 112*0eae32dcSDimitry Andric .setMIFlags(Flag); 113*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 114*0eae32dcSDimitry Andric .addReg(DstReg) 115*0eae32dcSDimitry Andric .addImm(8) 116*0eae32dcSDimitry Andric .setMIFlags(Flag); 117*0eae32dcSDimitry Andric if (((Val >> 8) & 0xFF) != 0) 118*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 119*0eae32dcSDimitry Andric .addReg(DstReg) 120*0eae32dcSDimitry Andric .addImm((Val >> 8) & 0xFF) 121*0eae32dcSDimitry Andric .setMIFlags(Flag); 122*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 123*0eae32dcSDimitry Andric .addReg(DstReg) 124*0eae32dcSDimitry Andric .addImm(8) 125*0eae32dcSDimitry Andric .setMIFlags(Flag); 126*0eae32dcSDimitry Andric if ((Val & 0xFF) != 0) 127*0eae32dcSDimitry Andric BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 128*0eae32dcSDimitry Andric .addReg(DstReg) 129*0eae32dcSDimitry Andric .addImm(Val & 0xFF) 130*0eae32dcSDimitry Andric .setMIFlags(Flag); 131*0eae32dcSDimitry Andric } 132*0eae32dcSDimitry Andric } 133*0eae32dcSDimitry Andric 134*0eae32dcSDimitry Andric return DstReg; 135*0eae32dcSDimitry Andric } 136*0eae32dcSDimitry Andric 137*0eae32dcSDimitry Andric unsigned CSKYInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, 138*0eae32dcSDimitry Andric int &FrameIndex) const { 139*0eae32dcSDimitry Andric switch (MI.getOpcode()) { 140*0eae32dcSDimitry Andric default: 141*0eae32dcSDimitry Andric return 0; 142*0eae32dcSDimitry Andric case CSKY::LD16B: 143*0eae32dcSDimitry Andric case CSKY::LD16H: 144*0eae32dcSDimitry Andric case CSKY::LD16W: 145*0eae32dcSDimitry Andric case CSKY::LD32B: 146*0eae32dcSDimitry Andric case CSKY::LD32BS: 147*0eae32dcSDimitry Andric case CSKY::LD32H: 148*0eae32dcSDimitry Andric case CSKY::LD32HS: 149*0eae32dcSDimitry Andric case CSKY::LD32W: 150*0eae32dcSDimitry Andric case CSKY::RESTORE_CARRY: 151*0eae32dcSDimitry Andric break; 152*0eae32dcSDimitry Andric } 153*0eae32dcSDimitry Andric 154*0eae32dcSDimitry Andric if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && 155*0eae32dcSDimitry Andric MI.getOperand(2).getImm() == 0) { 156*0eae32dcSDimitry Andric FrameIndex = MI.getOperand(1).getIndex(); 157*0eae32dcSDimitry Andric return MI.getOperand(0).getReg(); 158*0eae32dcSDimitry Andric } 159*0eae32dcSDimitry Andric 160*0eae32dcSDimitry Andric return 0; 161*0eae32dcSDimitry Andric } 162*0eae32dcSDimitry Andric 163*0eae32dcSDimitry Andric unsigned CSKYInstrInfo::isStoreToStackSlot(const MachineInstr &MI, 164*0eae32dcSDimitry Andric int &FrameIndex) const { 165*0eae32dcSDimitry Andric switch (MI.getOpcode()) { 166*0eae32dcSDimitry Andric default: 167*0eae32dcSDimitry Andric return 0; 168*0eae32dcSDimitry Andric case CSKY::ST16B: 169*0eae32dcSDimitry Andric case CSKY::ST16H: 170*0eae32dcSDimitry Andric case CSKY::ST16W: 171*0eae32dcSDimitry Andric case CSKY::ST32B: 172*0eae32dcSDimitry Andric case CSKY::ST32H: 173*0eae32dcSDimitry Andric case CSKY::ST32W: 174*0eae32dcSDimitry Andric case CSKY::SPILL_CARRY: 175*0eae32dcSDimitry Andric break; 176*0eae32dcSDimitry Andric } 177*0eae32dcSDimitry Andric 178*0eae32dcSDimitry Andric if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && 179*0eae32dcSDimitry Andric MI.getOperand(2).getImm() == 0) { 180*0eae32dcSDimitry Andric FrameIndex = MI.getOperand(1).getIndex(); 181*0eae32dcSDimitry Andric return MI.getOperand(0).getReg(); 182*0eae32dcSDimitry Andric } 183*0eae32dcSDimitry Andric 184*0eae32dcSDimitry Andric return 0; 185*0eae32dcSDimitry Andric } 186*0eae32dcSDimitry Andric 187*0eae32dcSDimitry Andric void CSKYInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 188*0eae32dcSDimitry Andric MachineBasicBlock::iterator I, 189*0eae32dcSDimitry Andric Register SrcReg, bool IsKill, int FI, 190*0eae32dcSDimitry Andric const TargetRegisterClass *RC, 191*0eae32dcSDimitry Andric const TargetRegisterInfo *TRI) const { 192*0eae32dcSDimitry Andric DebugLoc DL; 193*0eae32dcSDimitry Andric if (I != MBB.end()) 194*0eae32dcSDimitry Andric DL = I->getDebugLoc(); 195*0eae32dcSDimitry Andric 196*0eae32dcSDimitry Andric MachineFunction &MF = *MBB.getParent(); 197*0eae32dcSDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 198*0eae32dcSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 199*0eae32dcSDimitry Andric 200*0eae32dcSDimitry Andric unsigned Opcode = 0; 201*0eae32dcSDimitry Andric 202*0eae32dcSDimitry Andric if (CSKY::GPRRegClass.hasSubClassEq(RC)) { 203*0eae32dcSDimitry Andric Opcode = CSKY::ST32W; // Optimize for 16bit 204*0eae32dcSDimitry Andric } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) { 205*0eae32dcSDimitry Andric Opcode = CSKY::SPILL_CARRY; 206*0eae32dcSDimitry Andric CFI->setSpillsCR(); 207*0eae32dcSDimitry Andric } else { 208*0eae32dcSDimitry Andric llvm_unreachable("Unknown RegisterClass"); 209*0eae32dcSDimitry Andric } 210*0eae32dcSDimitry Andric 211*0eae32dcSDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand( 212*0eae32dcSDimitry Andric MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore, 213*0eae32dcSDimitry Andric MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); 214*0eae32dcSDimitry Andric 215*0eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(Opcode)) 216*0eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(IsKill)) 217*0eae32dcSDimitry Andric .addFrameIndex(FI) 218*0eae32dcSDimitry Andric .addImm(0) 219*0eae32dcSDimitry Andric .addMemOperand(MMO); 220*0eae32dcSDimitry Andric } 221*0eae32dcSDimitry Andric 222*0eae32dcSDimitry Andric void CSKYInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 223*0eae32dcSDimitry Andric MachineBasicBlock::iterator I, 224*0eae32dcSDimitry Andric Register DestReg, int FI, 225*0eae32dcSDimitry Andric const TargetRegisterClass *RC, 226*0eae32dcSDimitry Andric const TargetRegisterInfo *TRI) const { 227*0eae32dcSDimitry Andric DebugLoc DL; 228*0eae32dcSDimitry Andric if (I != MBB.end()) 229*0eae32dcSDimitry Andric DL = I->getDebugLoc(); 230*0eae32dcSDimitry Andric 231*0eae32dcSDimitry Andric MachineFunction &MF = *MBB.getParent(); 232*0eae32dcSDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 233*0eae32dcSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 234*0eae32dcSDimitry Andric 235*0eae32dcSDimitry Andric unsigned Opcode = 0; 236*0eae32dcSDimitry Andric 237*0eae32dcSDimitry Andric if (CSKY::GPRRegClass.hasSubClassEq(RC)) { 238*0eae32dcSDimitry Andric Opcode = CSKY::LD32W; 239*0eae32dcSDimitry Andric } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) { 240*0eae32dcSDimitry Andric Opcode = CSKY::RESTORE_CARRY; 241*0eae32dcSDimitry Andric CFI->setSpillsCR(); 242*0eae32dcSDimitry Andric } else { 243*0eae32dcSDimitry Andric llvm_unreachable("Unknown RegisterClass"); 244*0eae32dcSDimitry Andric } 245*0eae32dcSDimitry Andric 246*0eae32dcSDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand( 247*0eae32dcSDimitry Andric MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad, 248*0eae32dcSDimitry Andric MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); 249*0eae32dcSDimitry Andric 250*0eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(Opcode), DestReg) 251*0eae32dcSDimitry Andric .addFrameIndex(FI) 252*0eae32dcSDimitry Andric .addImm(0) 253*0eae32dcSDimitry Andric .addMemOperand(MMO); 254*0eae32dcSDimitry Andric } 255*0eae32dcSDimitry Andric 256*0eae32dcSDimitry Andric void CSKYInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 257*0eae32dcSDimitry Andric MachineBasicBlock::iterator I, 258*0eae32dcSDimitry Andric const DebugLoc &DL, MCRegister DestReg, 259*0eae32dcSDimitry Andric MCRegister SrcReg, bool KillSrc) const { 260*0eae32dcSDimitry Andric 261*0eae32dcSDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 262*0eae32dcSDimitry Andric 263*0eae32dcSDimitry Andric if (CSKY::GPRRegClass.contains(SrcReg) && 264*0eae32dcSDimitry Andric CSKY::CARRYRegClass.contains(DestReg)) { 265*0eae32dcSDimitry Andric if (STI.hasE2()) { 266*0eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::BTSTI32), DestReg) 267*0eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)) 268*0eae32dcSDimitry Andric .addImm(0); 269*0eae32dcSDimitry Andric } else { 270*0eae32dcSDimitry Andric assert(SrcReg < CSKY::R8); 271*0eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::BTSTI16), DestReg) 272*0eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)) 273*0eae32dcSDimitry Andric .addImm(0); 274*0eae32dcSDimitry Andric } 275*0eae32dcSDimitry Andric return; 276*0eae32dcSDimitry Andric } 277*0eae32dcSDimitry Andric 278*0eae32dcSDimitry Andric if (CSKY::CARRYRegClass.contains(SrcReg) && 279*0eae32dcSDimitry Andric CSKY::GPRRegClass.contains(DestReg)) { 280*0eae32dcSDimitry Andric 281*0eae32dcSDimitry Andric if (STI.hasE2()) { 282*0eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::MVC32), DestReg) 283*0eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 284*0eae32dcSDimitry Andric } else { 285*0eae32dcSDimitry Andric assert(DestReg < CSKY::R16); 286*0eae32dcSDimitry Andric assert(DestReg < CSKY::R8); 287*0eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::MOVI16), DestReg).addImm(0); 288*0eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::ADDC16)) 289*0eae32dcSDimitry Andric .addReg(DestReg, RegState::Define) 290*0eae32dcSDimitry Andric .addReg(SrcReg, RegState::Define) 291*0eae32dcSDimitry Andric .addReg(DestReg, getKillRegState(true)) 292*0eae32dcSDimitry Andric .addReg(DestReg, getKillRegState(true)) 293*0eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(true)); 294*0eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(CSKY::BTSTI16)) 295*0eae32dcSDimitry Andric .addReg(SrcReg, RegState::Define | getDeadRegState(KillSrc)) 296*0eae32dcSDimitry Andric .addReg(DestReg) 297*0eae32dcSDimitry Andric .addImm(0); 298*0eae32dcSDimitry Andric } 299*0eae32dcSDimitry Andric return; 300*0eae32dcSDimitry Andric } 301*0eae32dcSDimitry Andric 302*0eae32dcSDimitry Andric unsigned Opcode = 0; 303*0eae32dcSDimitry Andric if (CSKY::GPRRegClass.contains(DestReg, SrcReg)) 304*0eae32dcSDimitry Andric Opcode = CSKY::MOV32; 305*0eae32dcSDimitry Andric else { 306*0eae32dcSDimitry Andric LLVM_DEBUG(dbgs() << "src = " << SrcReg << ", dst = " << DestReg); 307*0eae32dcSDimitry Andric LLVM_DEBUG(I->dump()); 308*0eae32dcSDimitry Andric llvm_unreachable("Unknown RegisterClass"); 309*0eae32dcSDimitry Andric } 310*0eae32dcSDimitry Andric 311*0eae32dcSDimitry Andric BuildMI(MBB, I, DL, get(Opcode), DestReg) 312*0eae32dcSDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 313*0eae32dcSDimitry Andric } 314