xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp (revision b64c5a0ace59af62eff52bfe110a521dc73c937b)
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