| //===- XtensaInstrInfo.cpp - Xtensa Instruction Information ---------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file contains the Xtensa implementation of the TargetInstrInfo class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "XtensaInstrInfo.h" |
| #include "XtensaTargetMachine.h" |
| #include "llvm/CodeGen/MachineConstantPool.h" |
| #include "llvm/CodeGen/MachineFrameInfo.h" |
| #include "llvm/CodeGen/MachineInstrBuilder.h" |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| |
| #define GET_INSTRINFO_CTOR_DTOR |
| #include "XtensaGenInstrInfo.inc" |
| |
| using namespace llvm; |
| |
| static const MachineInstrBuilder & |
| addFrameReference(const MachineInstrBuilder &MIB, int FI) { |
| MachineInstr *MI = MIB; |
| MachineFunction &MF = *MI->getParent()->getParent(); |
| MachineFrameInfo &MFFrame = MF.getFrameInfo(); |
| const MCInstrDesc &MCID = MI->getDesc(); |
| MachineMemOperand::Flags Flags = MachineMemOperand::MONone; |
| if (MCID.mayLoad()) |
| Flags |= MachineMemOperand::MOLoad; |
| if (MCID.mayStore()) |
| Flags |= MachineMemOperand::MOStore; |
| int64_t Offset = 0; |
| Align Alignment = MFFrame.getObjectAlign(FI); |
| |
| MachineMemOperand *MMO = |
| MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI, Offset), |
| Flags, MFFrame.getObjectSize(FI), Alignment); |
| return MIB.addFrameIndex(FI).addImm(Offset).addMemOperand(MMO); |
| } |
| |
| XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget &STI) |
| : XtensaGenInstrInfo(Xtensa::ADJCALLSTACKDOWN, Xtensa::ADJCALLSTACKUP), |
| RI(STI), STI(STI) {} |
| |
| /// Adjust SP by Amount bytes. |
| void XtensaInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, |
| MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator I) const { |
| DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); |
| |
| if (Amount == 0) |
| return; |
| |
| MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); |
| const TargetRegisterClass *RC = &Xtensa::ARRegClass; |
| |
| // create virtual reg to store immediate |
| unsigned Reg = RegInfo.createVirtualRegister(RC); |
| |
| if (isInt<8>(Amount)) { // addi sp, sp, amount |
| BuildMI(MBB, I, DL, get(Xtensa::ADDI), Reg).addReg(SP).addImm(Amount); |
| } else { // Expand immediate that doesn't fit in 8-bit. |
| unsigned Reg1; |
| loadImmediate(MBB, I, &Reg1, Amount); |
| BuildMI(MBB, I, DL, get(Xtensa::ADD), Reg) |
| .addReg(SP) |
| .addReg(Reg1, RegState::Kill); |
| } |
| |
| BuildMI(MBB, I, DL, get(Xtensa::OR), SP) |
| .addReg(Reg, RegState::Kill) |
| .addReg(Reg, RegState::Kill); |
| } |
| |
| void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MBBI, |
| const DebugLoc &DL, MCRegister DestReg, |
| MCRegister SrcReg, bool KillSrc) const { |
| // The MOV instruction is not present in core ISA, |
| // so use OR instruction. |
| if (Xtensa::ARRegClass.contains(DestReg, SrcReg)) |
| BuildMI(MBB, MBBI, DL, get(Xtensa::OR), DestReg) |
| .addReg(SrcReg, getKillRegState(KillSrc)) |
| .addReg(SrcReg, getKillRegState(KillSrc)); |
| else |
| report_fatal_error("Impossible reg-to-reg copy"); |
| } |
| |
| void XtensaInstrInfo::storeRegToStackSlot( |
| MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, |
| bool isKill, int FrameIdx, const TargetRegisterClass *RC, |
| const TargetRegisterInfo *TRI, Register VReg) const { |
| DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
| unsigned LoadOpcode, StoreOpcode; |
| getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx); |
| MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, get(StoreOpcode)) |
| .addReg(SrcReg, getKillRegState(isKill)); |
| addFrameReference(MIB, FrameIdx); |
| } |
| |
| void XtensaInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MBBI, |
| Register DestReg, int FrameIdx, |
| const TargetRegisterClass *RC, |
| const TargetRegisterInfo *TRI, |
| Register VReg) const { |
| DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
| unsigned LoadOpcode, StoreOpcode; |
| getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx); |
| addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg), FrameIdx); |
| } |
| |
| void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC, |
| unsigned &LoadOpcode, |
| unsigned &StoreOpcode, |
| int64_t offset) const { |
| assert((RC == &Xtensa::ARRegClass) && |
| "Unsupported regclass to load or store"); |
| |
| LoadOpcode = Xtensa::L32I; |
| StoreOpcode = Xtensa::S32I; |
| } |
| |
| void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MBBI, |
| unsigned *Reg, int64_t Value) const { |
| DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
| MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); |
| const TargetRegisterClass *RC = &Xtensa::ARRegClass; |
| |
| // create virtual reg to store immediate |
| *Reg = RegInfo.createVirtualRegister(RC); |
| if (Value >= -2048 && Value <= 2047) { |
| BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Value); |
| } else if (Value >= -32768 && Value <= 32767) { |
| int Low = Value & 0xFF; |
| int High = Value & ~0xFF; |
| |
| BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Low); |
| BuildMI(MBB, MBBI, DL, get(Xtensa::ADDMI), *Reg).addReg(*Reg).addImm(High); |
| } else if (Value >= -4294967296LL && Value <= 4294967295LL) { |
| // 32 bit arbirary constant |
| MachineConstantPool *MCP = MBB.getParent()->getConstantPool(); |
| uint64_t UVal = ((uint64_t)Value) & 0xFFFFFFFFLL; |
| const Constant *CVal = ConstantInt::get( |
| Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), UVal, |
| false); |
| unsigned Idx = MCP->getConstantPoolIndex(CVal, Align(2U)); |
| // MCSymbol MSym |
| BuildMI(MBB, MBBI, DL, get(Xtensa::L32R), *Reg).addConstantPoolIndex(Idx); |
| } else { |
| // use L32R to let assembler load immediate best |
| // TODO replace to L32R |
| report_fatal_error("Unsupported load immediate value"); |
| } |
| } |