Implement base Calling Convention functionality. Implement stack load/store register operations. Implement call lowering.
163 lines
6.6 KiB
C++
163 lines
6.6 KiB
C++
//===- 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) {}
|
|
|
|
/// 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 arbirary 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");
|
|
}
|
|
}
|