1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
//===- 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) {}
Register XtensaInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
if (MI.getOpcode() == Xtensa::L32I) {
if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
FrameIndex = MI.getOperand(1).getIndex();
return MI.getOperand(0).getReg();
}
}
return Register();
}
Register XtensaInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
if (MI.getOpcode() == Xtensa::S32I) {
if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
FrameIndex = MI.getOperand(1).getIndex();
return MI.getOperand(0).getReg();
}
}
return Register();
}
/// 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 arbitrary 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");
}
}
|