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
25using namespace llvm;
26
27static const MachineInstrBuilder &
28addFrameReference(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(ObjectIdx: FI);
40
41 MachineMemOperand *MMO =
42 MF.getMachineMemOperand(PtrInfo: MachinePointerInfo::getFixedStack(MF, FI, Offset),
43 F: Flags, Size: MFFrame.getObjectSize(ObjectIdx: FI), BaseAlignment: Alignment);
44 return MIB.addFrameIndex(Idx: FI).addImm(Val: Offset).addMemOperand(MMO);
45}
46
47XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget &STI)
48 : XtensaGenInstrInfo(Xtensa::ADJCALLSTACKDOWN, Xtensa::ADJCALLSTACKUP),
49 RI(STI), STI(STI) {}
50
51/// Adjust SP by Amount bytes.
52void XtensaInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
53 MachineBasicBlock &MBB,
54 MachineBasicBlock::iterator I) const {
55 DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
56
57 if (Amount == 0)
58 return;
59
60 MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
61 const TargetRegisterClass *RC = &Xtensa::ARRegClass;
62
63 // create virtual reg to store immediate
64 unsigned Reg = RegInfo.createVirtualRegister(RegClass: RC);
65
66 if (isInt<8>(x: Amount)) { // addi sp, sp, amount
67 BuildMI(MBB, I, DL, get(Xtensa::ADDI), Reg).addReg(SP).addImm(Amount);
68 } else { // Expand immediate that doesn't fit in 8-bit.
69 unsigned Reg1;
70 loadImmediate(MBB, MBBI: I, Reg: &Reg1, Value: Amount);
71 BuildMI(MBB, I, DL, get(Xtensa::ADD), Reg)
72 .addReg(SP)
73 .addReg(Reg1, RegState::Kill);
74 }
75
76 BuildMI(MBB, I, DL, get(Xtensa::OR), SP)
77 .addReg(Reg, RegState::Kill)
78 .addReg(Reg, RegState::Kill);
79}
80
81void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
82 MachineBasicBlock::iterator MBBI,
83 const DebugLoc &DL, MCRegister DestReg,
84 MCRegister SrcReg, bool KillSrc) const {
85 // The MOV instruction is not present in core ISA,
86 // so use OR instruction.
87 if (Xtensa::ARRegClass.contains(DestReg, SrcReg))
88 BuildMI(MBB, MBBI, DL, get(Xtensa::OR), DestReg)
89 .addReg(SrcReg, getKillRegState(KillSrc))
90 .addReg(SrcReg, getKillRegState(KillSrc));
91 else
92 report_fatal_error(reason: "Impossible reg-to-reg copy");
93}
94
95void XtensaInstrInfo::storeRegToStackSlot(
96 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg,
97 bool isKill, int FrameIdx, const TargetRegisterClass *RC,
98 const TargetRegisterInfo *TRI, Register VReg) const {
99 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
100 unsigned LoadOpcode, StoreOpcode;
101 getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, offset: FrameIdx);
102 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, get(StoreOpcode))
103 .addReg(SrcReg, getKillRegState(B: isKill));
104 addFrameReference(MIB, FI: FrameIdx);
105}
106
107void XtensaInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
108 MachineBasicBlock::iterator MBBI,
109 Register DestReg, int FrameIdx,
110 const TargetRegisterClass *RC,
111 const TargetRegisterInfo *TRI,
112 Register VReg) const {
113 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
114 unsigned LoadOpcode, StoreOpcode;
115 getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, offset: FrameIdx);
116 addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg), FrameIdx);
117}
118
119void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
120 unsigned &LoadOpcode,
121 unsigned &StoreOpcode,
122 int64_t offset) const {
123 assert((RC == &Xtensa::ARRegClass) &&
124 "Unsupported regclass to load or store");
125
126 LoadOpcode = Xtensa::L32I;
127 StoreOpcode = Xtensa::S32I;
128}
129
130void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
131 MachineBasicBlock::iterator MBBI,
132 unsigned *Reg, int64_t Value) const {
133 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
134 MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
135 const TargetRegisterClass *RC = &Xtensa::ARRegClass;
136
137 // create virtual reg to store immediate
138 *Reg = RegInfo.createVirtualRegister(RegClass: RC);
139 if (Value >= -2048 && Value <= 2047) {
140 BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Value);
141 } else if (Value >= -32768 && Value <= 32767) {
142 int Low = Value & 0xFF;
143 int High = Value & ~0xFF;
144
145 BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Low);
146 BuildMI(MBB, MBBI, DL, get(Xtensa::ADDMI), *Reg).addReg(*Reg).addImm(High);
147 } else if (Value >= -4294967296LL && Value <= 4294967295LL) {
148 // 32 bit arbirary constant
149 MachineConstantPool *MCP = MBB.getParent()->getConstantPool();
150 uint64_t UVal = ((uint64_t)Value) & 0xFFFFFFFFLL;
151 const Constant *CVal = ConstantInt::get(
152 Ty: Type::getInt32Ty(C&: MBB.getParent()->getFunction().getContext()), V: UVal,
153 IsSigned: false);
154 unsigned Idx = MCP->getConstantPoolIndex(C: CVal, Alignment: Align(2U));
155 // MCSymbol MSym
156 BuildMI(MBB, MBBI, DL, get(Xtensa::L32R), *Reg).addConstantPoolIndex(Idx);
157 } else {
158 // use L32R to let assembler load immediate best
159 // TODO replace to L32R
160 report_fatal_error(reason: "Unsupported load immediate value");
161 }
162}
163

source code of llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp