aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AVR
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/Target/AVR
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
downloadsrc-vendor/llvm-project/master.tar.gz
src-vendor/llvm-project/master.zip
Vendor import of llvm-project master 2e10b7a39b9, the last commit beforevendor/llvm-project/llvmorg-11-init-20887-g2e10b7a39b9vendor/llvm-project/master
the llvmorg-12-init tag, from which release/11.x was branched.
Notes
Notes: svn path=/vendor/llvm-project/master/; revision=363578 svn path=/vendor/llvm-project/llvmorg-11-init-20887-g2e10b7a39b9/; revision=363579; tag=vendor/llvm-project/llvmorg-11-init-20887-g2e10b7a39b9
Diffstat (limited to 'llvm/lib/Target/AVR')
-rw-r--r--llvm/lib/Target/AVR/AVRAsmPrinter.cpp4
-rw-r--r--llvm/lib/Target/AVR/AVRCallingConv.td18
-rw-r--r--llvm/lib/Target/AVR/AVRDevices.td18
-rw-r--r--llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp276
-rw-r--r--llvm/lib/Target/AVR/AVRFrameLowering.cpp119
-rw-r--r--llvm/lib/Target/AVR/AVRFrameLowering.h4
-rw-r--r--llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp4
-rw-r--r--llvm/lib/Target/AVR/AVRISelLowering.cpp411
-rw-r--r--llvm/lib/Target/AVR/AVRISelLowering.h6
-rw-r--r--llvm/lib/Target/AVR/AVRInstrFormats.td20
-rw-r--r--llvm/lib/Target/AVR/AVRInstrInfo.cpp12
-rw-r--r--llvm/lib/Target/AVR/AVRInstrInfo.h4
-rw-r--r--llvm/lib/Target/AVR/AVRInstrInfo.td70
-rw-r--r--llvm/lib/Target/AVR/AVRMachineFunctionInfo.h20
-rw-r--r--llvm/lib/Target/AVR/AVRRegisterInfo.cpp27
-rw-r--r--llvm/lib/Target/AVR/AVRRegisterInfo.h6
-rw-r--r--llvm/lib/Target/AVR/AVRRegisterInfo.td27
-rw-r--r--llvm/lib/Target/AVR/AVRSubtarget.cpp11
-rw-r--r--llvm/lib/Target/AVR/AVRSubtarget.h19
-rw-r--r--llvm/lib/Target/AVR/AVRTargetMachine.cpp2
-rw-r--r--llvm/lib/Target/AVR/AVRTargetObjectFile.cpp2
-rw-r--r--llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp50
-rw-r--r--llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp159
-rw-r--r--llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp96
-rw-r--r--llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h6
-rw-r--r--llvm/lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h2
-rw-r--r--llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp33
-rw-r--r--llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.h11
-rw-r--r--llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.cpp2
-rw-r--r--llvm/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp4
-rw-r--r--llvm/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.h2
-rw-r--r--llvm/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h3
-rw-r--r--llvm/lib/Target/AVR/MCTargetDesc/AVRTargetStreamer.cpp4
33 files changed, 828 insertions, 624 deletions
diff --git a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
index 9b09c7456543..722eecdc16a1 100644
--- a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
+++ b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
@@ -51,7 +51,7 @@ public:
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
const char *ExtraCode, raw_ostream &O) override;
- void EmitInstruction(const MachineInstr *MI) override;
+ void emitInstruction(const MachineInstr *MI) override;
private:
const MCRegisterInfo &MRI;
@@ -168,7 +168,7 @@ bool AVRAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
return false;
}
-void AVRAsmPrinter::EmitInstruction(const MachineInstr *MI) {
+void AVRAsmPrinter::emitInstruction(const MachineInstr *MI) {
AVRMCInstLower MCInstLowering(OutContext, *this);
MCInst I;
diff --git a/llvm/lib/Target/AVR/AVRCallingConv.td b/llvm/lib/Target/AVR/AVRCallingConv.td
index 213e35fca66d..65545e531a88 100644
--- a/llvm/lib/Target/AVR/AVRCallingConv.td
+++ b/llvm/lib/Target/AVR/AVRCallingConv.td
@@ -6,21 +6,13 @@
//
//===----------------------------------------------------------------------===//
// This describes the calling conventions for AVR architecture.
+// Normal functions use a special calling convention, solved in code.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// AVR Return Value Calling Convention
//===----------------------------------------------------------------------===//
-def RetCC_AVR : CallingConv
-<[
- // i8 is returned in R24.
- CCIfType<[i8], CCAssignToReg<[R24]>>,
-
- // i16 are returned in R25:R24, R23:R22, R21:R20 and R19:R18.
- CCIfType<[i16], CCAssignToReg<[R25R24, R23R22, R21R20, R19R18]>>
-]>;
-
// Special return value calling convention for runtime functions.
def RetCC_AVR_BUILTIN : CallingConv
<[
@@ -41,14 +33,6 @@ def ArgCC_AVR_Vararg : CallingConv
CCAssignToStack<2, 1>
]>;
-// Special argument calling convention for
-// division runtime functions.
-def ArgCC_AVR_BUILTIN_DIV : CallingConv
-<[
- CCIfType<[i8], CCAssignToReg<[R24,R22]>>,
- CCIfType<[i16], CCAssignToReg<[R25R24, R23R22]>>
-]>;
-
//===----------------------------------------------------------------------===//
// Callee-saved register lists.
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AVR/AVRDevices.td b/llvm/lib/Target/AVR/AVRDevices.td
index 62def4574437..6730f2e1673e 100644
--- a/llvm/lib/Target/AVR/AVRDevices.td
+++ b/llvm/lib/Target/AVR/AVRDevices.td
@@ -121,6 +121,11 @@ def FeatureTinyEncoding : SubtargetFeature<"tinyencoding",
"The device has Tiny core specific "
"instruction encodings">;
+// The device has CPU registers mapped in data address space
+def FeatureMMR : SubtargetFeature<"memmappedregs", "m_hasMemMappedGPR",
+ "true", "The device has CPU registers "
+ "mapped in data address space">;
+
class ELFArch<string name> : SubtargetFeature<"", "ELFArch",
!strconcat("ELF::",name), "">;
@@ -152,7 +157,7 @@ def ELFArchXMEGA7 : ELFArch<"EF_AVR_ARCH_XMEGA7">;
// device should have.
def FamilyAVR0 : Family<"avr0", []>;
-def FamilyAVR1 : Family<"avr1", [FamilyAVR0, FeatureLPM]>;
+def FamilyAVR1 : Family<"avr1", [FamilyAVR0, FeatureLPM, FeatureMMR]>;
def FamilyAVR2 : Family<"avr2",
[FamilyAVR1, FeatureIJMPCALL, FeatureADDSUBIW,
@@ -190,11 +195,14 @@ def FamilyAVR6 : Family<"avr6",
def FamilyTiny : Family<"avrtiny",
[FamilyAVR0, FeatureBREAK, FeatureSRAM,
- FeatureTinyEncoding]>;
+ FeatureTinyEncoding, FeatureMMR]>;
def FamilyXMEGA : Family<"xmega",
- [FamilyAVR51, FeatureEIJMPCALL, FeatureSPMX,
- FeatureDES]>;
+ [FamilyAVR0, FeatureLPM, FeatureIJMPCALL, FeatureADDSUBIW,
+ FeatureSRAM, FeatureJMPCALL, FeatureMultiplication,
+ FeatureMOVW, FeatureLPMX, FeatureSPM,
+ FeatureBREAK, FeatureEIJMPCALL, FeatureSPMX,
+ FeatureDES, FeatureELPM, FeatureELPMX]>;
def FamilyXMEGAU : Family<"xmegau",
[FamilyXMEGA, FeatureRMW]>;
@@ -208,7 +216,7 @@ def FeatureSetSpecial : FeatureSet<"special",
FeatureLPM, FeatureLPMX, FeatureELPM,
FeatureELPMX, FeatureSPM, FeatureSPMX,
FeatureDES, FeatureRMW,
- FeatureMultiplication, FeatureBREAK]>;
+ FeatureMultiplication, FeatureBREAK, FeatureMMR]>;
//===---------------------------------------------------------------------===//
// AVR microcontrollers supported.
diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index f466c5c053ad..8ee69201e932 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -51,9 +51,9 @@ private:
const TargetInstrInfo *TII;
/// The register to be used for temporary storage.
- const unsigned SCRATCH_REGISTER = AVR::R0;
+ const Register SCRATCH_REGISTER = AVR::R0;
/// The register that will always contain zero.
- const unsigned ZERO_REGISTER = AVR::R1;
+ const Register ZERO_REGISTER = AVR::R1;
/// The IO address of the status register.
const unsigned SREG_ADDR = 0x3f;
@@ -66,7 +66,7 @@ private:
}
MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode,
- unsigned DstReg) {
+ Register DstReg) {
return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode), DstReg);
}
@@ -91,7 +91,7 @@ private:
BlockIt MBBI);
/// Scavenges a free GPR8 register for use.
- unsigned scavengeGPR8(MachineInstr &MI);
+ Register scavengeGPR8(MachineInstr &MI);
};
char AVRExpandPseudo::ID = 0;
@@ -141,7 +141,7 @@ bool AVRExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
bool AVRExpandPseudo::
expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
+ Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
Register DstReg = MI.getOperand(0).getReg();
Register SrcReg = MI.getOperand(2).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
@@ -174,7 +174,7 @@ expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt MBBI) {
bool AVRExpandPseudo::
expandLogic(unsigned Op, Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
+ Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
Register DstReg = MI.getOperand(0).getReg();
Register SrcReg = MI.getOperand(2).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
@@ -221,7 +221,7 @@ bool AVRExpandPseudo::
bool AVRExpandPseudo::
expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned DstLoReg, DstHiReg;
+ Register DstLoReg, DstHiReg;
Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool SrcIsKill = MI.getOperand(1).isKill();
@@ -273,8 +273,8 @@ bool AVRExpandPseudo::expand<AVR::SUBWRdRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::SUBIWRdK>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool SrcIsKill = MI.getOperand(1).isKill();
bool ImpIsDead = MI.getOperand(3).isDead();
@@ -325,16 +325,16 @@ bool AVRExpandPseudo::expand<AVR::SBCWRdRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::SBCIWRdK>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool SrcIsKill = MI.getOperand(1).isKill();
bool ImpIsDead = MI.getOperand(3).isDead();
unsigned Imm = MI.getOperand(2).getImm();
unsigned Lo8 = Imm & 0xff;
unsigned Hi8 = (Imm >> 8) & 0xff;
- OpLo = AVR::SBCIRdK;
- OpHi = AVR::SBCIRdK;
+ unsigned OpLo = AVR::SBCIRdK;
+ unsigned OpHi = AVR::SBCIRdK;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
auto MIBLO = buildMI(MBB, MBBI, OpLo)
@@ -388,13 +388,13 @@ bool AVRExpandPseudo::expand<AVR::EORWRdRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::COMWRd>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool DstIsKill = MI.getOperand(1).isKill();
bool ImpIsDead = MI.getOperand(2).isDead();
- OpLo = AVR::COMRd;
- OpHi = AVR::COMRd;
+ unsigned OpLo = AVR::COMRd;
+ unsigned OpHi = AVR::COMRd;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
auto MIBLO = buildMI(MBB, MBBI, OpLo)
@@ -418,14 +418,14 @@ bool AVRExpandPseudo::expand<AVR::COMWRd>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::CPWRdRr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
bool DstIsKill = MI.getOperand(0).isKill();
bool SrcIsKill = MI.getOperand(1).isKill();
bool ImpIsDead = MI.getOperand(2).isDead();
- OpLo = AVR::CPRdRr;
- OpHi = AVR::CPCRdRr;
+ unsigned OpLo = AVR::CPRdRr;
+ unsigned OpHi = AVR::CPCRdRr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
@@ -451,14 +451,14 @@ bool AVRExpandPseudo::expand<AVR::CPWRdRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::CPCWRdRr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
bool DstIsKill = MI.getOperand(0).isKill();
bool SrcIsKill = MI.getOperand(1).isKill();
bool ImpIsDead = MI.getOperand(2).isDead();
- OpLo = AVR::CPCRdRr;
- OpHi = AVR::CPCRdRr;
+ unsigned OpLo = AVR::CPCRdRr;
+ unsigned OpHi = AVR::CPCRdRr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
@@ -486,11 +486,11 @@ bool AVRExpandPseudo::expand<AVR::CPCWRdRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::LDIWRdK>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
- OpLo = AVR::LDIRdK;
- OpHi = AVR::LDIRdK;
+ unsigned OpLo = AVR::LDIRdK;
+ unsigned OpHi = AVR::LDIRdK;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
auto MIBLO = buildMI(MBB, MBBI, OpLo)
@@ -535,11 +535,11 @@ bool AVRExpandPseudo::expand<AVR::LDIWRdK>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::LDSWRdK>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
- OpLo = AVR::LDSRdK;
- OpHi = AVR::LDSRdK;
+ unsigned OpLo = AVR::LDSRdK;
+ unsigned OpHi = AVR::LDSRdK;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
auto MIBLO = buildMI(MBB, MBBI, OpLo)
@@ -579,26 +579,26 @@ bool AVRExpandPseudo::expand<AVR::LDSWRdK>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned TmpReg = 0; // 0 for no temporary register
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register TmpReg = 0; // 0 for no temporary register
+ Register SrcReg = MI.getOperand(1).getReg();
bool SrcIsKill = MI.getOperand(1).isKill();
- OpLo = AVR::LDRdPtr;
- OpHi = AVR::LDDRdPtrQ;
+ unsigned OpLo = AVR::LDRdPtr;
+ unsigned OpHi = AVR::LDDRdPtrQ;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
// Use a temporary register if src and dst registers are the same.
if (DstReg == SrcReg)
TmpReg = scavengeGPR8(MI);
- unsigned CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg;
- unsigned CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg;
+ Register CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg;
+ Register CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg;
// Load low byte.
auto MIBLO = buildMI(MBB, MBBI, OpLo)
- .addReg(CurDstLoReg, RegState::Define)
- .addReg(SrcReg, RegState::Define);
+ .addReg(CurDstLoReg, RegState::Define)
+ .addReg(SrcReg);
// Push low byte onto stack if necessary.
if (TmpReg)
@@ -628,13 +628,13 @@ bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::LDWRdPtrPi>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool SrcIsDead = MI.getOperand(1).isKill();
- OpLo = AVR::LDRdPtrPi;
- OpHi = AVR::LDRdPtrPi;
+ unsigned OpLo = AVR::LDRdPtrPi;
+ unsigned OpHi = AVR::LDRdPtrPi;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
@@ -659,13 +659,13 @@ bool AVRExpandPseudo::expand<AVR::LDWRdPtrPi>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::LDWRdPtrPd>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool SrcIsDead = MI.getOperand(1).isKill();
- OpLo = AVR::LDRdPtrPd;
- OpHi = AVR::LDRdPtrPd;
+ unsigned OpLo = AVR::LDRdPtrPd;
+ unsigned OpHi = AVR::LDRdPtrPd;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
@@ -690,14 +690,14 @@ bool AVRExpandPseudo::expand<AVR::LDWRdPtrPd>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned TmpReg = 0; // 0 for no temporary register
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register TmpReg = 0; // 0 for no temporary register
+ Register SrcReg = MI.getOperand(1).getReg();
unsigned Imm = MI.getOperand(2).getImm();
bool SrcIsKill = MI.getOperand(1).isKill();
- OpLo = AVR::LDDRdPtrQ;
- OpHi = AVR::LDDRdPtrQ;
+ unsigned OpLo = AVR::LDDRdPtrQ;
+ unsigned OpHi = AVR::LDDRdPtrQ;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
// Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
@@ -708,8 +708,8 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
if (DstReg == SrcReg)
TmpReg = scavengeGPR8(MI);
- unsigned CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg;
- unsigned CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg;
+ Register CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg;
+ Register CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg;
// Load low byte.
auto MIBLO = buildMI(MBB, MBBI, OpLo)
@@ -745,21 +745,21 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::LPMWRdZ>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned TmpReg = 0; // 0 for no temporary register
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register TmpReg = 0; // 0 for no temporary register
+ Register SrcReg = MI.getOperand(1).getReg();
bool SrcIsKill = MI.getOperand(1).isKill();
- OpLo = AVR::LPMRdZPi;
- OpHi = AVR::LPMRdZ;
+ unsigned OpLo = AVR::LPMRdZPi;
+ unsigned OpHi = AVR::LPMRdZ;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
// Use a temporary register if src and dst registers are the same.
if (DstReg == SrcReg)
TmpReg = scavengeGPR8(MI);
- unsigned CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg;
- unsigned CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg;
+ Register CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg;
+ Register CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg;
// Load low byte.
auto MIBLO = buildMI(MBB, MBBI, OpLo)
@@ -862,7 +862,7 @@ bool AVRExpandPseudo::expandAtomicArithmeticOp(unsigned Width,
});
}
-unsigned AVRExpandPseudo::scavengeGPR8(MachineInstr &MI) {
+Register AVRExpandPseudo::scavengeGPR8(MachineInstr &MI) {
MachineBasicBlock &MBB = *MI.getParent();
RegScavenger RS;
@@ -968,11 +968,11 @@ bool AVRExpandPseudo::expand<AVR::AtomicFence>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::STSWKRr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register SrcLoReg, SrcHiReg;
+ Register SrcReg = MI.getOperand(1).getReg();
bool SrcIsKill = MI.getOperand(1).isKill();
- OpLo = AVR::STSKRr;
- OpHi = AVR::STSKRr;
+ unsigned OpLo = AVR::STSKRr;
+ unsigned OpHi = AVR::STSKRr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
// Write the high byte first in case this address belongs to a special
@@ -1014,12 +1014,12 @@ bool AVRExpandPseudo::expand<AVR::STSWKRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::STWPtrRr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register SrcLoReg, SrcHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
bool SrcIsKill = MI.getOperand(1).isKill();
- OpLo = AVR::STPtrRr;
- OpHi = AVR::STDPtrQRr;
+ unsigned OpLo = AVR::STPtrRr;
+ unsigned OpHi = AVR::STDPtrQRr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
//:TODO: need to reverse this order like inw and stsw?
@@ -1042,14 +1042,14 @@ bool AVRExpandPseudo::expand<AVR::STWPtrRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::STWPtrPiRr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = MI.getOperand(2).getReg();
+ Register SrcLoReg, SrcHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(2).getReg();
unsigned Imm = MI.getOperand(3).getImm();
bool DstIsDead = MI.getOperand(0).isDead();
bool SrcIsKill = MI.getOperand(2).isKill();
- OpLo = AVR::STPtrPiRr;
- OpHi = AVR::STPtrPiRr;
+ unsigned OpLo = AVR::STPtrPiRr;
+ unsigned OpHi = AVR::STPtrPiRr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
@@ -1076,14 +1076,14 @@ bool AVRExpandPseudo::expand<AVR::STWPtrPiRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::STWPtrPdRr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = MI.getOperand(2).getReg();
+ Register SrcLoReg, SrcHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(2).getReg();
unsigned Imm = MI.getOperand(3).getImm();
bool DstIsDead = MI.getOperand(0).isDead();
bool SrcIsKill = MI.getOperand(2).isKill();
- OpLo = AVR::STPtrPdRr;
- OpHi = AVR::STPtrPdRr;
+ unsigned OpLo = AVR::STPtrPdRr;
+ unsigned OpHi = AVR::STPtrPdRr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
@@ -1110,14 +1110,14 @@ bool AVRExpandPseudo::expand<AVR::STWPtrPdRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = MI.getOperand(2).getReg();
+ Register SrcLoReg, SrcHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(2).getReg();
unsigned Imm = MI.getOperand(1).getImm();
bool DstIsKill = MI.getOperand(0).isKill();
bool SrcIsKill = MI.getOperand(2).isKill();
- OpLo = AVR::STDPtrQRr;
- OpHi = AVR::STDPtrQRr;
+ unsigned OpLo = AVR::STDPtrQRr;
+ unsigned OpHi = AVR::STDPtrQRr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
// Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
@@ -1144,12 +1144,12 @@ bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
+ Register DstLoReg, DstHiReg;
unsigned Imm = MI.getOperand(1).getImm();
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
- OpLo = AVR::INRdA;
- OpHi = AVR::INRdA;
+ unsigned OpLo = AVR::INRdA;
+ unsigned OpHi = AVR::INRdA;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
// Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
@@ -1174,12 +1174,12 @@ bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::OUTWARr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
+ Register SrcLoReg, SrcHiReg;
unsigned Imm = MI.getOperand(0).getImm();
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
bool SrcIsKill = MI.getOperand(1).isKill();
- OpLo = AVR::OUTARr;
- OpHi = AVR::OUTARr;
+ unsigned OpLo = AVR::OUTARr;
+ unsigned OpHi = AVR::OUTARr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
// Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
@@ -1205,12 +1205,12 @@ bool AVRExpandPseudo::expand<AVR::OUTWARr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::PUSHWRr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
- unsigned SrcReg = MI.getOperand(0).getReg();
+ Register SrcLoReg, SrcHiReg;
+ Register SrcReg = MI.getOperand(0).getReg();
bool SrcIsKill = MI.getOperand(0).isKill();
unsigned Flags = MI.getFlags();
- OpLo = AVR::PUSHRr;
- OpHi = AVR::PUSHRr;
+ unsigned OpLo = AVR::PUSHRr;
+ unsigned OpHi = AVR::PUSHRr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
// Low part
@@ -1230,11 +1230,11 @@ bool AVRExpandPseudo::expand<AVR::PUSHWRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::POPWRd>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
unsigned Flags = MI.getFlags();
- OpLo = AVR::POPRd;
- OpHi = AVR::POPRd;
+ unsigned OpLo = AVR::POPRd;
+ unsigned OpHi = AVR::POPRd;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
buildMI(MBB, MBBI, OpHi, DstHiReg).setMIFlags(Flags); // High
@@ -1254,7 +1254,7 @@ bool AVRExpandPseudo::expand<AVR::ROLBRd>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
unsigned OpShift, OpCarry;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
OpShift = AVR::ADDRdRr;
OpCarry = AVR::ADCRdRr;
@@ -1291,7 +1291,7 @@ bool AVRExpandPseudo::expand<AVR::RORBRd>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
unsigned OpShiftOut, OpLoad, OpShiftIn, OpAdd;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
OpShiftOut = AVR::LSRRd;
OpLoad = AVR::LDIRdK;
@@ -1334,13 +1334,13 @@ bool AVRExpandPseudo::expand<AVR::RORBRd>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool DstIsKill = MI.getOperand(1).isKill();
bool ImpIsDead = MI.getOperand(2).isDead();
- OpLo = AVR::ADDRdRr; // ADD Rd, Rd <==> LSL Rd
- OpHi = AVR::ADCRdRr; // ADC Rd, Rd <==> ROL Rd
+ unsigned OpLo = AVR::ADDRdRr; // ADD Rd, Rd <==> LSL Rd
+ unsigned OpHi = AVR::ADCRdRr; // ADC Rd, Rd <==> ROL Rd
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
// Low part
@@ -1367,13 +1367,13 @@ bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::LSRWRd>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool DstIsKill = MI.getOperand(1).isKill();
bool ImpIsDead = MI.getOperand(2).isDead();
- OpLo = AVR::RORRd;
- OpHi = AVR::LSRRd;
+ unsigned OpLo = AVR::RORRd;
+ unsigned OpHi = AVR::LSRRd;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
// High part
@@ -1410,13 +1410,13 @@ bool AVRExpandPseudo::expand<AVR::ROLWRd>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::ASRWRd>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool DstIsKill = MI.getOperand(1).isKill();
bool ImpIsDead = MI.getOperand(2).isDead();
- OpLo = AVR::RORRd;
- OpHi = AVR::ASRRd;
+ unsigned OpLo = AVR::RORRd;
+ unsigned OpHi = AVR::ASRRd;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
// High part
@@ -1440,7 +1440,7 @@ bool AVRExpandPseudo::expand<AVR::ASRWRd>(Block &MBB, BlockIt MBBI) {
template <> bool AVRExpandPseudo::expand<AVR::SEXT>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned DstLoReg, DstHiReg;
+ Register DstLoReg, DstHiReg;
// sext R17:R16, R17
// mov r16, r17
// lsl r17
@@ -1454,8 +1454,8 @@ template <> bool AVRExpandPseudo::expand<AVR::SEXT>(Block &MBB, BlockIt MBBI) {
// mov r17, r16
// lsl r17
// sbc r17, r17
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool SrcIsKill = MI.getOperand(1).isKill();
bool ImpIsDead = MI.getOperand(2).isDead();
@@ -1499,7 +1499,7 @@ template <> bool AVRExpandPseudo::expand<AVR::SEXT>(Block &MBB, BlockIt MBBI) {
template <> bool AVRExpandPseudo::expand<AVR::ZEXT>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned DstLoReg, DstHiReg;
+ Register DstLoReg, DstHiReg;
// zext R25:R24, R20
// mov R24, R20
// eor R25, R25
@@ -1508,8 +1508,8 @@ template <> bool AVRExpandPseudo::expand<AVR::ZEXT>(Block &MBB, BlockIt MBBI) {
// zext R25:R24, R25
// mov R24, R25
// eor R25, R25
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
bool SrcIsKill = MI.getOperand(1).isKill();
bool ImpIsDead = MI.getOperand(2).isDead();
@@ -1536,12 +1536,12 @@ template <> bool AVRExpandPseudo::expand<AVR::ZEXT>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::SPREAD>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned OpLo, OpHi, DstLoReg, DstHiReg;
- unsigned DstReg = MI.getOperand(0).getReg();
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
unsigned Flags = MI.getFlags();
- OpLo = AVR::INRdA;
- OpHi = AVR::INRdA;
+ unsigned OpLo = AVR::INRdA;
+ unsigned OpHi = AVR::INRdA;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
// Low part
@@ -1563,8 +1563,8 @@ bool AVRExpandPseudo::expand<AVR::SPREAD>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- unsigned SrcLoReg, SrcHiReg;
- unsigned SrcReg = MI.getOperand(1).getReg();
+ Register SrcLoReg, SrcHiReg;
+ Register SrcReg = MI.getOperand(1).getReg();
bool SrcIsKill = MI.getOperand(1).isKill();
unsigned Flags = MI.getFlags();
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
diff --git a/llvm/lib/Target/AVR/AVRFrameLowering.cpp b/llvm/lib/Target/AVR/AVRFrameLowering.cpp
index e6c48de5a782..c95a553b86ac 100644
--- a/llvm/lib/Target/AVR/AVRFrameLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRFrameLowering.cpp
@@ -30,8 +30,7 @@
namespace llvm {
AVRFrameLowering::AVRFrameLowering()
- : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align::None(),
- -2) {}
+ : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(1), -2) {}
bool AVRFrameLowering::canSimplifyCallFramePseudos(
const MachineFunction &MF) const {
@@ -53,30 +52,22 @@ bool AVRFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
void AVRFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator MBBI = MBB.begin();
- CallingConv::ID CallConv = MF.getFunction().getCallingConv();
DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
const AVRInstrInfo &TII = *STI.getInstrInfo();
+ const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
bool HasFP = hasFP(MF);
// Interrupt handlers re-enable interrupts in function entry.
- if (CallConv == CallingConv::AVR_INTR) {
+ if (AFI->isInterruptHandler()) {
BuildMI(MBB, MBBI, DL, TII.get(AVR::BSETs))
.addImm(0x07)
.setMIFlag(MachineInstr::FrameSetup);
}
- // Save the frame pointer if we have one.
- if (HasFP) {
- BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
- .addReg(AVR::R29R28, RegState::Kill)
- .setMIFlag(MachineInstr::FrameSetup);
- }
-
// Emit special prologue code to save R1, R0 and SREG in interrupt/signal
// handlers before saving any other registers.
- if (CallConv == CallingConv::AVR_INTR ||
- CallConv == CallingConv::AVR_SIGNAL) {
+ if (AFI->isInterruptOrSignalHandler()) {
BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
.addReg(AVR::R1R0, RegState::Kill)
.setMIFlag(MachineInstr::FrameSetup);
@@ -100,7 +91,6 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
}
const MachineFrameInfo &MFI = MF.getFrameInfo();
- const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
unsigned FrameSize = MFI.getStackSize() - AFI->getCalleeSavedFrameSize();
// Skip the callee-saved push instructions.
@@ -143,13 +133,11 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
- CallingConv::ID CallConv = MF.getFunction().getCallingConv();
- bool isHandler = (CallConv == CallingConv::AVR_INTR ||
- CallConv == CallingConv::AVR_SIGNAL);
+ const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
// Early exit if the frame pointer is not needed in this function except for
// signal/interrupt handlers where special code generation is required.
- if (!hasFP(MF) && !isHandler) {
+ if (!hasFP(MF) && !AFI->isInterruptOrSignalHandler()) {
return;
}
@@ -159,14 +147,13 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
DebugLoc DL = MBBI->getDebugLoc();
const MachineFrameInfo &MFI = MF.getFrameInfo();
- const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
unsigned FrameSize = MFI.getStackSize() - AFI->getCalleeSavedFrameSize();
const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
const AVRInstrInfo &TII = *STI.getInstrInfo();
// Emit special epilogue code to restore R1, R0 and SREG in interrupt/signal
// handlers at the very end of the function, just before reti.
- if (isHandler) {
+ if (AFI->isInterruptOrSignalHandler()) {
BuildMI(MBB, MBBI, DL, TII.get(AVR::POPRd), AVR::R0);
BuildMI(MBB, MBBI, DL, TII.get(AVR::OUTARr))
.addImm(0x3f)
@@ -174,9 +161,6 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R1R0);
}
- if (hasFP(MF))
- BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R29R28);
-
// Early exit if there is no need to restore the frame pointer.
if (!FrameSize) {
return;
@@ -234,8 +218,7 @@ bool AVRFrameLowering::hasFP(const MachineFunction &MF) const {
bool AVRFrameLowering::spillCalleeSavedRegisters(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) const {
+ ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
if (CSI.empty()) {
return false;
}
@@ -275,8 +258,7 @@ bool AVRFrameLowering::spillCalleeSavedRegisters(
bool AVRFrameLowering::restoreCalleeSavedRegisters(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
- std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) const {
+ MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
if (CSI.empty()) {
return false;
}
@@ -299,15 +281,10 @@ bool AVRFrameLowering::restoreCalleeSavedRegisters(
}
/// Replace pseudo store instructions that pass arguments through the stack with
-/// real instructions. If insertPushes is true then all instructions are
-/// replaced with push instructions, otherwise regular std instructions are
-/// inserted.
+/// real instructions.
static void fixStackStores(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
- const TargetInstrInfo &TII, bool insertPushes) {
- const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
- const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
-
+ const TargetInstrInfo &TII, Register FP) {
// Iterate through the BB until we hit a call instruction or we reach the end.
for (auto I = MI, E = MBB.end(); I != E && !I->isCall();) {
MachineBasicBlock::iterator NextMI = std::next(I);
@@ -322,29 +299,6 @@ static void fixStackStores(MachineBasicBlock &MBB,
assert(MI.getOperand(0).getReg() == AVR::SP &&
"Invalid register, should be SP!");
- if (insertPushes) {
- // Replace this instruction with a push.
- Register SrcReg = MI.getOperand(2).getReg();
- bool SrcIsKill = MI.getOperand(2).isKill();
-
- // We can't use PUSHWRr here because when expanded the order of the new
- // instructions are reversed from what we need. Perform the expansion now.
- if (Opcode == AVR::STDWSPQRr) {
- BuildMI(MBB, I, MI.getDebugLoc(), TII.get(AVR::PUSHRr))
- .addReg(TRI.getSubReg(SrcReg, AVR::sub_hi),
- getKillRegState(SrcIsKill));
- BuildMI(MBB, I, MI.getDebugLoc(), TII.get(AVR::PUSHRr))
- .addReg(TRI.getSubReg(SrcReg, AVR::sub_lo),
- getKillRegState(SrcIsKill));
- } else {
- BuildMI(MBB, I, MI.getDebugLoc(), TII.get(AVR::PUSHRr))
- .addReg(SrcReg, getKillRegState(SrcIsKill));
- }
-
- MI.eraseFromParent();
- I = NextMI;
- continue;
- }
// Replace this instruction with a regular store. Use Y as the base
// pointer since it is guaranteed to contain a copy of SP.
@@ -352,7 +306,7 @@ static void fixStackStores(MachineBasicBlock &MBB,
(Opcode == AVR::STDWSPQRr) ? AVR::STDWPtrQRr : AVR::STDPtrQRr;
MI.setDesc(TII.get(STOpc));
- MI.getOperand(0).setReg(AVR::R29R28);
+ MI.getOperand(0).setReg(FP);
I = NextMI;
}
@@ -368,7 +322,7 @@ MachineBasicBlock::iterator AVRFrameLowering::eliminateCallFramePseudoInstr(
// function entry. Delete the call frame pseudo and replace all pseudo stores
// with real store instructions.
if (hasReservedCallFrame(MF)) {
- fixStackStores(MBB, MI, TII, false);
+ fixStackStores(MBB, MI, TII, AVR::R29R28);
return MBB.erase(MI);
}
@@ -376,18 +330,37 @@ MachineBasicBlock::iterator AVRFrameLowering::eliminateCallFramePseudoInstr(
unsigned int Opcode = MI->getOpcode();
int Amount = TII.getFrameSize(*MI);
- // Adjcallstackup does not need to allocate stack space for the call, instead
- // we insert push instructions that will allocate the necessary stack.
- // For adjcallstackdown we convert it into an 'adiw reg, <amt>' handling
- // the read and write of SP in I/O space.
+ // ADJCALLSTACKUP and ADJCALLSTACKDOWN are converted to adiw/subi
+ // instructions to read and write the stack pointer in I/O space.
if (Amount != 0) {
- assert(getStackAlignment() == 1 && "Unsupported stack alignment");
+ assert(getStackAlign() == Align(1) && "Unsupported stack alignment");
if (Opcode == TII.getCallFrameSetupOpcode()) {
- fixStackStores(MBB, MI, TII, true);
+ // Update the stack pointer.
+ // In many cases this can be done far more efficiently by pushing the
+ // relevant values directly to the stack. However, doing that correctly
+ // (in the right order, possibly skipping some empty space for undef
+ // values, etc) is tricky and thus left to be optimized in the future.
+ BuildMI(MBB, MI, DL, TII.get(AVR::SPREAD), AVR::R31R30).addReg(AVR::SP);
+
+ MachineInstr *New = BuildMI(MBB, MI, DL, TII.get(AVR::SUBIWRdK), AVR::R31R30)
+ .addReg(AVR::R31R30, RegState::Kill)
+ .addImm(Amount);
+ New->getOperand(3).setIsDead();
+
+ BuildMI(MBB, MI, DL, TII.get(AVR::SPWRITE), AVR::SP)
+ .addReg(AVR::R31R30, RegState::Kill);
+
+ // Make sure the remaining stack stores are converted to real store
+ // instructions.
+ fixStackStores(MBB, MI, TII, AVR::R31R30);
} else {
assert(Opcode == TII.getCallFrameDestroyOpcode());
+ // Note that small stack changes could be implemented more efficiently
+ // with a few pop instructions instead of the 8-9 instructions now
+ // required.
+
// Select the best opcode to adjust SP based on the offset size.
unsigned addOpcode;
if (isUInt<6>(Amount)) {
@@ -419,8 +392,10 @@ void AVRFrameLowering::determineCalleeSaves(MachineFunction &MF,
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
// If we have a frame pointer, the Y register needs to be saved as well.
- // We don't do that here however - the prologue and epilogue generation
- // code will handle it specially.
+ if (hasFP(MF)) {
+ SavedRegs.set(AVR::R29);
+ SavedRegs.set(AVR::R28);
+ }
}
/// The frame analyzer pass.
///
@@ -430,7 +405,7 @@ struct AVRFrameAnalyzer : public MachineFunctionPass {
static char ID;
AVRFrameAnalyzer() : MachineFunctionPass(ID) {}
- bool runOnMachineFunction(MachineFunction &MF) {
+ bool runOnMachineFunction(MachineFunction &MF) override {
const MachineFrameInfo &MFI = MF.getFrameInfo();
AVRMachineFunctionInfo *FuncInfo = MF.getInfo<AVRMachineFunctionInfo>();
@@ -482,7 +457,7 @@ struct AVRFrameAnalyzer : public MachineFunctionPass {
return false;
}
- StringRef getPassName() const { return "AVR Frame Analyzer"; }
+ StringRef getPassName() const override { return "AVR Frame Analyzer"; }
};
char AVRFrameAnalyzer::ID = 0;
@@ -498,7 +473,7 @@ struct AVRDynAllocaSR : public MachineFunctionPass {
static char ID;
AVRDynAllocaSR() : MachineFunctionPass(ID) {}
- bool runOnMachineFunction(MachineFunction &MF) {
+ bool runOnMachineFunction(MachineFunction &MF) override {
// Early exit when there are no variable sized objects in the function.
if (!MF.getFrameInfo().hasVarSizedObjects()) {
return false;
@@ -510,7 +485,7 @@ struct AVRDynAllocaSR : public MachineFunctionPass {
MachineBasicBlock::iterator MBBI = EntryMBB.begin();
DebugLoc DL = EntryMBB.findDebugLoc(MBBI);
- unsigned SPCopy =
+ Register SPCopy =
MF.getRegInfo().createVirtualRegister(&AVR::DREGSRegClass);
// Create a copy of SP in function entry before any dynallocas are
@@ -531,7 +506,7 @@ struct AVRDynAllocaSR : public MachineFunctionPass {
return true;
}
- StringRef getPassName() const {
+ StringRef getPassName() const override {
return "AVR dynalloca stack pointer save/restore";
}
};
diff --git a/llvm/lib/Target/AVR/AVRFrameLowering.h b/llvm/lib/Target/AVR/AVRFrameLowering.h
index a7658438232a..a550c0efbb8e 100644
--- a/llvm/lib/Target/AVR/AVRFrameLowering.h
+++ b/llvm/lib/Target/AVR/AVRFrameLowering.h
@@ -24,12 +24,12 @@ public:
bool hasFP(const MachineFunction &MF) const override;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI,
+ ArrayRef<CalleeSavedInfo> CSI,
const TargetRegisterInfo *TRI) const override;
bool
restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
- std::vector<CalleeSavedInfo> &CSI,
+ MutableArrayRef<CalleeSavedInfo> CSI,
const TargetRegisterInfo *TRI) const override;
bool hasReservedCallFrame(const MachineFunction &MF) const override;
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;
diff --git a/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp b/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
index 4c4f4faa0508..fe31fa42c403 100644
--- a/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
@@ -265,7 +265,7 @@ bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
if (RI.getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) {
SDLoc dl(CopyFromRegOp);
- unsigned VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
+ Register VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
SDValue CopyToReg =
CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp);
@@ -294,7 +294,7 @@ bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
// More generic case.
// Create chain that puts Op into pointer register
// and return that register.
- unsigned VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
+ Register VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
SDValue CopyToReg = CurDAG->getCopyToReg(Op, dl, VReg, Op);
SDValue CopyFromReg =
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp
index 880688807702..bf9b32e1278e 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp
@@ -14,6 +14,7 @@
#include "AVRISelLowering.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -151,10 +152,12 @@ AVRTargetLowering::AVRTargetLowering(const AVRTargetMachine &TM,
setOperationAction(ISD::SREM, MVT::i16, Expand);
// Make division and modulus custom
- for (MVT VT : MVT::integer_valuetypes()) {
- setOperationAction(ISD::UDIVREM, VT, Custom);
- setOperationAction(ISD::SDIVREM, VT, Custom);
- }
+ setOperationAction(ISD::UDIVREM, MVT::i8, Custom);
+ setOperationAction(ISD::UDIVREM, MVT::i16, Custom);
+ setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
+ setOperationAction(ISD::SDIVREM, MVT::i8, Custom);
+ setOperationAction(ISD::SDIVREM, MVT::i16, Custom);
+ setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
// Do not use MUL. The AVR instructions are closer to SMUL_LOHI &co.
setOperationAction(ISD::MUL, MVT::i8, Expand);
@@ -190,41 +193,29 @@ AVRTargetLowering::AVRTargetLowering(const AVRTargetMachine &TM,
// improvements in how we treat 16-bit "registers" to be feasible.
}
- // Division rtlib functions (not supported)
+ // Division rtlib functions (not supported), use divmod functions instead
setLibcallName(RTLIB::SDIV_I8, nullptr);
setLibcallName(RTLIB::SDIV_I16, nullptr);
setLibcallName(RTLIB::SDIV_I32, nullptr);
- setLibcallName(RTLIB::SDIV_I64, nullptr);
- setLibcallName(RTLIB::SDIV_I128, nullptr);
setLibcallName(RTLIB::UDIV_I8, nullptr);
setLibcallName(RTLIB::UDIV_I16, nullptr);
setLibcallName(RTLIB::UDIV_I32, nullptr);
- setLibcallName(RTLIB::UDIV_I64, nullptr);
- setLibcallName(RTLIB::UDIV_I128, nullptr);
- // Modulus rtlib functions (not supported)
+ // Modulus rtlib functions (not supported), use divmod functions instead
setLibcallName(RTLIB::SREM_I8, nullptr);
setLibcallName(RTLIB::SREM_I16, nullptr);
setLibcallName(RTLIB::SREM_I32, nullptr);
- setLibcallName(RTLIB::SREM_I64, nullptr);
- setLibcallName(RTLIB::SREM_I128, nullptr);
setLibcallName(RTLIB::UREM_I8, nullptr);
setLibcallName(RTLIB::UREM_I16, nullptr);
setLibcallName(RTLIB::UREM_I32, nullptr);
- setLibcallName(RTLIB::UREM_I64, nullptr);
- setLibcallName(RTLIB::UREM_I128, nullptr);
// Division and modulus rtlib functions
setLibcallName(RTLIB::SDIVREM_I8, "__divmodqi4");
setLibcallName(RTLIB::SDIVREM_I16, "__divmodhi4");
setLibcallName(RTLIB::SDIVREM_I32, "__divmodsi4");
- setLibcallName(RTLIB::SDIVREM_I64, "__divmoddi4");
- setLibcallName(RTLIB::SDIVREM_I128, "__divmodti4");
setLibcallName(RTLIB::UDIVREM_I8, "__udivmodqi4");
setLibcallName(RTLIB::UDIVREM_I16, "__udivmodhi4");
setLibcallName(RTLIB::UDIVREM_I32, "__udivmodsi4");
- setLibcallName(RTLIB::UDIVREM_I64, "__udivmoddi4");
- setLibcallName(RTLIB::UDIVREM_I128, "__udivmodti4");
// Several of the runtime library functions use a special calling conv
setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::AVR_BUILTIN);
@@ -259,6 +250,8 @@ const char *AVRTargetLowering::getTargetNodeName(unsigned Opcode) const {
NODE(ASR);
NODE(LSLLOOP);
NODE(LSRLOOP);
+ NODE(ROLLOOP);
+ NODE(RORLOOP);
NODE(ASRLOOP);
NODE(BRCOND);
NODE(CMP);
@@ -282,6 +275,8 @@ SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
const SDNode *N = Op.getNode();
EVT VT = Op.getValueType();
SDLoc dl(N);
+ assert(isPowerOf2_32(VT.getSizeInBits()) &&
+ "Expected power-of-2 shift amount");
// Expand non-constant shifts to loops.
if (!isa<ConstantSDNode>(N->getOperand(1))) {
@@ -294,12 +289,20 @@ SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
case ISD::SRL:
return DAG.getNode(AVRISD::LSRLOOP, dl, VT, N->getOperand(0),
N->getOperand(1));
- case ISD::ROTL:
- return DAG.getNode(AVRISD::ROLLOOP, dl, VT, N->getOperand(0),
- N->getOperand(1));
- case ISD::ROTR:
- return DAG.getNode(AVRISD::RORLOOP, dl, VT, N->getOperand(0),
- N->getOperand(1));
+ case ISD::ROTL: {
+ SDValue Amt = N->getOperand(1);
+ EVT AmtVT = Amt.getValueType();
+ Amt = DAG.getNode(ISD::AND, dl, AmtVT, Amt,
+ DAG.getConstant(VT.getSizeInBits() - 1, dl, AmtVT));
+ return DAG.getNode(AVRISD::ROLLOOP, dl, VT, N->getOperand(0), Amt);
+ }
+ case ISD::ROTR: {
+ SDValue Amt = N->getOperand(1);
+ EVT AmtVT = Amt.getValueType();
+ Amt = DAG.getNode(ISD::AND, dl, AmtVT, Amt,
+ DAG.getConstant(VT.getSizeInBits() - 1, dl, AmtVT));
+ return DAG.getNode(AVRISD::RORLOOP, dl, VT, N->getOperand(0), Amt);
+ }
case ISD::SRA:
return DAG.getNode(AVRISD::ASRLOOP, dl, VT, N->getOperand(0),
N->getOperand(1));
@@ -315,9 +318,11 @@ SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
break;
case ISD::ROTL:
Opc8 = AVRISD::ROL;
+ ShiftAmount = ShiftAmount % VT.getSizeInBits();
break;
case ISD::ROTR:
Opc8 = AVRISD::ROR;
+ ShiftAmount = ShiftAmount % VT.getSizeInBits();
break;
case ISD::SRL:
Opc8 = AVRISD::LSR;
@@ -357,12 +362,6 @@ SDValue AVRTargetLowering::LowerDivRem(SDValue Op, SelectionDAG &DAG) const {
case MVT::i32:
LC = IsSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
- case MVT::i64:
- LC = IsSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
- break;
- case MVT::i128:
- LC = IsSigned ? RTLIB::SDIVREM_I128 : RTLIB::UDIVREM_I128;
- break;
}
SDValue InChain = DAG.getEntryNode();
@@ -883,173 +882,145 @@ bool AVRTargetLowering::isOffsetFoldingLegal(
#include "AVRGenCallingConv.inc"
-/// For each argument in a function store the number of pieces it is composed
-/// of.
-static void parseFunctionArgs(const SmallVectorImpl<ISD::InputArg> &Ins,
- SmallVectorImpl<unsigned> &Out) {
- for (const ISD::InputArg &Arg : Ins) {
- if(Arg.PartOffset > 0) continue;
- unsigned Bytes = ((Arg.ArgVT.getSizeInBits()) + 7) / 8;
-
- Out.push_back((Bytes + 1) / 2);
- }
-}
-
-/// For external symbols there is no function prototype information so we
-/// have to rely directly on argument sizes.
-static void parseExternFuncCallArgs(const SmallVectorImpl<ISD::OutputArg> &In,
- SmallVectorImpl<unsigned> &Out) {
- for (unsigned i = 0, e = In.size(); i != e;) {
- unsigned Size = 0;
- unsigned Offset = 0;
- while ((i != e) && (In[i].PartOffset == Offset)) {
- Offset += In[i].VT.getStoreSize();
- ++i;
- ++Size;
- }
- Out.push_back(Size);
- }
-}
-
-static StringRef getFunctionName(TargetLowering::CallLoweringInfo &CLI) {
- SDValue Callee = CLI.Callee;
-
- if (const ExternalSymbolSDNode *G = dyn_cast<ExternalSymbolSDNode>(Callee)) {
- return G->getSymbol();
- }
-
- if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- return G->getGlobal()->getName();
- }
-
- llvm_unreachable("don't know how to get the name for this callee");
-}
+/// Registers for calling conventions, ordered in reverse as required by ABI.
+/// Both arrays must be of the same length.
+static const MCPhysReg RegList8[] = {
+ AVR::R25, AVR::R24, AVR::R23, AVR::R22, AVR::R21, AVR::R20,
+ AVR::R19, AVR::R18, AVR::R17, AVR::R16, AVR::R15, AVR::R14,
+ AVR::R13, AVR::R12, AVR::R11, AVR::R10, AVR::R9, AVR::R8};
+static const MCPhysReg RegList16[] = {
+ AVR::R26R25, AVR::R25R24, AVR::R24R23, AVR::R23R22,
+ AVR::R22R21, AVR::R21R20, AVR::R20R19, AVR::R19R18,
+ AVR::R18R17, AVR::R17R16, AVR::R16R15, AVR::R15R14,
+ AVR::R14R13, AVR::R13R12, AVR::R12R11, AVR::R11R10,
+ AVR::R10R9, AVR::R9R8};
+
+static_assert(array_lengthof(RegList8) == array_lengthof(RegList16),
+ "8-bit and 16-bit register arrays must be of equal length");
/// Analyze incoming and outgoing function arguments. We need custom C++ code
-/// to handle special constraints in the ABI like reversing the order of the
-/// pieces of splitted arguments. In addition, all pieces of a certain argument
-/// have to be passed either using registers or the stack but never mixing both.
-static void analyzeStandardArguments(TargetLowering::CallLoweringInfo *CLI,
- const Function *F, const DataLayout *TD,
- const SmallVectorImpl<ISD::OutputArg> *Outs,
- const SmallVectorImpl<ISD::InputArg> *Ins,
- CallingConv::ID CallConv,
- SmallVectorImpl<CCValAssign> &ArgLocs,
- CCState &CCInfo, bool IsCall, bool IsVarArg) {
- static const MCPhysReg RegList8[] = {AVR::R24, AVR::R22, AVR::R20,
- AVR::R18, AVR::R16, AVR::R14,
- AVR::R12, AVR::R10, AVR::R8};
- static const MCPhysReg RegList16[] = {AVR::R25R24, AVR::R23R22, AVR::R21R20,
- AVR::R19R18, AVR::R17R16, AVR::R15R14,
- AVR::R13R12, AVR::R11R10, AVR::R9R8};
- if (IsVarArg) {
- // Variadic functions do not need all the analysis below.
- if (IsCall) {
- CCInfo.AnalyzeCallOperands(*Outs, ArgCC_AVR_Vararg);
- } else {
- CCInfo.AnalyzeFormalArguments(*Ins, ArgCC_AVR_Vararg);
+/// to handle special constraints in the ABI.
+/// In addition, all pieces of a certain argument have to be passed either
+/// using registers or the stack but never mixing both.
+template <typename ArgT>
+static void
+analyzeArguments(TargetLowering::CallLoweringInfo *CLI, const Function *F,
+ const DataLayout *TD, const SmallVectorImpl<ArgT> &Args,
+ SmallVectorImpl<CCValAssign> &ArgLocs, CCState &CCInfo) {
+ unsigned NumArgs = Args.size();
+ // This is the index of the last used register, in RegList*.
+ // -1 means R26 (R26 is never actually used in CC).
+ int RegLastIdx = -1;
+ // Once a value is passed to the stack it will always be used
+ bool UseStack = false;
+ for (unsigned i = 0; i != NumArgs;) {
+ MVT VT = Args[i].VT;
+ // We have to count the number of bytes for each function argument, that is
+ // those Args with the same OrigArgIndex. This is important in case the
+ // function takes an aggregate type.
+ // Current argument will be between [i..j).
+ unsigned ArgIndex = Args[i].OrigArgIndex;
+ unsigned TotalBytes = VT.getStoreSize();
+ unsigned j = i + 1;
+ for (; j != NumArgs; ++j) {
+ if (Args[j].OrigArgIndex != ArgIndex)
+ break;
+ TotalBytes += Args[j].VT.getStoreSize();
}
- return;
- }
-
- // Fill in the Args array which will contain original argument sizes.
- SmallVector<unsigned, 8> Args;
- if (IsCall) {
- parseExternFuncCallArgs(*Outs, Args);
- } else {
- assert(F != nullptr && "function should not be null");
- parseFunctionArgs(*Ins, Args);
- }
-
- unsigned RegsLeft = array_lengthof(RegList8), ValNo = 0;
- // Variadic functions always use the stack.
- bool UsesStack = false;
- for (unsigned i = 0, pos = 0, e = Args.size(); i != e; ++i) {
- unsigned Size = Args[i];
-
- // If we have a zero-sized argument, don't attempt to lower it.
- // AVR-GCC does not support zero-sized arguments and so we need not
- // worry about ABI compatibility.
- if (Size == 0) continue;
-
- MVT LocVT = (IsCall) ? (*Outs)[pos].VT : (*Ins)[pos].VT;
-
- // If we have plenty of regs to pass the whole argument do it.
- if (!UsesStack && (Size <= RegsLeft)) {
- const MCPhysReg *RegList = (LocVT == MVT::i16) ? RegList16 : RegList8;
+ // Round up to even number of bytes.
+ TotalBytes = alignTo(TotalBytes, 2);
+ // Skip zero sized arguments
+ if (TotalBytes == 0)
+ continue;
+ // The index of the first register to be used
+ unsigned RegIdx = RegLastIdx + TotalBytes;
+ RegLastIdx = RegIdx;
+ // If there are not enough registers, use the stack
+ if (RegIdx >= array_lengthof(RegList8)) {
+ UseStack = true;
+ }
+ for (; i != j; ++i) {
+ MVT VT = Args[i].VT;
- for (unsigned j = 0; j != Size; ++j) {
- unsigned Reg = CCInfo.AllocateReg(
- ArrayRef<MCPhysReg>(RegList, array_lengthof(RegList8)));
+ if (UseStack) {
+ auto evt = EVT(VT).getTypeForEVT(CCInfo.getContext());
+ unsigned Offset = CCInfo.AllocateStack(TD->getTypeAllocSize(evt),
+ TD->getABITypeAlign(evt));
CCInfo.addLoc(
- CCValAssign::getReg(ValNo++, LocVT, Reg, LocVT, CCValAssign::Full));
- --RegsLeft;
- }
-
- // Reverse the order of the pieces to agree with the "big endian" format
- // required in the calling convention ABI.
- std::reverse(ArgLocs.begin() + pos, ArgLocs.begin() + pos + Size);
- } else {
- // Pass the rest of arguments using the stack.
- UsesStack = true;
- for (unsigned j = 0; j != Size; ++j) {
- unsigned Offset = CCInfo.AllocateStack(
- TD->getTypeAllocSize(EVT(LocVT).getTypeForEVT(CCInfo.getContext())),
- TD->getABITypeAlignment(
- EVT(LocVT).getTypeForEVT(CCInfo.getContext())));
- CCInfo.addLoc(CCValAssign::getMem(ValNo++, LocVT, Offset, LocVT,
- CCValAssign::Full));
+ CCValAssign::getMem(i, VT, Offset, VT, CCValAssign::Full));
+ } else {
+ unsigned Reg;
+ if (VT == MVT::i8) {
+ Reg = CCInfo.AllocateReg(RegList8[RegIdx]);
+ } else if (VT == MVT::i16) {
+ Reg = CCInfo.AllocateReg(RegList16[RegIdx]);
+ } else {
+ llvm_unreachable(
+ "calling convention can only manage i8 and i16 types");
+ }
+ assert(Reg && "register not available in calling convention");
+ CCInfo.addLoc(CCValAssign::getReg(i, VT, Reg, VT, CCValAssign::Full));
+ // Registers inside a particular argument are sorted in increasing order
+ // (remember the array is reversed).
+ RegIdx -= VT.getStoreSize();
}
}
- pos += Size;
}
}
-static void analyzeBuiltinArguments(TargetLowering::CallLoweringInfo &CLI,
- const Function *F, const DataLayout *TD,
- const SmallVectorImpl<ISD::OutputArg> *Outs,
- const SmallVectorImpl<ISD::InputArg> *Ins,
- CallingConv::ID CallConv,
- SmallVectorImpl<CCValAssign> &ArgLocs,
- CCState &CCInfo, bool IsCall, bool IsVarArg) {
- StringRef FuncName = getFunctionName(CLI);
-
- if (FuncName.startswith("__udivmod") || FuncName.startswith("__divmod")) {
- CCInfo.AnalyzeCallOperands(*Outs, ArgCC_AVR_BUILTIN_DIV);
- } else {
- analyzeStandardArguments(&CLI, F, TD, Outs, Ins,
- CallConv, ArgLocs, CCInfo,
- IsCall, IsVarArg);
+/// Count the total number of bytes needed to pass or return these arguments.
+template <typename ArgT>
+static unsigned getTotalArgumentsSizeInBytes(const SmallVectorImpl<ArgT> &Args) {
+ unsigned TotalBytes = 0;
+
+ for (const ArgT& Arg : Args) {
+ TotalBytes += Arg.VT.getStoreSize();
}
+ return TotalBytes;
}
-static void analyzeArguments(TargetLowering::CallLoweringInfo *CLI,
- const Function *F, const DataLayout *TD,
- const SmallVectorImpl<ISD::OutputArg> *Outs,
- const SmallVectorImpl<ISD::InputArg> *Ins,
- CallingConv::ID CallConv,
- SmallVectorImpl<CCValAssign> &ArgLocs,
- CCState &CCInfo, bool IsCall, bool IsVarArg) {
- switch (CallConv) {
- case CallingConv::AVR_BUILTIN: {
- analyzeBuiltinArguments(*CLI, F, TD, Outs, Ins,
- CallConv, ArgLocs, CCInfo,
- IsCall, IsVarArg);
- return;
- }
- default: {
- analyzeStandardArguments(CLI, F, TD, Outs, Ins,
- CallConv, ArgLocs, CCInfo,
- IsCall, IsVarArg);
- return;
+/// Analyze incoming and outgoing value of returning from a function.
+/// The algorithm is similar to analyzeArguments, but there can only be
+/// one value, possibly an aggregate, and it is limited to 8 bytes.
+template <typename ArgT>
+static void analyzeReturnValues(const SmallVectorImpl<ArgT> &Args,
+ CCState &CCInfo) {
+ unsigned NumArgs = Args.size();
+ unsigned TotalBytes = getTotalArgumentsSizeInBytes(Args);
+ // CanLowerReturn() guarantees this assertion.
+ assert(TotalBytes <= 8 && "return values greater than 8 bytes cannot be lowered");
+
+ // GCC-ABI says that the size is rounded up to the next even number,
+ // but actually once it is more than 4 it will always round up to 8.
+ if (TotalBytes > 4) {
+ TotalBytes = 8;
+ } else {
+ TotalBytes = alignTo(TotalBytes, 2);
+ }
+
+ // The index of the first register to use.
+ int RegIdx = TotalBytes - 1;
+ for (unsigned i = 0; i != NumArgs; ++i) {
+ MVT VT = Args[i].VT;
+ unsigned Reg;
+ if (VT == MVT::i8) {
+ Reg = CCInfo.AllocateReg(RegList8[RegIdx]);
+ } else if (VT == MVT::i16) {
+ Reg = CCInfo.AllocateReg(RegList16[RegIdx]);
+ } else {
+ llvm_unreachable("calling convention can only manage i8 and i16 types");
}
+ assert(Reg && "register not available in calling convention");
+ CCInfo.addLoc(CCValAssign::getReg(i, VT, Reg, VT, CCValAssign::Full));
+ // Registers sort in increasing order
+ RegIdx -= VT.getStoreSize();
}
}
SDValue AVRTargetLowering::LowerFormalArguments(
SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
- const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &InVals) const {
+ const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
+ SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo &MFI = MF.getFrameInfo();
auto DL = DAG.getDataLayout();
@@ -1059,8 +1030,12 @@ SDValue AVRTargetLowering::LowerFormalArguments(
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
*DAG.getContext());
- analyzeArguments(nullptr, &MF.getFunction(), &DL, 0, &Ins, CallConv, ArgLocs, CCInfo,
- false, isVarArg);
+ // Variadic functions do not need all the analysis below.
+ if (isVarArg) {
+ CCInfo.AnalyzeFormalArguments(Ins, ArgCC_AVR_Vararg);
+ } else {
+ analyzeArguments(nullptr, &MF.getFunction(), &DL, Ins, ArgLocs, CCInfo);
+ }
SDValue ArgValue;
for (CCValAssign &VA : ArgLocs) {
@@ -1181,8 +1156,12 @@ SDValue AVRTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
getPointerTy(DAG.getDataLayout()));
}
- analyzeArguments(&CLI, F, &DAG.getDataLayout(), &Outs, 0, CallConv, ArgLocs, CCInfo,
- true, isVarArg);
+ // Variadic functions do not need all the analysis below.
+ if (isVarArg) {
+ CCInfo.AnalyzeCallOperands(Outs, ArgCC_AVR_Vararg);
+ } else {
+ analyzeArguments(&CLI, F, &DAG.getDataLayout(), Outs, ArgLocs, CCInfo);
+ }
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@@ -1319,13 +1298,10 @@ SDValue AVRTargetLowering::LowerCallResult(
*DAG.getContext());
// Handle runtime calling convs.
- auto CCFunction = CCAssignFnForReturn(CallConv);
- CCInfo.AnalyzeCallResult(Ins, CCFunction);
-
- if (CallConv != CallingConv::AVR_BUILTIN && RVLocs.size() > 1) {
- // Reverse splitted return values to get the "big endian" format required
- // to agree with the calling convention ABI.
- std::reverse(RVLocs.begin(), RVLocs.end());
+ if (CallConv == CallingConv::AVR_BUILTIN) {
+ CCInfo.AnalyzeCallResult(Ins, RetCC_AVR_BUILTIN);
+ } else {
+ analyzeReturnValues(Ins, CCInfo);
}
// Copy all of the result registers out of their specified physreg.
@@ -1344,26 +1320,17 @@ SDValue AVRTargetLowering::LowerCallResult(
// Return Value Calling Convention Implementation
//===----------------------------------------------------------------------===//
-CCAssignFn *AVRTargetLowering::CCAssignFnForReturn(CallingConv::ID CC) const {
- switch (CC) {
- case CallingConv::AVR_BUILTIN:
- return RetCC_AVR_BUILTIN;
- default:
- return RetCC_AVR;
+bool AVRTargetLowering::CanLowerReturn(
+ CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
+ if (CallConv == CallingConv::AVR_BUILTIN) {
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
+ return CCInfo.CheckReturn(Outs, RetCC_AVR_BUILTIN);
}
-}
-bool
-AVRTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
- MachineFunction &MF, bool isVarArg,
- const SmallVectorImpl<ISD::OutputArg> &Outs,
- LLVMContext &Context) const
-{
- SmallVector<CCValAssign, 16> RVLocs;
- CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
-
- auto CCFunction = CCAssignFnForReturn(CallConv);
- return CCInfo.CheckReturn(Outs, CCFunction);
+ unsigned TotalBytes = getTotalArgumentsSizeInBytes(Outs);
+ return TotalBytes <= 8;
}
SDValue
@@ -1379,25 +1346,19 @@ AVRTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
*DAG.getContext());
- // Analyze return values.
- auto CCFunction = CCAssignFnForReturn(CallConv);
- CCInfo.AnalyzeReturn(Outs, CCFunction);
-
- // If this is the first return lowered for this function, add the regs to
- // the liveout set for the function.
MachineFunction &MF = DAG.getMachineFunction();
- unsigned e = RVLocs.size();
- // Reverse splitted return values to get the "big endian" format required
- // to agree with the calling convention ABI.
- if (e > 1) {
- std::reverse(RVLocs.begin(), RVLocs.end());
+ // Analyze return values.
+ if (CallConv == CallingConv::AVR_BUILTIN) {
+ CCInfo.AnalyzeReturn(Outs, RetCC_AVR_BUILTIN);
+ } else {
+ analyzeReturnValues(Outs, CCInfo);
}
SDValue Flag;
SmallVector<SDValue, 4> RetOps(1, Chain);
// Copy the result values into the output registers.
- for (unsigned i = 0; i != e; ++i) {
+ for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
@@ -1415,10 +1376,12 @@ AVRTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
return Chain;
}
+ const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
+
unsigned RetOpc =
- (CallConv == CallingConv::AVR_INTR || CallConv == CallingConv::AVR_SIGNAL)
- ? AVRISD::RETI_FLAG
- : AVRISD::RET_FLAG;
+ AFI->isInterruptOrSignalHandler()
+ ? AVRISD::RETI_FLAG
+ : AVRISD::RET_FLAG;
RetOps[0] = Chain; // Update chain.
@@ -1514,8 +1477,8 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI,
LoopBB->addSuccessor(RemBB);
LoopBB->addSuccessor(LoopBB);
- unsigned ShiftAmtReg = RI.createVirtualRegister(&AVR::LD8RegClass);
- unsigned ShiftAmtReg2 = RI.createVirtualRegister(&AVR::LD8RegClass);
+ Register ShiftAmtReg = RI.createVirtualRegister(&AVR::LD8RegClass);
+ Register ShiftAmtReg2 = RI.createVirtualRegister(&AVR::LD8RegClass);
Register ShiftReg = RI.createVirtualRegister(RC);
Register ShiftReg2 = RI.createVirtualRegister(RC);
Register ShiftAmtSrcReg = MI.getOperand(2).getReg();
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.h b/llvm/lib/Target/AVR/AVRISelLowering.h
index aca1ea1d50e5..d1eaf53b15e9 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.h
+++ b/llvm/lib/Target/AVR/AVRISelLowering.h
@@ -146,10 +146,8 @@ private:
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
- CCAssignFn *CCAssignFnForReturn(CallingConv::ID CC) const;
-
- bool CanLowerReturn(CallingConv::ID CallConv,
- MachineFunction &MF, bool isVarArg,
+ bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
+ bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
LLVMContext &Context) const override;
diff --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td
index ef596f5cebd5..6eb49076efb0 100644
--- a/llvm/lib/Target/AVR/AVRInstrFormats.td
+++ b/llvm/lib/Target/AVR/AVRInstrFormats.td
@@ -148,6 +148,8 @@ class FRd<bits<4> opcode, bits<7> f, dag outs, dag ins, string asmstr,
let Inst{11-9} = f{6-4};
let Inst{8-4} = d;
let Inst{3-0} = f{3-0};
+
+ let DecoderMethod = "decodeFRd";
}
//===----------------------------------------------------------------------===//
@@ -235,6 +237,8 @@ class FLPMX<bit e, bit p, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{3-2} = 0b01;
let Inst{1} = e;
let Inst{0} = p;
+
+ let DecoderMethod = "decodeFLPMX";
}
//===----------------------------------------------------------------------===//
@@ -252,6 +256,8 @@ class FMOVWRdRr<dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{15-8} = 0b00000001;
let Inst{7-4} = d{4-1};
let Inst{3-0} = r{4-1};
+
+ let DecoderMethod = "decodeFMOVWRdRr";
}
//===----------------------------------------------------------------------===//
@@ -270,6 +276,8 @@ class FMUL2RdRr<bit f, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{8} = f;
let Inst{7-4} = rd{3-0};
let Inst{3-0} = rr{3-0};
+
+ let DecoderMethod = "decodeFMUL2RdRr";
}
// Special encoding for the FMUL family of instructions.
@@ -293,6 +301,8 @@ class FFMULRdRr<bits<2> f, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{6-4} = rd;
let Inst{3} = f{0};
let Inst{2-0} = rr;
+
+ let DecoderMethod = "decodeFFMULRdRr";
}
@@ -314,6 +324,8 @@ class FWRdK<bit f, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{7-6} = k{5-4};
let Inst{5-4} = dst{2-1};
let Inst{3-0} = k{3-0};
+
+ let DecoderMethod = "decodeFWRdK";
}
//===----------------------------------------------------------------------===//
@@ -332,6 +344,8 @@ class FIORdA<dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{10-9} = A{5-4};
let Inst{8-4} = d;
let Inst{3-0} = A{3-0};
+
+ let DecoderMethod = "decodeFIORdA";
}
//===----------------------------------------------------------------------===//
@@ -350,6 +364,8 @@ class FIOARr<dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{10-9} = A{5-4};
let Inst{8-4} = r;
let Inst{3-0} = A{3-0};
+
+ let DecoderMethod = "decodeFIOARr";
}
//===----------------------------------------------------------------------===//
@@ -374,6 +390,8 @@ class FIOBIT<bits<2> t, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{3} = A{0};
let Inst{2-0} = b{2-0};
+
+ let DecoderMethod = "decodeFIOBIT";
}
//===----------------------------------------------------------------------===//
@@ -485,7 +503,7 @@ class F32BRk<bits<3> f, dag outs, dag ins, string asmstr, list<dag> pattern>
}
//===----------------------------------------------------------------------===//
-// 32 bits direct mem instructions: <|1001|00fd|dddd|0000|kkkk|kkkk|kkkk|kkkk|>
+// 32 bits direct mem instructions: <|1001|00fd|dddd|0000|kkkk|kkkk|kkkk|kkkk|>
// f = secondary opcode = 1 bit
// d = destination = 5 bits
// k = constant address = 16 bits
diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.cpp b/llvm/lib/Target/AVR/AVRInstrInfo.cpp
index a6832f282b31..06f07696bde3 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.cpp
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.cpp
@@ -48,11 +48,11 @@ void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
// Not all AVR devices support the 16-bit `MOVW` instruction.
if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {
- if (STI.hasMOVW()) {
+ if (STI.hasMOVW() && AVR::DREGSMOVWRegClass.contains(DestReg, SrcReg)) {
BuildMI(MBB, MI, DL, get(AVR::MOVWRdRr), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
} else {
- unsigned DestLo, DestHi, SrcLo, SrcHi;
+ Register DestLo, DestHi, SrcLo, SrcHi;
TRI.splitReg(DestReg, DestLo, DestHi);
TRI.splitReg(SrcReg, SrcLo, SrcHi);
@@ -119,7 +119,7 @@ unsigned AVRInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
void AVRInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
- unsigned SrcReg, bool isKill,
+ Register SrcReg, bool isKill,
int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
@@ -138,7 +138,7 @@ void AVRInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FrameIndex),
MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
- MFI.getObjectAlignment(FrameIndex));
+ MFI.getObjectAlign(FrameIndex));
unsigned Opcode = 0;
if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
@@ -158,7 +158,7 @@ void AVRInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
void AVRInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
- unsigned DestReg, int FrameIndex,
+ Register DestReg, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
DebugLoc DL;
@@ -172,7 +172,7 @@ void AVRInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FrameIndex),
MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
- MFI.getObjectAlignment(FrameIndex));
+ MFI.getObjectAlign(FrameIndex));
unsigned Opcode = 0;
if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.h b/llvm/lib/Target/AVR/AVRInstrInfo.h
index bb00ca8c724a..11f45865de54 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.h
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.h
@@ -75,12 +75,12 @@ public:
const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
bool KillSrc) const override;
void storeRegToStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI, unsigned SrcReg,
+ MachineBasicBlock::iterator MI, Register SrcReg,
bool isKill, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const override;
void loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI, unsigned DestReg,
+ MachineBasicBlock::iterator MI, Register DestReg,
int FrameIndex, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const override;
unsigned isLoadFromStackSlot(const MachineInstr &MI,
diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td
index acf991dcfbb1..f03c254382b4 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.td
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.td
@@ -107,7 +107,9 @@ def imm_com8 : Operand<i8> {
def ioaddr_XFORM : SDNodeXForm<imm,
[{
- return CurDAG->getTargetConstant(uint8_t(N->getZExtValue()) - 0x20, SDLoc(N), MVT::i8);
+ uint8_t offset = Subtarget->getIORegisterOffset();
+ return CurDAG->getTargetConstant(uint8_t(N->getZExtValue()) - offset,
+ SDLoc(N), MVT::i8);
}]>;
def iobitpos8_XFORM : SDNodeXForm<imm,
@@ -124,20 +126,23 @@ def iobitposn8_XFORM : SDNodeXForm<imm,
def ioaddr8 : PatLeaf<(imm),
[{
- uint64_t val = N->getZExtValue();
- return val >= 0x20 && val < 0x60;
+ uint8_t offset = Subtarget->getIORegisterOffset();
+ uint64_t val = N->getZExtValue() - offset;
+ return val < 0x40;
}], ioaddr_XFORM>;
def lowioaddr8 : PatLeaf<(imm),
[{
- uint64_t val = N->getZExtValue();
- return val >= 0x20 && val < 0x40;
+ uint8_t offset = Subtarget->getIORegisterOffset();
+ uint64_t val = N->getZExtValue() - offset;
+ return val < 0x20;
}], ioaddr_XFORM>;
def ioaddr16 : PatLeaf<(imm),
[{
- uint64_t val = N->getZExtValue();
- return val >= 0x20 && val < 0x5f;
+ uint8_t offset = Subtarget->getIORegisterOffset();
+ uint64_t val = N->getZExtValue() - offset;
+ return val < 0x3f;
}], ioaddr_XFORM>;
def iobitpos8 : PatLeaf<(imm),
@@ -188,6 +193,7 @@ def brtarget_13 : Operand<OtherVT>
def call_target : Operand<iPTR>
{
let EncoderMethod = "encodeCallTarget";
+ let DecoderMethod = "decodeCallTarget";
}
// A 16-bit address (which can lead to an R_AVR_16 relocation).
@@ -260,58 +266,58 @@ def LDDSTDPtrReg : Operand<i16>
//===----------------------------------------------------------------------===//
def HasSRAM : Predicate<"Subtarget->hasSRAM()">,
- AssemblerPredicate<"FeatureSRAM">;
+ AssemblerPredicate<(all_of FeatureSRAM)>;
def HasJMPCALL : Predicate<"Subtarget->hasJMPCALL()">,
- AssemblerPredicate<"FeatureJMPCALL">;
+ AssemblerPredicate<(all_of FeatureJMPCALL)>;
def HasIJMPCALL : Predicate<"Subtarget->hasIJMPCALL()">,
- AssemblerPredicate<"FeatureIJMPCALL">;
+ AssemblerPredicate<(all_of FeatureIJMPCALL)>;
def HasEIJMPCALL : Predicate<"Subtarget->hasEIJMPCALL()">,
- AssemblerPredicate<"FeatureEIJMPCALL">;
+ AssemblerPredicate<(all_of FeatureEIJMPCALL)>;
def HasADDSUBIW : Predicate<"Subtarget->hasADDSUBIW()">,
- AssemblerPredicate<"FeatureADDSUBIW">;
+ AssemblerPredicate<(all_of FeatureADDSUBIW)>;
def HasSmallStack : Predicate<"Subtarget->HasSmallStack()">,
- AssemblerPredicate<"FeatureSmallStack">;
+ AssemblerPredicate<(all_of FeatureSmallStack)>;
def HasMOVW : Predicate<"Subtarget->hasMOVW()">,
- AssemblerPredicate<"FeatureMOVW">;
+ AssemblerPredicate<(all_of FeatureMOVW)>;
def HasLPM : Predicate<"Subtarget->hasLPM()">,
- AssemblerPredicate<"FeatureLPM">;
+ AssemblerPredicate<(all_of FeatureLPM)>;
def HasLPMX : Predicate<"Subtarget->hasLPMX()">,
- AssemblerPredicate<"FeatureLPMX">;
+ AssemblerPredicate<(all_of FeatureLPMX)>;
def HasELPM : Predicate<"Subtarget->hasELPM()">,
- AssemblerPredicate<"FeatureELPM">;
+ AssemblerPredicate<(all_of FeatureELPM)>;
def HasELPMX : Predicate<"Subtarget->hasELPMX()">,
- AssemblerPredicate<"FeatureELPMX">;
+ AssemblerPredicate<(all_of FeatureELPMX)>;
def HasSPM : Predicate<"Subtarget->hasSPM()">,
- AssemblerPredicate<"FeatureSPM">;
+ AssemblerPredicate<(all_of FeatureSPM)>;
def HasSPMX : Predicate<"Subtarget->hasSPMX()">,
- AssemblerPredicate<"FeatureSPMX">;
+ AssemblerPredicate<(all_of FeatureSPMX)>;
def HasDES : Predicate<"Subtarget->hasDES()">,
- AssemblerPredicate<"FeatureDES">;
+ AssemblerPredicate<(all_of FeatureDES)>;
def SupportsRMW : Predicate<"Subtarget->supportsRMW()">,
- AssemblerPredicate<"FeatureRMW">;
+ AssemblerPredicate<(all_of FeatureRMW)>;
def SupportsMultiplication : Predicate<"Subtarget->supportsMultiplication()">,
- AssemblerPredicate<"FeatureMultiplication">;
+ AssemblerPredicate<(all_of FeatureMultiplication)>;
def HasBREAK : Predicate<"Subtarget->hasBREAK()">,
- AssemblerPredicate<"FeatureBREAK">;
+ AssemblerPredicate<(all_of FeatureBREAK)>;
def HasTinyEncoding : Predicate<"Subtarget->hasTinyEncoding()">,
- AssemblerPredicate<"FeatureTinyEncoding">;
+ AssemblerPredicate<(all_of FeatureTinyEncoding)>;
// AVR specific condition code. These correspond to AVR_*_COND in
@@ -555,7 +561,7 @@ Defs = [R1, R0, SREG] in
def MULSRdRr : FMUL2RdRr<0,
(outs),
- (ins GPR8:$lhs, GPR8:$rhs),
+ (ins LD8:$lhs, LD8:$rhs),
"muls\t$lhs, $rhs",
[]>,
Requires<[SupportsMultiplication]>;
@@ -563,28 +569,28 @@ Defs = [R1, R0, SREG] in
def MULSURdRr : FMUL2RdRr<1,
(outs),
- (ins GPR8:$lhs, GPR8:$rhs),
+ (ins LD8lo:$lhs, LD8lo:$rhs),
"mulsu\t$lhs, $rhs",
[]>,
Requires<[SupportsMultiplication]>;
def FMUL : FFMULRdRr<0b01,
(outs),
- (ins GPR8:$lhs, GPR8:$rhs),
+ (ins LD8lo:$lhs, LD8lo:$rhs),
"fmul\t$lhs, $rhs",
[]>,
Requires<[SupportsMultiplication]>;
def FMULS : FFMULRdRr<0b10,
(outs),
- (ins GPR8:$lhs, GPR8:$rhs),
+ (ins LD8lo:$lhs, LD8lo:$rhs),
"fmuls\t$lhs, $rhs",
[]>,
Requires<[SupportsMultiplication]>;
def FMULSU : FFMULRdRr<0b11,
(outs),
- (ins GPR8:$lhs, GPR8:$rhs),
+ (ins LD8lo:$lhs, LD8lo:$rhs),
"fmulsu\t$lhs, $rhs",
[]>,
Requires<[SupportsMultiplication]>;
@@ -840,7 +846,7 @@ let isCall = 1 in
//===----------------------------------------------------------------------===//
let isTerminator = 1,
isReturn = 1,
-isBarrier = 1 in
+isBarrier = 1 in
{
def RET : F16<0b1001010100001000,
(outs),
@@ -2042,8 +2048,6 @@ def : Pat<(add i16:$src1, imm:$src2),
(SUBIWRdK i16:$src1, (imm16_neg_XFORM imm:$src2))>;
def : Pat<(addc i16:$src1, imm:$src2),
(SUBIWRdK i16:$src1, (imm16_neg_XFORM imm:$src2))>;
-def : Pat<(adde i16:$src1, imm:$src2),
- (SBCIWRdK i16:$src1, (imm16_neg_XFORM imm:$src2))>;
def : Pat<(add i8:$src1, imm:$src2),
(SUBIRdK i8:$src1, (imm8_neg_XFORM imm:$src2))>;
diff --git a/llvm/lib/Target/AVR/AVRMachineFunctionInfo.h b/llvm/lib/Target/AVR/AVRMachineFunctionInfo.h
index 5226e30491c3..5432fac122ef 100644
--- a/llvm/lib/Target/AVR/AVRMachineFunctionInfo.h
+++ b/llvm/lib/Target/AVR/AVRMachineFunctionInfo.h
@@ -31,6 +31,12 @@ class AVRMachineFunctionInfo : public MachineFunctionInfo {
/// used inside the function.
bool HasStackArgs;
+ /// Whether or not the function is an interrupt handler.
+ bool IsInterruptHandler;
+
+ /// Whether or not the function is an non-blocking interrupt handler.
+ bool IsSignalHandler;
+
/// Size of the callee-saved register portion of the
/// stack frame in bytes.
unsigned CalleeSavedFrameSize;
@@ -41,11 +47,17 @@ class AVRMachineFunctionInfo : public MachineFunctionInfo {
public:
AVRMachineFunctionInfo()
: HasSpills(false), HasAllocas(false), HasStackArgs(false),
+ IsInterruptHandler(false), IsSignalHandler(false),
CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {}
explicit AVRMachineFunctionInfo(MachineFunction &MF)
: HasSpills(false), HasAllocas(false), HasStackArgs(false),
- CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {}
+ CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {
+ unsigned CallConv = MF.getFunction().getCallingConv();
+
+ this->IsInterruptHandler = CallConv == CallingConv::AVR_INTR || MF.getFunction().hasFnAttribute("interrupt");
+ this->IsSignalHandler = CallConv == CallingConv::AVR_SIGNAL || MF.getFunction().hasFnAttribute("signal");
+ }
bool getHasSpills() const { return HasSpills; }
void setHasSpills(bool B) { HasSpills = B; }
@@ -56,6 +68,12 @@ public:
bool getHasStackArgs() const { return HasStackArgs; }
void setHasStackArgs(bool B) { HasStackArgs = B; }
+ /// Checks if the function is some form of interrupt service routine.
+ bool isInterruptOrSignalHandler() const { return isInterruptHandler() || isSignalHandler(); }
+
+ bool isInterruptHandler() const { return IsInterruptHandler; }
+ bool isSignalHandler() const { return IsSignalHandler; }
+
unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; }
void setCalleeSavedFrameSize(unsigned Bytes) { CalleeSavedFrameSize = Bytes; }
diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
index 8fce05c933bc..2a4905ce2461 100644
--- a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
+++ b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
@@ -22,6 +22,7 @@
#include "AVR.h"
#include "AVRInstrInfo.h"
+#include "AVRMachineFunctionInfo.h"
#include "AVRTargetMachine.h"
#include "MCTargetDesc/AVRMCTargetDesc.h"
@@ -34,19 +35,21 @@ AVRRegisterInfo::AVRRegisterInfo() : AVRGenRegisterInfo(0) {}
const uint16_t *
AVRRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
- CallingConv::ID CC = MF->getFunction().getCallingConv();
+ const AVRMachineFunctionInfo *AFI = MF->getInfo<AVRMachineFunctionInfo>();
- return ((CC == CallingConv::AVR_INTR || CC == CallingConv::AVR_SIGNAL)
+ return AFI->isInterruptOrSignalHandler()
? CSR_Interrupts_SaveList
- : CSR_Normal_SaveList);
+ : CSR_Normal_SaveList;
}
const uint32_t *
AVRRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID CC) const {
- return ((CC == CallingConv::AVR_INTR || CC == CallingConv::AVR_SIGNAL)
+ const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
+
+ return AFI->isInterruptOrSignalHandler()
? CSR_Interrupts_RegMask
- : CSR_Normal_RegMask);
+ : CSR_Normal_RegMask;
}
BitVector AVRRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
@@ -95,7 +98,8 @@ AVRRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
}
/// Fold a frame offset shared between two add instructions into a single one.
-static void foldFrameOffset(MachineBasicBlock::iterator &II, int &Offset, unsigned DstReg) {
+static void foldFrameOffset(MachineBasicBlock::iterator &II, int &Offset,
+ Register DstReg) {
MachineInstr &MI = *II;
int Opcode = MI.getOpcode();
@@ -264,13 +268,12 @@ AVRRegisterInfo::getPointerRegClass(const MachineFunction &MF,
return &AVR::PTRDISPREGSRegClass;
}
-void AVRRegisterInfo::splitReg(unsigned Reg,
- unsigned &LoReg,
- unsigned &HiReg) const {
- assert(AVR::DREGSRegClass.contains(Reg) && "can only split 16-bit registers");
+void AVRRegisterInfo::splitReg(Register Reg, Register &LoReg,
+ Register &HiReg) const {
+ assert(AVR::DREGSRegClass.contains(Reg) && "can only split 16-bit registers");
- LoReg = getSubReg(Reg, AVR::sub_lo);
- HiReg = getSubReg(Reg, AVR::sub_hi);
+ LoReg = getSubReg(Reg, AVR::sub_lo);
+ HiReg = getSubReg(Reg, AVR::sub_hi);
}
bool AVRRegisterInfo::shouldCoalesce(MachineInstr *MI,
diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.h b/llvm/lib/Target/AVR/AVRRegisterInfo.h
index 8e6e63af3d57..23439f2fe195 100644
--- a/llvm/lib/Target/AVR/AVRRegisterInfo.h
+++ b/llvm/lib/Target/AVR/AVRRegisterInfo.h
@@ -49,11 +49,7 @@ public:
/// Splits a 16-bit `DREGS` register into the lo/hi register pair.
/// \param Reg A 16-bit register to split.
- void splitReg(unsigned Reg, unsigned &LoReg, unsigned &HiReg) const;
-
- bool trackLivenessAfterRegAlloc(const MachineFunction &) const override {
- return true;
- }
+ void splitReg(Register Reg, Register &LoReg, Register &HiReg) const;
bool shouldCoalesce(MachineInstr *MI,
const TargetRegisterClass *SrcRC,
diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.td b/llvm/lib/Target/AVR/AVRRegisterInfo.td
index ea38fedd22ce..ab5d02356c9d 100644
--- a/llvm/lib/Target/AVR/AVRRegisterInfo.td
+++ b/llvm/lib/Target/AVR/AVRRegisterInfo.td
@@ -103,6 +103,17 @@ CoveredBySubRegs = 1 in
def R5R4 : AVRReg<4, "r5:r4", [R4, R5]>, DwarfRegNum<[4]>;
def R3R2 : AVRReg<2, "r3:r2", [R2, R3]>, DwarfRegNum<[2]>;
def R1R0 : AVRReg<0, "r1:r0", [R0, R1]>, DwarfRegNum<[0]>;
+
+ // Pseudo registers for unaligned i16
+ def R26R25 : AVRReg<25, "r26:r25", [R25, R26]>, DwarfRegNum<[25]>;
+ def R24R23 : AVRReg<23, "r24:r23", [R23, R24]>, DwarfRegNum<[23]>;
+ def R22R21 : AVRReg<21, "r22:r21", [R21, R22]>, DwarfRegNum<[21]>;
+ def R20R19 : AVRReg<19, "r20:r19", [R19, R20]>, DwarfRegNum<[19]>;
+ def R18R17 : AVRReg<17, "r18:r17", [R17, R18]>, DwarfRegNum<[17]>;
+ def R16R15 : AVRReg<15, "r16:r15", [R15, R16]>, DwarfRegNum<[15]>;
+ def R14R13 : AVRReg<13, "r14:r13", [R13, R14]>, DwarfRegNum<[13]>;
+ def R12R11 : AVRReg<11, "r12:r11", [R11, R12]>, DwarfRegNum<[11]>;
+ def R10R9 : AVRReg<9, "r10:r9", [R9, R10]>, DwarfRegNum<[9]>;
}
//===----------------------------------------------------------------------===//
@@ -153,6 +164,22 @@ def DREGS : RegisterClass<"AVR", [i16], 8,
R31R30, R27R26,
// Callee saved registers.
R29R28, R17R16, R15R14, R13R12, R11R10,
+ R9R8, R7R6, R5R4, R3R2, R1R0,
+ // Pseudo regs for unaligned 16-bits
+ R26R25, R24R23, R22R21,
+ R20R19, R18R17, R16R15,
+ R14R13, R12R11, R10R9
+ )>;
+
+// 16-bit pair register class for movw
+def DREGSMOVW : RegisterClass<"AVR", [i16], 8,
+ (
+ // Return value and arguments.
+ add R25R24, R19R18, R21R20, R23R22,
+ // Scratch registers.
+ R31R30, R27R26,
+ // Callee saved registers.
+ R29R28, R17R16, R15R14, R13R12, R11R10,
R9R8, R7R6, R5R4, R3R2, R1R0
)>;
diff --git a/llvm/lib/Target/AVR/AVRSubtarget.cpp b/llvm/lib/Target/AVR/AVRSubtarget.cpp
index 6a41036fdd6c..195ca95bc3bd 100644
--- a/llvm/lib/Target/AVR/AVRSubtarget.cpp
+++ b/llvm/lib/Target/AVR/AVRSubtarget.cpp
@@ -29,16 +29,19 @@ namespace llvm {
AVRSubtarget::AVRSubtarget(const Triple &TT, const std::string &CPU,
const std::string &FS, const AVRTargetMachine &TM)
- : AVRGenSubtargetInfo(TT, CPU, FS), InstrInfo(), FrameLowering(),
- TLInfo(TM, initializeSubtargetDependencies(CPU, FS, TM)), TSInfo(),
+ : AVRGenSubtargetInfo(TT, CPU, FS), ELFArch(0),
// Subtarget features
m_hasSRAM(false), m_hasJMPCALL(false), m_hasIJMPCALL(false),
m_hasEIJMPCALL(false), m_hasADDSUBIW(false), m_hasSmallStack(false),
- m_hasMOVW(false), m_hasLPM(false), m_hasLPMX(false), m_hasELPM(false),
+ m_hasMOVW(false), m_hasLPM(false), m_hasLPMX(false), m_hasELPM(false),
m_hasELPMX(false), m_hasSPM(false), m_hasSPMX(false), m_hasDES(false),
m_supportsRMW(false), m_supportsMultiplication(false), m_hasBREAK(false),
- m_hasTinyEncoding(false), ELFArch(false), m_FeatureSetDummy(false) {
+ m_hasTinyEncoding(false), m_hasMemMappedGPR(false),
+ m_FeatureSetDummy(false),
+
+ InstrInfo(), FrameLowering(),
+ TLInfo(TM, initializeSubtargetDependencies(CPU, FS, TM)), TSInfo() {
// Parse features string.
ParseSubtargetFeatures(CPU, FS);
}
diff --git a/llvm/lib/Target/AVR/AVRSubtarget.h b/llvm/lib/Target/AVR/AVRSubtarget.h
index da9289af7c8d..81d883eb30d9 100644
--- a/llvm/lib/Target/AVR/AVRSubtarget.h
+++ b/llvm/lib/Target/AVR/AVRSubtarget.h
@@ -71,6 +71,9 @@ public:
bool supportsMultiplication() const { return m_supportsMultiplication; }
bool hasBREAK() const { return m_hasBREAK; }
bool hasTinyEncoding() const { return m_hasTinyEncoding; }
+ bool hasMemMappedGPR() const { return m_hasMemMappedGPR; }
+
+ uint8_t getIORegisterOffset() const { return hasMemMappedGPR() ? 0x20 : 0x0; }
/// Gets the ELF architecture for the e_flags field
/// of an ELF object file.
@@ -81,10 +84,9 @@ public:
}
private:
- AVRInstrInfo InstrInfo;
- AVRFrameLowering FrameLowering;
- AVRTargetLowering TLInfo;
- AVRSelectionDAGInfo TSInfo;
+
+ /// The ELF e_flags architecture.
+ unsigned ELFArch;
// Subtarget feature settings
// See AVR.td for details.
@@ -106,13 +108,16 @@ private:
bool m_supportsMultiplication;
bool m_hasBREAK;
bool m_hasTinyEncoding;
-
- /// The ELF e_flags architecture.
- unsigned ELFArch;
+ bool m_hasMemMappedGPR;
// Dummy member, used by FeatureSet's. We cannot have a SubtargetFeature with
// no variable, so we instead bind pseudo features to this variable.
bool m_FeatureSetDummy;
+
+ AVRInstrInfo InstrInfo;
+ AVRFrameLowering FrameLowering;
+ AVRTargetLowering TLInfo;
+ AVRSelectionDAGInfo TSInfo;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/AVR/AVRTargetMachine.cpp b/llvm/lib/Target/AVR/AVRTargetMachine.cpp
index b33284b73d63..0c7136e6f77e 100644
--- a/llvm/lib/Target/AVR/AVRTargetMachine.cpp
+++ b/llvm/lib/Target/AVR/AVRTargetMachine.cpp
@@ -49,7 +49,7 @@ AVRTargetMachine::AVRTargetMachine(const Target &T, const Triple &TT,
: LLVMTargetMachine(T, AVRDataLayout, TT, getCPU(CPU), FS, Options,
getEffectiveRelocModel(RM),
getEffectiveCodeModel(CM, CodeModel::Small), OL),
- SubTarget(TT, getCPU(CPU), FS, *this) {
+ SubTarget(TT, std::string(getCPU(CPU)), std::string(FS), *this) {
this->TLOF = std::make_unique<AVRTargetObjectFile>();
initAsmInfo();
}
diff --git a/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp b/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
index 980096a09835..14206cdb8276 100644
--- a/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
+++ b/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
@@ -30,7 +30,7 @@ AVRTargetObjectFile::SelectSectionForGlobal(const GlobalObject *GO,
const TargetMachine &TM) const {
// Global values in flash memory are placed in the progmem.data section
// unless they already have a user assigned section.
- if (AVR::isProgramMemoryAddress(GO) && !GO->hasSection())
+ if (AVR::isProgramMemoryAddress(GO) && !GO->hasSection() && Kind.isReadOnly())
return ProgmemDataSection;
// Otherwise, we work the same way as ELF.
diff --git a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
index fc34583ae573..230bc7adc07a 100644
--- a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
+++ b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
@@ -53,6 +53,8 @@ class AVRAsmParser : public MCTargetAsmParser {
bool MatchingInlineAsm) override;
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+ OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+ SMLoc &EndLoc) override;
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
@@ -64,7 +66,7 @@ class AVRAsmParser : public MCTargetAsmParser {
bool parseOperand(OperandVector &Operands);
int parseRegisterName(unsigned (*matchFn)(StringRef));
int parseRegisterName();
- int parseRegister();
+ int parseRegister(bool RestoreOnFailure = false);
bool tryParseRegisterOperand(OperandVector &Operands);
bool tryParseExpression(OperandVector &Operands);
bool tryParseRelocExpression(OperandVector &Operands);
@@ -176,10 +178,10 @@ public:
return isUInt<8>(Value);
}
- bool isReg() const { return Kind == k_Register; }
- bool isImm() const { return Kind == k_Immediate; }
- bool isToken() const { return Kind == k_Token; }
- bool isMem() const { return Kind == k_Memri; }
+ bool isReg() const override { return Kind == k_Register; }
+ bool isImm() const override { return Kind == k_Immediate; }
+ bool isToken() const override { return Kind == k_Token; }
+ bool isMem() const override { return Kind == k_Memri; }
bool isMemri() const { return Kind == k_Memri; }
StringRef getToken() const {
@@ -187,7 +189,7 @@ public:
return Tok;
}
- unsigned getReg() const {
+ unsigned getReg() const override {
assert((Kind == k_Register || Kind == k_Memri) && "Invalid access!");
return RegImm.Reg;
@@ -237,10 +239,10 @@ public:
RegImm = {RegNo, Imm};
}
- SMLoc getStartLoc() const { return Start; }
- SMLoc getEndLoc() const { return End; }
+ SMLoc getStartLoc() const override { return Start; }
+ SMLoc getEndLoc() const override { return End; }
- virtual void print(raw_ostream &O) const {
+ void print(raw_ostream &O) const override {
switch (Kind) {
case k_Token:
O << "Token: \"" << getToken() << "\"";
@@ -307,7 +309,7 @@ bool AVRAsmParser::missingFeature(llvm::SMLoc const &Loc,
bool AVRAsmParser::emit(MCInst &Inst, SMLoc const &Loc, MCStreamer &Out) const {
Inst.setLoc(Loc);
- Out.EmitInstruction(Inst, STI);
+ Out.emitInstruction(Inst, STI);
return false;
}
@@ -359,19 +361,25 @@ int AVRAsmParser::parseRegisterName() {
return RegNum;
}
-int AVRAsmParser::parseRegister() {
+int AVRAsmParser::parseRegister(bool RestoreOnFailure) {
int RegNum = AVR::NoRegister;
if (Parser.getTok().is(AsmToken::Identifier)) {
// Check for register pair syntax
if (Parser.getLexer().peekTok().is(AsmToken::Colon)) {
+ AsmToken HighTok = Parser.getTok();
Parser.Lex();
+ AsmToken ColonTok = Parser.getTok();
Parser.Lex(); // Eat high (odd) register and colon
if (Parser.getTok().is(AsmToken::Identifier)) {
// Convert lower (even) register to DREG
RegNum = toDREG(parseRegisterName());
}
+ if (RegNum == AVR::NoRegister && RestoreOnFailure) {
+ getLexer().UnLex(std::move(ColonTok));
+ getLexer().UnLex(std::move(HighTok));
+ }
} else {
RegNum = parseRegisterName();
}
@@ -580,12 +588,24 @@ AVRAsmParser::parseMemriOperand(OperandVector &Operands) {
bool AVRAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) {
StartLoc = Parser.getTok().getLoc();
- RegNo = parseRegister();
+ RegNo = parseRegister(/*RestoreOnFailure=*/false);
EndLoc = Parser.getTok().getLoc();
return (RegNo == AVR::NoRegister);
}
+OperandMatchResultTy AVRAsmParser::tryParseRegister(unsigned &RegNo,
+ SMLoc &StartLoc,
+ SMLoc &EndLoc) {
+ StartLoc = Parser.getTok().getLoc();
+ RegNo = parseRegister(/*RestoreOnFailure=*/true);
+ EndLoc = Parser.getTok().getLoc();
+
+ if (RegNo == AVR::NoRegister)
+ return MatchOperand_NoMatch;
+ return MatchOperand_Success;
+}
+
void AVRAsmParser::eatComma() {
if (getLexer().is(AsmToken::Comma)) {
Parser.Lex();
@@ -650,7 +670,7 @@ bool AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) {
Tokens[0].getKind() == AsmToken::Minus &&
Tokens[1].getKind() == AsmToken::Identifier) {
MCSymbol *Symbol = getContext().getOrCreateSymbol(".text");
- AVRStreamer.EmitValueForModiferKind(Symbol, SizeInBytes, L,
+ AVRStreamer.emitValueForModiferKind(Symbol, SizeInBytes, L,
AVRMCExpr::VK_AVR_None);
return false;
}
@@ -668,7 +688,7 @@ bool AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) {
}
MCSymbol *Symbol =
getContext().getOrCreateSymbol(Parser.getTok().getString());
- AVRStreamer.EmitValueForModiferKind(Symbol, SizeInBytes, L, ModifierKind);
+ AVRStreamer.emitValueForModiferKind(Symbol, SizeInBytes, L, ModifierKind);
return false;
}
@@ -676,7 +696,7 @@ bool AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) {
const MCExpr *Value;
if (Parser.parseExpression(Value))
return true;
- Parser.getStreamer().EmitValue(Value, SizeInBytes, L);
+ Parser.getStreamer().emitValue(Value, SizeInBytes, L);
return false;
};
return (parseMany(parseOne));
diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index 694aee818f7c..8e7251a74dfd 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -57,23 +57,180 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRDisassembler() {
createAVRDisassembler);
}
+static const uint16_t GPRDecoderTable[] = {
+ AVR::R0, AVR::R1, AVR::R2, AVR::R3,
+ AVR::R4, AVR::R5, AVR::R6, AVR::R7,
+ AVR::R8, AVR::R9, AVR::R10, AVR::R11,
+ AVR::R12, AVR::R13, AVR::R14, AVR::R15,
+ AVR::R16, AVR::R17, AVR::R18, AVR::R19,
+ AVR::R20, AVR::R21, AVR::R22, AVR::R23,
+ AVR::R24, AVR::R25, AVR::R26, AVR::R27,
+ AVR::R28, AVR::R29, AVR::R30, AVR::R31,
+};
+
static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+
+ unsigned Register = GPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Register));
return MCDisassembler::Success;
}
static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
+ if (RegNo > 15)
+ return MCDisassembler::Fail;
+
+ unsigned Register = GPRDecoderTable[RegNo+16];
+ Inst.addOperand(MCOperand::createReg(Register));
return MCDisassembler::Success;
}
static DecodeStatus DecodePTRREGSRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
+ // Note: this function must be defined but does not seem to be called.
+ assert(false && "unimplemented: PTRREGS register class");
return MCDisassembler::Success;
}
+static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
#include "AVRGenDisassemblerTables.inc"
+static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned addr = 0;
+ addr |= fieldFromInstruction(Insn, 0, 4);
+ addr |= fieldFromInstruction(Insn, 9, 2) << 4;
+ unsigned reg = fieldFromInstruction(Insn, 4, 5);
+ Inst.addOperand(MCOperand::createImm(addr));
+ if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned addr = 0;
+ addr |= fieldFromInstruction(Insn, 0, 4);
+ addr |= fieldFromInstruction(Insn, 9, 2) << 4;
+ unsigned reg = fieldFromInstruction(Insn, 4, 5);
+ if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::createImm(addr));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned addr = fieldFromInstruction(Insn, 3, 5);
+ unsigned b = fieldFromInstruction(Insn, 0, 3);
+ Inst.addOperand(MCOperand::createImm(addr));
+ Inst.addOperand(MCOperand::createImm(b));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Field,
+ uint64_t Address, const void *Decoder) {
+ // Call targets need to be shifted left by one so this needs a custom
+ // decoder.
+ Inst.addOperand(MCOperand::createImm(Field << 1));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned d = fieldFromInstruction(Insn, 4, 5);
+ if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ if (decodeFRd(Inst, Insn, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::createReg(AVR::R31R30));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned d = fieldFromInstruction(Insn, 4, 3) + 16;
+ unsigned r = fieldFromInstruction(Insn, 0, 3) + 16;
+ if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned r = fieldFromInstruction(Insn, 4, 4) * 2;
+ unsigned d = fieldFromInstruction(Insn, 0, 4) * 2;
+ if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned d = fieldFromInstruction(Insn, 4, 2) * 2 + 24; // starts at r24:r25
+ unsigned k = 0;
+ k |= fieldFromInstruction(Insn, 0, 4);
+ k |= fieldFromInstruction(Insn, 6, 2) << 4;
+ if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::createImm(k));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned rd = fieldFromInstruction(Insn, 4, 4) + 16;
+ unsigned rr = fieldFromInstruction(Insn, 0, 4) + 16;
+ if (DecodeGPR8RegisterClass(Inst, rd, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ if (DecodeGPR8RegisterClass(Inst, rr, Address, Decoder) == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ return MCDisassembler::Success;
+}
+
static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
uint64_t &Size, uint32_t &Insn) {
if (Bytes.size() < 2) {
@@ -96,7 +253,7 @@ static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
}
Size = 4;
- Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | (Bytes[3] << 24);
+ Insn = (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
return MCDisassembler::Success;
}
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
index e92b16c8ee9d..ac72abe0d9f6 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
@@ -34,8 +34,9 @@ namespace adjust {
using namespace llvm;
-void signed_width(unsigned Width, uint64_t Value, std::string Description,
- const MCFixup &Fixup, MCContext *Ctx = nullptr) {
+static void signed_width(unsigned Width, uint64_t Value,
+ std::string Description, const MCFixup &Fixup,
+ MCContext *Ctx = nullptr) {
if (!isIntN(Width, Value)) {
std::string Diagnostic = "out of range " + Description;
@@ -53,8 +54,9 @@ void signed_width(unsigned Width, uint64_t Value, std::string Description,
}
}
-void unsigned_width(unsigned Width, uint64_t Value, std::string Description,
- const MCFixup &Fixup, MCContext *Ctx = nullptr) {
+static void unsigned_width(unsigned Width, uint64_t Value,
+ std::string Description, const MCFixup &Fixup,
+ MCContext *Ctx = nullptr) {
if (!isUIntN(Width, Value)) {
std::string Diagnostic = "out of range " + Description;
@@ -72,8 +74,8 @@ void unsigned_width(unsigned Width, uint64_t Value, std::string Description,
}
/// Adjusts the value of a branch target before fixup application.
-void adjustBranch(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void adjustBranch(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
// We have one extra bit of precision because the value is rightshifted by
// one.
unsigned_width(Size + 1, Value, std::string("branch target"), Fixup, Ctx);
@@ -83,14 +85,12 @@ void adjustBranch(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
}
/// Adjusts the value of a relative branch target before fixup application.
-void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup,
+ uint64_t &Value, MCContext *Ctx = nullptr) {
// We have one extra bit of precision because the value is rightshifted by
// one.
signed_width(Size + 1, Value, std::string("branch target"), Fixup, Ctx);
- Value -= 2;
-
// Rightshifts the value by one.
AVR::fixups::adjustBranchTarget(Value);
}
@@ -101,8 +101,8 @@ void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
/// 1001 kkkk 010k kkkk kkkk kkkk 111k kkkk
///
/// Offset of 0 (so the result is left shifted by 3 bits before application).
-void fixup_call(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void fixup_call(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
adjustBranch(Size, Fixup, Value, Ctx);
auto top = Value & (0xf00000 << 6); // the top four bits
@@ -117,8 +117,8 @@ void fixup_call(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
/// Resolves to:
/// 0000 00kk kkkk k000
/// Offset of 0 (so the result is left shifted by 3 bits before application).
-void fixup_7_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void fixup_7_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
adjustRelativeBranch(Size, Fixup, Value, Ctx);
// Because the value may be negative, we must mask out the sign bits
@@ -131,21 +131,33 @@ void fixup_7_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
/// Resolves to:
/// 0000 kkkk kkkk kkkk
/// Offset of 0 (so the result isn't left-shifted before application).
-void fixup_13_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void fixup_13_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
adjustRelativeBranch(Size, Fixup, Value, Ctx);
// Because the value may be negative, we must mask out the sign bits
Value &= 0xfff;
}
+/// 6-bit fixup for the immediate operand of the STD/LDD family of
+/// instructions.
+///
+/// Resolves to:
+/// 10q0 qq10 0000 1qqq
+static void fixup_6(const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
+ unsigned_width(6, Value, std::string("immediate"), Fixup, Ctx);
+
+ Value = ((Value & 0x20) << 8) | ((Value & 0x18) << 7) | (Value & 0x07);
+}
+
/// 6-bit fixup for the immediate operand of the ADIW family of
/// instructions.
///
/// Resolves to:
/// 0000 0000 kk00 kkkk
-void fixup_6_adiw(const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void fixup_6_adiw(const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
unsigned_width(6, Value, std::string("immediate"), Fixup, Ctx);
Value = ((Value & 0x30) << 2) | (Value & 0x0f);
@@ -155,8 +167,8 @@ void fixup_6_adiw(const MCFixup &Fixup, uint64_t &Value,
///
/// Resolves to:
/// 0000 0000 AAAA A000
-void fixup_port5(const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void fixup_port5(const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
unsigned_width(5, Value, std::string("port number"), Fixup, Ctx);
Value &= 0x1f;
@@ -168,8 +180,8 @@ void fixup_port5(const MCFixup &Fixup, uint64_t &Value,
///
/// Resolves to:
/// 1011 0AAd dddd AAAA
-void fixup_port6(const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void fixup_port6(const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
unsigned_width(6, Value, std::string("port number"), Fixup, Ctx);
Value = ((Value & 0x30) << 5) | (Value & 0x0f);
@@ -177,9 +189,7 @@ void fixup_port6(const MCFixup &Fixup, uint64_t &Value,
/// Adjusts a program memory address.
/// This is a simple right-shift.
-void pm(uint64_t &Value) {
- Value >>= 1;
-}
+static void pm(uint64_t &Value) { Value >>= 1; }
/// Fixups relating to the LDI instruction.
namespace ldi {
@@ -189,36 +199,36 @@ namespace ldi {
/// Resolves to:
/// 0000 KKKK 0000 KKKK
/// Offset of 0 (so the result isn't left-shifted before application).
-void fixup(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void fixup(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
uint64_t upper = Value & 0xf0;
uint64_t lower = Value & 0x0f;
Value = (upper << 4) | lower;
}
-void neg(uint64_t &Value) { Value *= -1; }
+static void neg(uint64_t &Value) { Value *= -1; }
-void lo8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void lo8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
Value &= 0xff;
ldi::fixup(Size, Fixup, Value, Ctx);
}
-void hi8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void hi8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
Value = (Value & 0xff00) >> 8;
ldi::fixup(Size, Fixup, Value, Ctx);
}
-void hh8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void hh8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
Value = (Value & 0xff0000) >> 16;
ldi::fixup(Size, Fixup, Value, Ctx);
}
-void ms8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
- MCContext *Ctx = nullptr) {
+static void ms8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
+ MCContext *Ctx = nullptr) {
Value = (Value & 0xff000000) >> 24;
ldi::fixup(Size, Fixup, Value, Ctx);
}
@@ -237,17 +247,6 @@ void AVRAsmBackend::adjustFixupValue(const MCFixup &Fixup,
uint64_t Size = AVRAsmBackend::getFixupKindInfo(Fixup.getKind()).TargetSize;
unsigned Kind = Fixup.getKind();
-
- // Parsed LLVM-generated temporary labels are already
- // adjusted for instruction size, but normal labels aren't.
- //
- // To handle both cases, we simply un-adjust the temporary label
- // case so it acts like all other labels.
- if (const MCSymbolRefExpr *A = Target.getSymA()) {
- if (A->getSymbol().isTemporary())
- Value += 2;
- }
-
switch (Kind) {
default:
llvm_unreachable("unhandled fixup");
@@ -326,6 +325,9 @@ void AVRAsmBackend::adjustFixupValue(const MCFixup &Fixup,
Value &= 0xffff;
break;
+ case AVR::fixup_6:
+ adjust::fixup_6(Fixup, Value, Ctx);
+ break;
case AVR::fixup_6_adiw:
adjust::fixup_6_adiw(Fixup, Value, Ctx);
break;
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h
index 1e713db38145..9e150f120dd4 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h
@@ -22,9 +22,6 @@
namespace llvm {
class MCAssembler;
-class MCObjectWriter;
-class Target;
-
struct MCFixupKindInfo;
/// Utilities for manipulating generated AVR machine code.
@@ -62,9 +59,6 @@ public:
return false;
}
- void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
- MCInst &Res) const override {}
-
bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h
index b3504b89e4d3..a0dd1dc8ac3e 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRFixupKinds.h
@@ -137,7 +137,7 @@ namespace fixups {
/// of the fact that all instructions are aligned to addresses of size
/// 2, so bit 0 of an address is always 0. This gives us another bit
/// of precision.
-/// \param[in,out] The target to adjust.
+/// \param [in,out] val The target to adjust.
template <typename T> inline void adjustBranchTarget(T &val) { val >>= 1; }
} // end of namespace fixups
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp
index 832112406155..42fac5e2e000 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp
@@ -78,7 +78,7 @@ void AVRInstPrinter::printInst(const MCInst *MI, uint64_t Address,
printOperand(MI, 2, O);
break;
default:
- if (!printAliasInstr(MI, O))
+ if (!printAliasInstr(MI, Address, O))
printInstruction(MI, Address, O);
printAnnotation(O, Annot);
@@ -100,8 +100,25 @@ const char *AVRInstPrinter::getPrettyRegisterName(unsigned RegNum,
void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
- const MCOperand &Op = MI->getOperand(OpNo);
const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).OpInfo[OpNo];
+ if (MOI.RegClass == AVR::ZREGRegClassID) {
+ // Special case for the Z register, which sometimes doesn't have an operand
+ // in the MCInst.
+ O << "Z";
+ return;
+ }
+
+ if (OpNo >= MI->size()) {
+ // Not all operands are correctly disassembled at the moment. This means
+ // that some machine instructions won't have all the necessary operands
+ // set.
+ // To avoid asserting, print <unknown> instead until the necessary support
+ // has been implemented.
+ O << "<unknown>";
+ return;
+ }
+
+ const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg()) {
bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
@@ -114,7 +131,7 @@ void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
O << getPrettyRegisterName(Op.getReg(), MRI);
}
} else if (Op.isImm()) {
- O << Op.getImm();
+ O << formatImm(Op.getImm());
} else {
assert(Op.isExpr() && "Unknown operand kind in printOperand");
O << *Op.getExpr();
@@ -125,6 +142,16 @@ void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
/// being encoded as a pc-relative value.
void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
+ if (OpNo >= MI->size()) {
+ // Not all operands are correctly disassembled at the moment. This means
+ // that some machine instructions won't have all the necessary operands
+ // set.
+ // To avoid asserting, print <unknown> instead until the necessary support
+ // has been implemented.
+ O << "<unknown>";
+ return;
+ }
+
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm()) {
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.h
index 247e9fc83989..910fd3455dee 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.h
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.h
@@ -38,13 +38,18 @@ private:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printPCRelImm(const MCInst *MI, uint64_t /*Address*/, unsigned OpNo,
+ raw_ostream &O) {
+ printPCRelImm(MI, OpNo, O);
+ }
void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O);
// Autogenerated by TableGen.
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
- bool printAliasInstr(const MCInst *MI, raw_ostream &O);
- void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx,
- unsigned PrintMethodIdx, raw_ostream &O);
+ bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &O);
+ void printCustomAliasOperand(const MCInst *MI, uint64_t Address,
+ unsigned OpIdx, unsigned PrintMethodIdx,
+ raw_ostream &O);
};
} // end namespace llvm
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.cpp
index c25a2b232013..b11ee42bfcd6 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCAsmInfo.cpp
@@ -21,8 +21,8 @@ AVRMCAsmInfo::AVRMCAsmInfo(const Triple &TT, const MCTargetOptions &Options) {
CalleeSaveStackSlotSize = 2;
CommentString = ";";
PrivateGlobalPrefix = ".L";
+ PrivateLabelPrefix = ".L";
UsesELFSectionDirectiveForBSS = true;
- UseIntegratedAssembler = true;
SupportsDebugInformation = true;
}
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp
index d9169f90a765..77b49931843b 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.cpp
@@ -20,7 +20,7 @@
using namespace llvm;
-void AVRMCELFStreamer::EmitValueForModiferKind(
+void AVRMCELFStreamer::emitValueForModiferKind(
const MCSymbol *Sym, unsigned SizeInBytes, SMLoc Loc,
AVRMCExpr::VariantKind ModifierKind) {
MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_AVR_NONE;
@@ -36,7 +36,7 @@ void AVRMCELFStreamer::EmitValueForModiferKind(
Kind = MCSymbolRefExpr::VK_AVR_HI8;
else if (ModifierKind == AVRMCExpr::VK_AVR_HH8)
Kind = MCSymbolRefExpr::VK_AVR_HLO8;
- MCELFStreamer::EmitValue(MCSymbolRefExpr::create(Sym, Kind, getContext()),
+ MCELFStreamer::emitValue(MCSymbolRefExpr::create(Sym, Kind, getContext()),
SizeInBytes, Loc);
}
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.h
index 37a610bc4248..1d05b8d56d93 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.h
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCELFStreamer.h
@@ -41,7 +41,7 @@ public:
std::move(Emitter)),
MCII(createAVRMCInstrInfo()) {}
- void EmitValueForModiferKind(
+ void emitValueForModiferKind(
const MCSymbol *Sym, unsigned SizeInBytes, SMLoc Loc = SMLoc(),
AVRMCExpr::VariantKind ModifierKind = AVRMCExpr::VK_AVR_None);
};
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h
index 470db01ff468..ef116793d326 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCTargetDesc.h
@@ -27,10 +27,7 @@ class MCObjectTargetWriter;
class MCRegisterInfo;
class MCSubtargetInfo;
class MCTargetOptions;
-class StringRef;
class Target;
-class Triple;
-class raw_pwrite_stream;
MCInstrInfo *createAVRMCInstrInfo();
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRTargetStreamer.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRTargetStreamer.cpp
index 3487a2bbb864..eccd343d79ab 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRTargetStreamer.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRTargetStreamer.cpp
@@ -32,11 +32,11 @@ void AVRTargetStreamer::finish() {
OS.emitRawComment(" Declaring this symbol tells the CRT that it should");
OS.emitRawComment("copy all variables from program memory to RAM on startup");
- OS.EmitSymbolAttribute(DoCopyData, MCSA_Global);
+ OS.emitSymbolAttribute(DoCopyData, MCSA_Global);
OS.emitRawComment(" Declaring this symbol tells the CRT that it should");
OS.emitRawComment("clear the zeroed data section on startup");
- OS.EmitSymbolAttribute(DoClearBss, MCSA_Global);
+ OS.emitSymbolAttribute(DoClearBss, MCSA_Global);
}
} // end namespace llvm