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(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 | |
47 | XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget &STI) |
48 | : XtensaGenInstrInfo(Xtensa::ADJCALLSTACKDOWN, Xtensa::ADJCALLSTACKUP), |
49 | RI(STI), STI(STI) {} |
50 | |
51 | /// Adjust SP by Amount bytes. |
52 | void 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 | |
81 | void 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 | |
95 | void 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 | |
107 | void 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 | |
119 | void 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 | |
130 | void 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 | |