1 //===- XtensaInstrInfo.cpp - Xtensa Instruction Information ---------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6 // See https://llvm.org/LICENSE.txt for license information. 7 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 // This file contains the Xtensa implementation of the TargetInstrInfo class. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "XtensaInstrInfo.h" 16 #include "XtensaTargetMachine.h" 17 #include "llvm/CodeGen/MachineConstantPool.h" 18 #include "llvm/CodeGen/MachineFrameInfo.h" 19 #include "llvm/CodeGen/MachineInstrBuilder.h" 20 #include "llvm/CodeGen/MachineRegisterInfo.h" 21 22 #define GET_INSTRINFO_CTOR_DTOR 23 #include "XtensaGenInstrInfo.inc" 24 25 using namespace llvm; 26 27 static const MachineInstrBuilder & 28 addFrameReference(const MachineInstrBuilder &MIB, int FI) { 29 MachineInstr *MI = MIB; 30 MachineFunction &MF = *MI->getParent()->getParent(); 31 MachineFrameInfo &MFFrame = MF.getFrameInfo(); 32 const MCInstrDesc &MCID = MI->getDesc(); 33 MachineMemOperand::Flags Flags = MachineMemOperand::MONone; 34 if (MCID.mayLoad()) 35 Flags |= MachineMemOperand::MOLoad; 36 if (MCID.mayStore()) 37 Flags |= MachineMemOperand::MOStore; 38 int64_t Offset = 0; 39 Align Alignment = MFFrame.getObjectAlign(FI); 40 41 MachineMemOperand *MMO = 42 MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI, Offset), 43 Flags, MFFrame.getObjectSize(FI), Alignment); 44 return MIB.addFrameIndex(FI).addImm(Offset).addMemOperand(MMO); 45 } 46 47 XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget &STI) 48 : XtensaGenInstrInfo(Xtensa::ADJCALLSTACKDOWN, Xtensa::ADJCALLSTACKUP), 49 RI(STI), STI(STI) {} 50 51 Register XtensaInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, 52 int &FrameIndex) const { 53 if (MI.getOpcode() == Xtensa::L32I) { 54 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && 55 MI.getOperand(2).getImm() == 0) { 56 FrameIndex = MI.getOperand(1).getIndex(); 57 return MI.getOperand(0).getReg(); 58 } 59 } 60 return Register(); 61 } 62 63 Register XtensaInstrInfo::isStoreToStackSlot(const MachineInstr &MI, 64 int &FrameIndex) const { 65 if (MI.getOpcode() == Xtensa::S32I) { 66 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && 67 MI.getOperand(2).getImm() == 0) { 68 FrameIndex = MI.getOperand(1).getIndex(); 69 return MI.getOperand(0).getReg(); 70 } 71 } 72 return Register(); 73 } 74 75 /// Adjust SP by Amount bytes. 76 void XtensaInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, 77 MachineBasicBlock &MBB, 78 MachineBasicBlock::iterator I) const { 79 DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); 80 81 if (Amount == 0) 82 return; 83 84 MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); 85 const TargetRegisterClass *RC = &Xtensa::ARRegClass; 86 87 // create virtual reg to store immediate 88 unsigned Reg = RegInfo.createVirtualRegister(RC); 89 90 if (isInt<8>(Amount)) { // addi sp, sp, amount 91 BuildMI(MBB, I, DL, get(Xtensa::ADDI), Reg).addReg(SP).addImm(Amount); 92 } else { // Expand immediate that doesn't fit in 8-bit. 93 unsigned Reg1; 94 loadImmediate(MBB, I, &Reg1, Amount); 95 BuildMI(MBB, I, DL, get(Xtensa::ADD), Reg) 96 .addReg(SP) 97 .addReg(Reg1, RegState::Kill); 98 } 99 100 BuildMI(MBB, I, DL, get(Xtensa::OR), SP) 101 .addReg(Reg, RegState::Kill) 102 .addReg(Reg, RegState::Kill); 103 } 104 105 void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 106 MachineBasicBlock::iterator MBBI, 107 const DebugLoc &DL, MCRegister DestReg, 108 MCRegister SrcReg, bool KillSrc) const { 109 // The MOV instruction is not present in core ISA, 110 // so use OR instruction. 111 if (Xtensa::ARRegClass.contains(DestReg, SrcReg)) 112 BuildMI(MBB, MBBI, DL, get(Xtensa::OR), DestReg) 113 .addReg(SrcReg, getKillRegState(KillSrc)) 114 .addReg(SrcReg, getKillRegState(KillSrc)); 115 else 116 report_fatal_error("Impossible reg-to-reg copy"); 117 } 118 119 void XtensaInstrInfo::storeRegToStackSlot( 120 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, 121 bool isKill, int FrameIdx, const TargetRegisterClass *RC, 122 const TargetRegisterInfo *TRI, Register VReg) const { 123 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 124 unsigned LoadOpcode, StoreOpcode; 125 getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx); 126 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, get(StoreOpcode)) 127 .addReg(SrcReg, getKillRegState(isKill)); 128 addFrameReference(MIB, FrameIdx); 129 } 130 131 void XtensaInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 132 MachineBasicBlock::iterator MBBI, 133 Register DestReg, int FrameIdx, 134 const TargetRegisterClass *RC, 135 const TargetRegisterInfo *TRI, 136 Register VReg) const { 137 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 138 unsigned LoadOpcode, StoreOpcode; 139 getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx); 140 addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg), FrameIdx); 141 } 142 143 void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC, 144 unsigned &LoadOpcode, 145 unsigned &StoreOpcode, 146 int64_t offset) const { 147 assert((RC == &Xtensa::ARRegClass) && 148 "Unsupported regclass to load or store"); 149 150 LoadOpcode = Xtensa::L32I; 151 StoreOpcode = Xtensa::S32I; 152 } 153 154 void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB, 155 MachineBasicBlock::iterator MBBI, 156 unsigned *Reg, int64_t Value) const { 157 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 158 MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); 159 const TargetRegisterClass *RC = &Xtensa::ARRegClass; 160 161 // create virtual reg to store immediate 162 *Reg = RegInfo.createVirtualRegister(RC); 163 if (Value >= -2048 && Value <= 2047) { 164 BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Value); 165 } else if (Value >= -32768 && Value <= 32767) { 166 int Low = Value & 0xFF; 167 int High = Value & ~0xFF; 168 169 BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Low); 170 BuildMI(MBB, MBBI, DL, get(Xtensa::ADDMI), *Reg).addReg(*Reg).addImm(High); 171 } else if (Value >= -4294967296LL && Value <= 4294967295LL) { 172 // 32 bit arbitrary constant 173 MachineConstantPool *MCP = MBB.getParent()->getConstantPool(); 174 uint64_t UVal = ((uint64_t)Value) & 0xFFFFFFFFLL; 175 const Constant *CVal = ConstantInt::get( 176 Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), UVal, 177 false); 178 unsigned Idx = MCP->getConstantPoolIndex(CVal, Align(2U)); 179 // MCSymbol MSym 180 BuildMI(MBB, MBBI, DL, get(Xtensa::L32R), *Reg).addConstantPoolIndex(Idx); 181 } else { 182 // use L32R to let assembler load immediate best 183 // TODO replace to L32R 184 report_fatal_error("Unsupported load immediate value"); 185 } 186 } 187