Files
clang-p2996/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
Andrei Safronov 3dc09fbf29 [Xtensa] Implement THREADPTR and DFPAccel Xtensa Options. (#145543)
Implment base support of the TLS functionality using Xtensa THREADPTR
Option. Implement basic functionality of the DFPAccel Option(registers
support).
2025-07-02 17:47:07 +03:00

311 lines
9.5 KiB
C++

//===-- XtensaMCTargetDesc.cpp - Xtensa target descriptions ---------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "XtensaMCTargetDesc.h"
#include "TargetInfo/XtensaTargetInfo.h"
#include "XtensaInstPrinter.h"
#include "XtensaMCAsmInfo.h"
#include "XtensaTargetStreamer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#define GET_INSTRINFO_MC_DESC
#include "XtensaGenInstrInfo.inc"
#define GET_REGINFO_MC_DESC
#include "XtensaGenRegisterInfo.inc"
#define GET_SUBTARGETINFO_MC_DESC
#include "XtensaGenSubtargetInfo.inc"
using namespace llvm;
bool Xtensa::isValidAddrOffset(int Scale, int64_t OffsetVal) {
bool Valid = false;
switch (Scale) {
case 1:
Valid = (OffsetVal >= 0 && OffsetVal <= 255);
break;
case 2:
Valid = (OffsetVal >= 0 && OffsetVal <= 510) && ((OffsetVal & 0x1) == 0);
break;
case 4:
Valid = (OffsetVal >= 0 && OffsetVal <= 1020) && ((OffsetVal & 0x3) == 0);
break;
default:
break;
}
return Valid;
}
bool Xtensa::isValidAddrOffsetForOpcode(unsigned Opcode, int64_t Offset) {
int Scale = 0;
switch (Opcode) {
case Xtensa::L8UI:
case Xtensa::S8I:
Scale = 1;
break;
case Xtensa::L16SI:
case Xtensa::L16UI:
case Xtensa::S16I:
Scale = 2;
break;
case Xtensa::LEA_ADD:
return (Offset >= -128 && Offset <= 127);
default:
// assume that MI is 32-bit load/store operation
Scale = 4;
break;
}
return isValidAddrOffset(Scale, Offset);
}
// Verify Special Register
bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
RegisterAccessType RAType) {
switch (RegNo) {
case Xtensa::BREG:
return FeatureBits[Xtensa::FeatureBoolean];
case Xtensa::CCOUNT:
case Xtensa::CCOMPARE0:
if (FeatureBits[Xtensa::FeatureTimers1])
return true;
LLVM_FALLTHROUGH;
case Xtensa::CCOMPARE1:
if (FeatureBits[Xtensa::FeatureTimers2])
return true;
LLVM_FALLTHROUGH;
case Xtensa::CCOMPARE2:
if (FeatureBits[Xtensa::FeatureTimers3])
return true;
return false;
case Xtensa::CONFIGID0:
return RAType != Xtensa::REGISTER_EXCHANGE;
case Xtensa::CONFIGID1:
return RAType == Xtensa::REGISTER_READ;
case Xtensa::CPENABLE:
return FeatureBits[Xtensa::FeatureCoprocessor];
case Xtensa::DEBUGCAUSE:
return RAType == Xtensa::REGISTER_READ && FeatureBits[Xtensa::FeatureDebug];
case Xtensa::DEPC:
case Xtensa::EPC1:
case Xtensa::EXCCAUSE:
case Xtensa::EXCSAVE1:
case Xtensa::EXCVADDR:
return FeatureBits[Xtensa::FeatureException];
LLVM_FALLTHROUGH;
case Xtensa::EPC2:
case Xtensa::EPS2:
case Xtensa::EXCSAVE2:
if (FeatureBits[Xtensa::FeatureHighPriInterrupts])
return true;
LLVM_FALLTHROUGH;
case Xtensa::EPC3:
case Xtensa::EPS3:
case Xtensa::EXCSAVE3:
if (FeatureBits[Xtensa::FeatureHighPriInterruptsLevel3])
return true;
LLVM_FALLTHROUGH;
case Xtensa::EPC4:
case Xtensa::EPS4:
case Xtensa::EXCSAVE4:
if (FeatureBits[Xtensa::FeatureHighPriInterruptsLevel4])
return true;
LLVM_FALLTHROUGH;
case Xtensa::EPC5:
case Xtensa::EPS5:
case Xtensa::EXCSAVE5:
if (FeatureBits[Xtensa::FeatureHighPriInterruptsLevel5])
return true;
LLVM_FALLTHROUGH;
case Xtensa::EPC6:
case Xtensa::EPS6:
case Xtensa::EXCSAVE6:
if (FeatureBits[Xtensa::FeatureHighPriInterruptsLevel6])
return true;
LLVM_FALLTHROUGH;
case Xtensa::EPC7:
case Xtensa::EPS7:
case Xtensa::EXCSAVE7:
if (FeatureBits[Xtensa::FeatureHighPriInterruptsLevel7])
return true;
return false;
case Xtensa::INTENABLE:
return FeatureBits[Xtensa::FeatureInterrupt];
case Xtensa::INTERRUPT:
return RAType == Xtensa::REGISTER_READ &&
FeatureBits[Xtensa::FeatureInterrupt];
case Xtensa::INTSET:
case Xtensa::INTCLEAR:
return RAType == Xtensa::REGISTER_WRITE &&
FeatureBits[Xtensa::FeatureInterrupt];
case Xtensa::ICOUNT:
case Xtensa::ICOUNTLEVEL:
case Xtensa::IBREAKENABLE:
case Xtensa::DDR:
case Xtensa::IBREAKA0:
case Xtensa::IBREAKA1:
case Xtensa::DBREAKA0:
case Xtensa::DBREAKA1:
case Xtensa::DBREAKC0:
case Xtensa::DBREAKC1:
return FeatureBits[Xtensa::FeatureDebug];
case Xtensa::LBEG:
case Xtensa::LEND:
case Xtensa::LCOUNT:
return FeatureBits[Xtensa::FeatureLoop];
case Xtensa::LITBASE:
return FeatureBits[Xtensa::FeatureExtendedL32R];
case Xtensa::MEMCTL:
return FeatureBits[Xtensa::FeatureDataCache];
case Xtensa::ACCLO:
case Xtensa::ACCHI:
case Xtensa::M0:
case Xtensa::M1:
case Xtensa::M2:
case Xtensa::M3:
return FeatureBits[Xtensa::FeatureMAC16];
case Xtensa::MISC0:
case Xtensa::MISC1:
case Xtensa::MISC2:
case Xtensa::MISC3:
return FeatureBits[Xtensa::FeatureMiscSR];
case Xtensa::PRID:
return RAType == Xtensa::REGISTER_READ && FeatureBits[Xtensa::FeaturePRID];
case Xtensa::THREADPTR:
return FeatureBits[FeatureTHREADPTR];
case Xtensa::VECBASE:
return FeatureBits[Xtensa::FeatureRelocatableVector];
case Xtensa::FCR:
case Xtensa::FSR:
return FeatureBits[FeatureSingleFloat];
case Xtensa::F64R_LO:
case Xtensa::F64R_HI:
case Xtensa::F64S:
return FeatureBits[FeatureDFPAccel];
case Xtensa::WINDOWBASE:
case Xtensa::WINDOWSTART:
return FeatureBits[Xtensa::FeatureWindowed];
case Xtensa::NoRegister:
return false;
}
return true;
}
// Get Xtensa User Register by encoding value.
MCRegister Xtensa::getUserRegister(unsigned Code, const MCRegisterInfo &MRI) {
MCRegister UserReg = Xtensa::NoRegister;
if (MRI.getEncodingValue(Xtensa::FCR) == Code) {
UserReg = Xtensa::FCR;
} else if (MRI.getEncodingValue(Xtensa::FSR) == Code) {
UserReg = Xtensa::FSR;
} else if (MRI.getEncodingValue(Xtensa::F64R_LO) == Code) {
UserReg = Xtensa::F64R_LO;
} else if (MRI.getEncodingValue(Xtensa::F64R_HI) == Code) {
UserReg = Xtensa::F64R_HI;
} else if (MRI.getEncodingValue(Xtensa::F64S) == Code) {
UserReg = Xtensa::F64S;
} else if (MRI.getEncodingValue(Xtensa::THREADPTR) == Code) {
UserReg = Xtensa::THREADPTR;
}
return UserReg;
}
static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI,
const Triple &TT,
const MCTargetOptions &Options) {
MCAsmInfo *MAI = new XtensaMCAsmInfo(TT);
return MAI;
}
static MCInstrInfo *createXtensaMCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitXtensaMCInstrInfo(X);
return X;
}
static MCInstPrinter *createXtensaMCInstPrinter(const Triple &TT,
unsigned SyntaxVariant,
const MCAsmInfo &MAI,
const MCInstrInfo &MII,
const MCRegisterInfo &MRI) {
return new XtensaInstPrinter(MAI, MII, MRI);
}
static MCRegisterInfo *createXtensaMCRegisterInfo(const Triple &TT) {
MCRegisterInfo *X = new MCRegisterInfo();
InitXtensaMCRegisterInfo(X, Xtensa::SP);
return X;
}
static MCSubtargetInfo *
createXtensaMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
return createXtensaMCSubtargetInfoImpl(TT, CPU, CPU, FS);
}
static MCTargetStreamer *
createXtensaAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
MCInstPrinter *InstPrint) {
return new XtensaTargetAsmStreamer(S, OS);
}
static MCTargetStreamer *
createXtensaObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
return new XtensaTargetELFStreamer(S);
}
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaTargetMC() {
// Register the MCAsmInfo.
TargetRegistry::RegisterMCAsmInfo(getTheXtensaTarget(),
createXtensaMCAsmInfo);
// Register the MCCodeEmitter.
TargetRegistry::RegisterMCCodeEmitter(getTheXtensaTarget(),
createXtensaMCCodeEmitter);
// Register the MCInstrInfo.
TargetRegistry::RegisterMCInstrInfo(getTheXtensaTarget(),
createXtensaMCInstrInfo);
// Register the MCInstPrinter.
TargetRegistry::RegisterMCInstPrinter(getTheXtensaTarget(),
createXtensaMCInstPrinter);
// Register the MCRegisterInfo.
TargetRegistry::RegisterMCRegInfo(getTheXtensaTarget(),
createXtensaMCRegisterInfo);
// Register the MCSubtargetInfo.
TargetRegistry::RegisterMCSubtargetInfo(getTheXtensaTarget(),
createXtensaMCSubtargetInfo);
// Register the MCAsmBackend.
TargetRegistry::RegisterMCAsmBackend(getTheXtensaTarget(),
createXtensaAsmBackend);
// Register the asm target streamer.
TargetRegistry::RegisterAsmTargetStreamer(getTheXtensaTarget(),
createXtensaAsmTargetStreamer);
// Register the ELF target streamer.
TargetRegistry::RegisterObjectTargetStreamer(
getTheXtensaTarget(), createXtensaObjectTargetStreamer);
}