1 //===- XtensaInstrInfo.cpp - Xtensa Instruction Information ---------------===//
3 // The LLVM Compiler Infrastructure
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
9 //===----------------------------------------------------------------------===//
11 // This file contains the Xtensa implementation of the TargetInstrInfo class.
13 //===----------------------------------------------------------------------===//
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"
22 #define GET_INSTRINFO_CTOR_DTOR
23 #include "XtensaGenInstrInfo.inc"
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
;
35 Flags
|= MachineMemOperand::MOLoad
;
37 Flags
|= MachineMemOperand::MOStore
;
39 Align Alignment
= MFFrame
.getObjectAlign(FI
);
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
);
47 XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget
&STI
)
48 : XtensaGenInstrInfo(Xtensa::ADJCALLSTACKDOWN
, Xtensa::ADJCALLSTACKUP
),
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();
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();
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();
84 MachineRegisterInfo
&RegInfo
= MBB
.getParent()->getRegInfo();
85 const TargetRegisterClass
*RC
= &Xtensa::ARRegClass
;
87 // create virtual reg to store immediate
88 unsigned Reg
= RegInfo
.createVirtualRegister(RC
);
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.
94 loadImmediate(MBB
, I
, &Reg1
, Amount
);
95 BuildMI(MBB
, I
, DL
, get(Xtensa::ADD
), Reg
)
97 .addReg(Reg1
, RegState::Kill
);
100 BuildMI(MBB
, I
, DL
, get(Xtensa::OR
), SP
)
101 .addReg(Reg
, RegState::Kill
)
102 .addReg(Reg
, RegState::Kill
);
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
));
116 report_fatal_error("Impossible reg-to-reg copy");
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
);
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
);
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");
150 LoadOpcode
= Xtensa::L32I
;
151 StoreOpcode
= Xtensa::S32I
;
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
;
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;
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
,
178 unsigned Idx
= MCP
->getConstantPoolIndex(CVal
, Align(2U));
180 BuildMI(MBB
, MBBI
, DL
, get(Xtensa::L32R
), *Reg
).addConstantPoolIndex(Idx
);
182 // use L32R to let assembler load immediate best
183 // TODO replace to L32R
184 report_fatal_error("Unsupported load immediate value");