Merge pull request #66 from dylanmckay/avr-pick-upstream-llvm-fixes
[AVR] Cherry-pick 17 upstream AVR backend fixes into the Rust LLVM fork
diff --git a/llvm/lib/Target/AVR/AVRCallingConv.td b/llvm/lib/Target/AVR/AVRCallingConv.td
index 213e35f..65545e5 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 @@
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 62def45..6730f2e 100644
--- a/llvm/lib/Target/AVR/AVRDevices.td
+++ b/llvm/lib/Target/AVR/AVRDevices.td
@@ -121,6 +121,11 @@
"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 @@
// 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 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 @@
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 f466c5c..1c6a504 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -597,8 +597,8 @@
// 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)
diff --git a/llvm/lib/Target/AVR/AVRFrameLowering.cpp b/llvm/lib/Target/AVR/AVRFrameLowering.cpp
index e6c48de..7f441a0 100644
--- a/llvm/lib/Target/AVR/AVRFrameLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRFrameLowering.cpp
@@ -57,26 +57,19 @@
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 +93,6 @@
}
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 +135,11 @@
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 +149,13 @@
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 +163,6 @@
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;
@@ -299,15 +285,10 @@
}
/// 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 +303,6 @@
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 +310,7 @@
(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 +326,7 @@
// 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 +334,37 @@
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");
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 +396,10 @@
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.
///
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp
index 8806888..315d3d8 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 @@
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 @@
// 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);
@@ -357,12 +348,6 @@
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 +868,147 @@
#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;
+/// 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};
- 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");
-}
+static_assert(array_lengthof(RegList8) == array_lengthof(RegList16),
+ "8-bit and 15-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;
- }
+ // 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;
- // 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;
-
- 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->getABITypeAlignment(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);
+/// 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;
+ unsigned NumArgs = Args.size();
- if (FuncName.startswith("__udivmod") || FuncName.startswith("__divmod")) {
- CCInfo.AnalyzeCallOperands(*Outs, ArgCC_AVR_BUILTIN_DIV);
+ for (unsigned i = 0; i != NumArgs; ++i) {
+ MVT VT = Args[i].VT;
+ TotalBytes += VT.getStoreSize();
+ }
+ return TotalBytes;
+}
+
+/// 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 greter 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 {
- analyzeStandardArguments(&CLI, F, TD, Outs, Ins,
- CallConv, ArgLocs, CCInfo,
- IsCall, IsVarArg);
+ TotalBytes = alignTo(TotalBytes, 2);
}
-}
-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;
+ // 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");
}
- default: {
- analyzeStandardArguments(CLI, F, TD, Outs, Ins,
- CallConv, ArgLocs, CCInfo,
- IsCall, IsVarArg);
- return;
- }
+ 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 +1018,12 @@
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 +1144,12 @@
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 +1286,10 @@
*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 +1308,17 @@
// 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 +1334,19 @@
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 +1364,12 @@
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.
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.h b/llvm/lib/Target/AVR/AVRISelLowering.h
index aca1ea1..d1eaf53 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.h
+++ b/llvm/lib/Target/AVR/AVRISelLowering.h
@@ -146,10 +146,8 @@
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/AVRInstrInfo.cpp b/llvm/lib/Target/AVR/AVRInstrInfo.cpp
index a6832f2..534141c 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.cpp
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.cpp
@@ -48,7 +48,7 @@
// 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 {
diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td
index acf991d..ca5600c 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.td
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.td
@@ -107,7 +107,9 @@
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 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 >= 0x0 && 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 >= 0x0 && 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 >= 0x0 && val < 0x3f;
}], ioaddr_XFORM>;
def iobitpos8 : PatLeaf<(imm),
@@ -555,7 +560,7 @@
def MULSRdRr : FMUL2RdRr<0,
(outs),
- (ins GPR8:$lhs, GPR8:$rhs),
+ (ins LD8:$lhs, LD8:$rhs),
"muls\t$lhs, $rhs",
[]>,
Requires<[SupportsMultiplication]>;
@@ -563,28 +568,28 @@
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]>;
@@ -2042,8 +2047,6 @@
(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 5226e30..5432fac 100644
--- a/llvm/lib/Target/AVR/AVRMachineFunctionInfo.h
+++ b/llvm/lib/Target/AVR/AVRMachineFunctionInfo.h
@@ -31,6 +31,12 @@
/// 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 @@
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 @@
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 8fce05c..d74c40c 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 @@
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 {
diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.td b/llvm/lib/Target/AVR/AVRRegisterInfo.td
index ea38fed..8e36971 100644
--- a/llvm/lib/Target/AVR/AVRRegisterInfo.td
+++ b/llvm/lib/Target/AVR/AVRRegisterInfo.td
@@ -103,6 +103,16 @@
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 i32
+ 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 +163,22 @@
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 6a41036..195ca95 100644
--- a/llvm/lib/Target/AVR/AVRSubtarget.cpp
+++ b/llvm/lib/Target/AVR/AVRSubtarget.cpp
@@ -29,16 +29,19 @@
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 da9289a..81d883e 100644
--- a/llvm/lib/Target/AVR/AVRSubtarget.h
+++ b/llvm/lib/Target/AVR/AVRSubtarget.h
@@ -71,6 +71,9 @@
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 @@
}
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 @@
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/AVRTargetObjectFile.cpp b/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
index 980096a0..14206cd 100644
--- a/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
+++ b/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
@@ -30,7 +30,7 @@
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/MCTargetDesc/AVRAsmBackend.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
index e92b16c..9dd385c 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
@@ -89,8 +89,6 @@
// one.
signed_width(Size + 1, Value, std::string("branch target"), Fixup, Ctx);
- Value -= 2;
-
// Rightshifts the value by one.
AVR::fixups::adjustBranchTarget(Value);
}
@@ -139,6 +137,18 @@
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.
///
@@ -237,17 +247,6 @@
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 @@
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/test/CodeGen/AVR/PR37143.ll b/llvm/test/CodeGen/AVR/PR37143.ll
index 72f4a2f..c7cabd3 100644
--- a/llvm/test/CodeGen/AVR/PR37143.ll
+++ b/llvm/test/CodeGen/AVR/PR37143.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s
+; RUN: llc -mattr=avr6,sram < %s -march=avr -verify-machineinstrs | FileCheck %s
; CHECK: ld {{r[0-9]+}}, [[PTR:[XYZ]]]
; CHECK: ldd {{r[0-9]+}}, [[PTR]]+1
diff --git a/llvm/test/CodeGen/AVR/add.ll b/llvm/test/CodeGen/AVR/add.ll
index cd3a69e..30f23b1 100644
--- a/llvm/test/CodeGen/AVR/add.ll
+++ b/llvm/test/CodeGen/AVR/add.ll
@@ -45,6 +45,17 @@
ret i16 %result
}
+define i16 @add16_reg_reg_zext(i16 %a, i1 zeroext %b) {
+; CHECK-LABEL: add16_reg_reg_zext:
+; CHECK: mov r18, r22
+; CHECK: clr r19
+; CHECK: add r24, r18
+; CHECK: adc r25, r19
+ %zext = zext i1 %b to i16
+ %result = add i16 %a, %zext
+ ret i16 %result
+}
+
define i32 @add32_reg_reg(i32 %a, i32 %b) {
; CHECK-LABEL: add32_reg_reg:
; CHECK: add r22, r18
@@ -65,6 +76,21 @@
ret i32 %result
}
+define i32 @add32_reg_reg_zext(i32 %a, i1 zeroext %b) {
+; CHECK-LABEL: add32_reg_reg_zext:
+; CHECK: mov r18, r20
+; CHECK: clr r19
+; CHECK: ldi r20, 0
+; CHECK: ldi r21, 0
+; CHECK: add r22, r18
+; CHECK: adc r23, r19
+; CHECK: adc r24, r20
+; CHECK: adc r25, r21
+ %zext = zext i1 %b to i32
+ %result = add i32 %a, %zext
+ ret i32 %result
+}
+
define i64 @add64_reg_reg(i64 %a, i64 %b) {
; CHECK-LABEL: add64_reg_reg:
; CHECK: add r18, r10
@@ -91,3 +117,22 @@
%result = add i64 %a, 5
ret i64 %result
}
+
+define i64 @add64_reg_reg_zext(i64 %a, i1 zeroext %b) {
+; CHECK-LABEL: add64_reg_reg_zext:
+; CHECK: mov r30, r16
+; CHECK: clr r31
+; CHECK: ldi r26, 0
+; CHECK: ldi r27, 0
+; CHECK: add r18, r30
+; CHECK: adc r19, r31
+; CHECK: adc r20, r26
+; CHECK: adc r21, r27
+; CHECK: adc r22, r26
+; CHECK: adc r23, r27
+; CHECK: adc r24, r26
+; CHECK: adc r25, r27
+ %zext = zext i1 %b to i64
+ %result = add i64 %a, %zext
+ ret i64 %result
+}
diff --git a/llvm/test/CodeGen/AVR/brind.ll b/llvm/test/CodeGen/AVR/brind.ll
index ec8262e..4eea966 100644
--- a/llvm/test/CodeGen/AVR/brind.ll
+++ b/llvm/test/CodeGen/AVR/brind.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mattr=sram,eijmpcall < %s -march=avr | FileCheck %s
+; RUN: llc -mattr=sram,eijmpcall < %s -march=avr -verify-machineinstrs | FileCheck %s
@brind.k = private unnamed_addr constant [2 x i8*] [i8* blockaddress(@brind, %return), i8* blockaddress(@brind, %b)], align 1
diff --git a/llvm/test/CodeGen/AVR/call.ll b/llvm/test/CodeGen/AVR/call.ll
index a2556e8..3cf821e 100644
--- a/llvm/test/CodeGen/AVR/call.ll
+++ b/llvm/test/CodeGen/AVR/call.ll
@@ -32,8 +32,8 @@
; CHECK-LABEL: calli8_stack:
; CHECK: ldi [[REG1:r[0-9]+]], 10
; CHECK: ldi [[REG2:r[0-9]+]], 11
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+1, [[REG1]]
+; CHECK: std Z+2, [[REG2]]
; CHECK: call foo8_3
%result1 = call i8 @foo8_3(i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 9, i8 10, i8 11)
ret i8 %result1
@@ -54,12 +54,12 @@
; CHECK-LABEL: calli16_stack:
; CHECK: ldi [[REG1:r[0-9]+]], 9
; CHECK: ldi [[REG2:r[0-9]+]], 2
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+1, [[REG1]]
+; CHECK: std Z+2, [[REG2]]
; CHECK: ldi [[REG1:r[0-9]+]], 10
; CHECK: ldi [[REG2:r[0-9]+]], 2
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+3, [[REG1]]
+; CHECK: std Z+4, [[REG2]]
; CHECK: call foo16_2
%result1 = call i16 @foo16_2(i16 512, i16 513, i16 514, i16 515, i16 516, i16 517, i16 518, i16 519, i16 520, i16 521, i16 522)
ret i16 %result1
@@ -84,12 +84,12 @@
; CHECK-LABEL: calli32_stack:
; CHECK: ldi [[REG1:r[0-9]+]], 64
; CHECK: ldi [[REG2:r[0-9]+]], 66
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+1, [[REG1]]
+; CHECK: std Z+2, [[REG2]]
; CHECK: ldi [[REG1:r[0-9]+]], 15
; CHECK: ldi [[REG2:r[0-9]+]], 2
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+3, [[REG1]]
+; CHECK: std Z+4, [[REG2]]
; CHECK: call foo32_2
%result1 = call i32 @foo32_2(i32 1, i32 2, i32 3, i32 4, i32 34554432)
ret i32 %result1
@@ -115,20 +115,20 @@
; CHECK: ldi [[REG1:r[0-9]+]], 76
; CHECK: ldi [[REG2:r[0-9]+]], 73
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+5, [[REG1]]
+; CHECK: std Z+6, [[REG2]]
; CHECK: ldi [[REG1:r[0-9]+]], 31
; CHECK: ldi [[REG2:r[0-9]+]], 242
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+7, [[REG1]]
+; CHECK: std Z+8, [[REG2]]
; CHECK: ldi [[REG1:r[0-9]+]], 155
; CHECK: ldi [[REG2:r[0-9]+]], 88
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+3, [[REG1]]
+; CHECK: std Z+4, [[REG2]]
; CHECK: ldi [[REG1:r[0-9]+]], 255
; CHECK: ldi [[REG2:r[0-9]+]], 255
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+1, [[REG1]]
+; CHECK: std Z+2, [[REG2]]
; CHECK: call foo64_2
%result1 = call i64 @foo64_2(i64 1, i64 2, i64 17446744073709551615)
ret i64 %result1
diff --git a/llvm/test/CodeGen/AVR/calling-conv/c/basic_aggr.ll b/llvm/test/CodeGen/AVR/calling-conv/c/basic_aggr.ll
new file mode 100644
index 0000000..0f6cf0e
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/calling-conv/c/basic_aggr.ll
@@ -0,0 +1,84 @@
+; RUN: llc < %s -march=avr | FileCheck %s
+
+; CHECK-LABEL: ret_void_args_struct_i8_i32
+define void @ret_void_args_struct_i8_i32({ i8, i32 } %a) {
+start:
+ ; CHECK: sts 4, r20
+ %0 = extractvalue { i8, i32 } %a, 0
+ store volatile i8 %0, i8* inttoptr (i64 4 to i8*)
+
+ ; CHECK-NEXT: sts 8, r24
+ ; CHECK-NEXT: sts 7, r23
+ ; CHECK-NEXT: sts 6, r22
+ ; CHECK-NEXT: sts 5, r21
+ %1 = extractvalue { i8, i32 } %a, 1
+ store volatile i32 %1, i32* inttoptr (i64 5 to i32*)
+ ret void
+}
+
+; CHECK-LABEL: ret_void_args_struct_i8_i8_i8_i8
+define void @ret_void_args_struct_i8_i8_i8_i8({ i8, i8, i8, i8 } %a) {
+start:
+ ; CHECK: sts 4, r22
+ %0 = extractvalue { i8, i8, i8, i8 } %a, 0
+ store volatile i8 %0, i8* inttoptr (i64 4 to i8*)
+ ; CHECK-NEXT: sts 5, r23
+ %1 = extractvalue { i8, i8, i8, i8 } %a, 1
+ store volatile i8 %1, i8* inttoptr (i64 5 to i8*)
+ ; CHECK-NEXT: sts 6, r24
+ %2 = extractvalue { i8, i8, i8, i8 } %a, 2
+ store volatile i8 %2, i8* inttoptr (i64 6 to i8*)
+ ; CHECK-NEXT: sts 7, r25
+ %3 = extractvalue { i8, i8, i8, i8 } %a, 3
+ store volatile i8 %3, i8* inttoptr (i64 7 to i8*)
+ ret void
+}
+
+; CHECK-LABEL: ret_void_args_struct_i32_16_i8
+define void @ret_void_args_struct_i32_16_i8({ i32, i16, i8} %a) {
+start:
+ ; CHECK: sts 7, r21
+ ; CHECK-NEXT: sts 6, r20
+ ; CHECK-NEXT: sts 5, r19
+ ; CHECK-NEXT: sts 4, r18
+ %0 = extractvalue { i32, i16, i8 } %a, 0
+ store volatile i32 %0, i32* inttoptr (i64 4 to i32*)
+
+ ; CHECK-NEXT: sts 5, r23
+ ; CHECK-NEXT: sts 4, r22
+ %1 = extractvalue { i32, i16, i8 } %a, 1
+ store volatile i16 %1, i16* inttoptr (i64 4 to i16*)
+
+ ; CHECK-NEXT: sts 4, r24
+ %2 = extractvalue { i32, i16, i8 } %a, 2
+ store volatile i8 %2, i8* inttoptr (i64 4 to i8*)
+ ret void
+}
+
+; CHECK-LABEL: ret_void_args_struct_i8_i32_struct_i32_i8
+define void @ret_void_args_struct_i8_i32_struct_i32_i8({ i8, i32 } %a, { i32, i8 } %b) {
+start:
+ ; CHECK: sts 4, r20
+ %0 = extractvalue { i8, i32 } %a, 0
+ store volatile i8 %0, i8* inttoptr (i64 4 to i8*)
+
+ ; CHECK-NEXT: sts 8, r24
+ ; CHECK-NEXT: sts 7, r23
+ ; CHECK-NEXT: sts 6, r22
+ ; CHECK-NEXT: sts 5, r21
+ %1 = extractvalue { i8, i32 } %a, 1
+ store volatile i32 %1, i32* inttoptr (i64 5 to i32*)
+
+ ; CHECK-NEXT: sts 9, r17
+ ; CHECK-NEXT: sts 8, r16
+ ; CHECK-NEXT: sts 7, r15
+ ; CHECK-NEXT: sts 6, r14
+ %2 = extractvalue { i32, i8 } %b, 0
+ store volatile i32 %2, i32* inttoptr (i64 6 to i32*)
+
+ ; CHECK-NEXT: sts 7, r18
+ %3 = extractvalue { i32, i8 } %b, 1
+ store volatile i8 %3, i8* inttoptr (i64 7 to i8*)
+ ret void
+}
+
diff --git a/llvm/test/CodeGen/AVR/calling-conv/c/call.ll b/llvm/test/CodeGen/AVR/calling-conv/c/call.ll
new file mode 100644
index 0000000..e218ed3
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/calling-conv/c/call.ll
@@ -0,0 +1,89 @@
+; RUN: llc < %s -march=avr | FileCheck %s
+
+declare void @ret_void_args_i8(i8 %a)
+declare void @ret_void_args_i8_i32(i8 %a, i32 %b)
+declare void @ret_void_args_i8_i8_i8_i8(i8 %a, i8 %b, i8 %c, i8 %d)
+declare void @ret_void_args_i32_i16_i8(i32 %a, i16 %b, i8 %c)
+declare void @ret_void_args_i64(i64 %a)
+declare void @ret_void_args_i64_i64(i64 %a, i64 %b)
+declare void @ret_void_args_i64_i64_i16(i64 %a, i64 %b, i16 %c)
+
+; CHECK-LABEL: call_void_args_i8
+define void @call_void_args_i8() {
+ ; CHECK: ldi r24, 64
+ call void @ret_void_args_i8 (i8 64)
+ ret void
+}
+
+; CHECK-LABEL: call_void_args_i8_i32
+define void @call_void_args_i8_i32() {
+ ; CHECK: ldi r20, 4
+ ; CHECK-NEXT: ldi r21, 3
+ ; CHECK-NEXT: ldi r22, 2
+ ; CHECK-NEXT: ldi r23, 1
+ ; CHECK-NEXT: ldi r24, 64
+ call void @ret_void_args_i8_i32 (i8 64, i32 16909060)
+ ret void
+}
+
+; CHECK-LABEL: call_void_args_i8_i8_i8_i8
+define void @call_void_args_i8_i8_i8_i8() {
+ ; CHECK: ldi r24, 1
+ ; CHECK-NEXT: ldi r22, 2
+ ; CHECK-NEXT: ldi r20, 3
+ ; CHECK-NEXT: ldi r18, 4
+ call void @ret_void_args_i8_i8_i8_i8(i8 1, i8 2, i8 3, i8 4)
+ ret void
+}
+
+; CHECK-LABEL: call_void_args_i32_i16_i8
+define void @call_void_args_i32_i16_i8() {
+ ; CHECK: ldi r22, 4
+ ; CHECK-NEXT: ldi r23, 3
+ ; CHECK-NEXT: ldi r24, 2
+ ; CHECK-NEXT: ldi r25, 1
+ ; CHECK-NEXT: ldi r20, 1
+ ; CHECK-NEXT: ldi r21, 4
+ ; CHECK-NEXT: ldi r18, 64
+ call void @ret_void_args_i32_i16_i8(i32 16909060, i16 1025, i8 64)
+ ret void
+}
+
+; CHECK-LABEL: call_void_args_i64
+define void @call_void_args_i64() {
+ ; CHECK: ldi r18, 8
+ ; CHECK-NEXT: ldi r19, 7
+ ; CHECK-NEXT: ldi r20, 6
+ ; CHECK-NEXT: ldi r21, 5
+ ; CHECK-NEXT: ldi r22, 4
+ ; CHECK-NEXT: ldi r23, 3
+ ; CHECK-NEXT: ldi r24, 2
+ ; CHECK-NEXT: ldi r25, 1
+ call void @ret_void_args_i64(i64 72623859790382856)
+ ret void
+}
+
+; CHECK-LABEL: call_void_args_i64_i64
+define void @call_void_args_i64_i64() {
+ ; CHECK: ldi r18, 8
+ ; CHECK-NEXT: ldi r19, 7
+ ; CHECK-NEXT: ldi r20, 6
+ ; CHECK-NEXT: ldi r21, 5
+ ; CHECK-NEXT: ldi r22, 4
+ ; CHECK-NEXT: ldi r23, 3
+ ; CHECK-NEXT: ldi r24, 2
+ ; CHECK-NEXT: ldi r25, 1
+ ; the second arg is in r10:r17, but unordered
+ ; CHECK: r17,
+ ; CHECK: r10,
+ call void @ret_void_args_i64_i64(i64 72623859790382856, i64 651345242494996224)
+ ret void
+}
+
+; CHECK-LABEL: call_void_args_i64_i64_i16
+define void @call_void_args_i64_i64_i16() {
+ ; CHECK: r8,
+ ; CHECK: r9,
+ call void @ret_void_args_i64_i64_i16(i64 72623859790382856, i64 651345242494996224, i16 5655)
+ ret void
+}
diff --git a/llvm/test/CodeGen/AVR/calling-conv/c/call_aggr.ll b/llvm/test/CodeGen/AVR/calling-conv/c/call_aggr.ll
new file mode 100644
index 0000000..aeba3c8
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/calling-conv/c/call_aggr.ll
@@ -0,0 +1,48 @@
+; RUN: llc < %s -march=avr | FileCheck %s
+
+declare void @ret_void_args_struct_i8_i32({ i8, i32 } %a)
+declare void @ret_void_args_struct_i8_i8_i8_i8({ i8, i8, i8, i8 } %a)
+declare void @ret_void_args_struct_i32_i16_i8({ i32, i16, i8} %a)
+declare void @ret_void_args_struct_i8_i32_struct_i32_i8({ i8, i32 } %a, { i32, i8 } %b)
+
+; CHECK-LABEL: call_void_args_struct_i8_i32
+define void @call_void_args_struct_i8_i32() {
+ ; CHECK: ldi r20, 64
+ ; CHECK-NEXT: r21,
+ ; CHECK-NEXT: r22,
+ ; CHECK-NEXT: r23,
+ ; CHECK-NEXT: r24,
+ call void @ret_void_args_struct_i8_i32({ i8, i32 } { i8 64, i32 16909060 })
+ ret void
+}
+
+; CHECK-LABEL: @call_void_args_struct_i8_i8_i8_i8
+define void @call_void_args_struct_i8_i8_i8_i8() {
+ ; CHECK: ldi r22, 1
+ ; CHECK-NEXT: ldi r23, 2
+ ; CHECK-NEXT: ldi r24, 3
+ ; CHECK-NEXT: ldi r25, 4
+ call void @ret_void_args_struct_i8_i8_i8_i8({ i8, i8, i8, i8 } { i8 1, i8 2, i8 3, i8 4 })
+ ret void
+}
+
+; CHECK-LABEL: @call_void_args_struct_i32_i16_i8
+define void @call_void_args_struct_i32_i16_i8() {
+ ; CHECK: ldi r18, 4
+ ; CHECK-NEXT: ldi r19, 3
+ ; CHECK-NEXT: ldi r20, 2
+ ; CHECK-NEXT: ldi r21, 1
+ ; CHECK-NEXT: ldi r22, 23
+ ; CHECK-NEXT: ldi r23, 22
+ ; CHECK-NEXT: ldi r24, 64
+ call void @ret_void_args_struct_i32_i16_i8({ i32, i16, i8 } { i32 16909060, i16 5655, i8 64 })
+ ret void
+}
+
+; CHECK-LABEL: @call_void_args_struct_i8_i32_struct_i32_i8
+define void @call_void_args_struct_i8_i32_struct_i32_i8() {
+ ; CHECK: ldi r20, 64
+ ; CHECK: ldi r18, 65
+ call void @ret_void_args_struct_i8_i32_struct_i32_i8({ i8, i32 } { i8 64, i32 16909060 }, { i32, i8 } { i32 287454020, i8 65 })
+ ret void
+}
diff --git a/llvm/test/CodeGen/AVR/calling-conv/c/return_aggr.ll b/llvm/test/CodeGen/AVR/calling-conv/c/return_aggr.ll
new file mode 100644
index 0000000..97668f6
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/calling-conv/c/return_aggr.ll
@@ -0,0 +1,31 @@
+; RUN: llc < %s -march=avr | FileCheck %s
+
+; CHECK-LABEL: ret_struct_i8_i16_i8
+define { i8, i16, i8 } @ret_struct_i8_i16_i8() {
+start:
+ ; for some reason the i16 is loaded to r24:r25
+ ; and then moved to r23:r24
+ ; CHECK: ldi r22, 64
+ ; CHECK-NEXT: r23,
+ ; CHECK-NEXT: r24,
+ ; CHECK-NEXT: r25, 11
+ %0 = insertvalue {i8, i16, i8} undef, i8 64, 0
+ %1 = insertvalue {i8, i16, i8} %0, i16 1024, 1
+ %2 = insertvalue {i8, i16, i8} %1, i8 11, 2
+ ret {i8, i16, i8} %2
+}
+
+; CHECK-LABEL: ret_struct_i32_i16
+define { i32, i16 } @ret_struct_i32_i16() {
+start:
+ ; CHECK: ldi r18, 4
+ ; CHECK-NEXT: ldi r19, 3
+ ; CHECK-NEXT: ldi r20, 2
+ ; CHECK-NEXT: ldi r21, 1
+ ; CHECK-NEXT: ldi r22, 0
+ ; CHECK-NEXT: ldi r23, 8
+ %0 = insertvalue { i32, i16 } undef, i32 16909060, 0
+ %1 = insertvalue { i32, i16 } %0, i16 2048, 1
+ ret { i32, i16} %1
+}
+
diff --git a/llvm/test/CodeGen/AVR/calling-conv/c/stack.ll b/llvm/test/CodeGen/AVR/calling-conv/c/stack.ll
index 52b6427..00ff7d1 100644
--- a/llvm/test/CodeGen/AVR/calling-conv/c/stack.ll
+++ b/llvm/test/CodeGen/AVR/calling-conv/c/stack.ll
@@ -11,15 +11,15 @@
; CHECK-NEXT: in r29, 62
; Load the top two bytes from the 32-bit int.
- ; CHECK-NEXT: ldd r24, Y+5
- ; CHECK-NEXT: ldd r25, Y+6
+ ; CHECK-NEXT: ldd r24, Y+7
+ ; CHECK-NEXT: ldd r25, Y+8
; Store the top two bytes of the 32-bit int to memory.
; CHECK-NEXT: sts 7, r25
; CHECK-NEXT: sts 6, r24
; Load the bottom two bytes from the 32-bit int.
- ; CHECK-NEXT: ldd r24, Y+3
- ; CHECK-NEXT: ldd r25, Y+4
+ ; CHECK-NEXT: ldd r24, Y+5
+ ; CHECK-NEXT: ldd r25, Y+6
; Store the bottom two bytes of the 32-bit int to memory.
; CHECK-NEXT: sts 5, r25
; CHECK-NEXT: sts 4, r24
diff --git a/llvm/test/CodeGen/AVR/div.ll b/llvm/test/CodeGen/AVR/div.ll
index 7626ecb..b222294 100644
--- a/llvm/test/CodeGen/AVR/div.ll
+++ b/llvm/test/CodeGen/AVR/div.ll
@@ -65,15 +65,7 @@
; Unsigned 64-bit division
define i64 @udiv64(i64 %a, i64 %b) {
; CHECK-LABEL: udiv64:
-; CHECK: call __udivmoddi4
-; CHECK-NEXT: ldd r18, Y+1
-; CHECK-NEXT: ldd r19, Y+2
-; CHECK-NEXT: ldd r20, Y+3
-; CHECK-NEXT: ldd r21, Y+4
-; CHECK-NEXT: ldd r22, Y+5
-; CHECK-NEXT: ldd r23, Y+6
-; CHECK-NEXT: ldd r24, Y+7
-; CHECK-NEXT: ldd r25, Y+8
+; CHECK: call __udivdi3
; CHECK: ret
%quot = udiv i64 %a, %b
ret i64 %quot
@@ -82,15 +74,7 @@
; Signed 64-bit division
define i64 @sdiv64(i64 %a, i64 %b) {
; CHECK-LABEL: sdiv64:
-; CHECK: call __divmoddi4
-; CHECK-NEXT: ldd r18, Y+1
-; CHECK-NEXT: ldd r19, Y+2
-; CHECK-NEXT: ldd r20, Y+3
-; CHECK-NEXT: ldd r21, Y+4
-; CHECK-NEXT: ldd r22, Y+5
-; CHECK-NEXT: ldd r23, Y+6
-; CHECK-NEXT: ldd r24, Y+7
-; CHECK-NEXT: ldd r25, Y+8
+; CHECK: call __divdi3
; CHECK: ret
%quot = sdiv i64 %a, %b
ret i64 %quot
@@ -99,7 +83,7 @@
; Unsigned 128-bit division
define i128 @udiv128(i128 %a, i128 %b) {
; CHECK-LABEL: udiv128:
-; CHECK: call __udivmodti4
+; CHECK: call __udivti3
; CHECK: ret
%quot = udiv i128 %a, %b
ret i128 %quot
@@ -108,7 +92,7 @@
; Signed 128-bit division
define i128 @sdiv128(i128 %a, i128 %b) {
; CHECK-LABEL: sdiv128:
-; CHECK: call __divmodti4
+; CHECK: call __divti3
; CHECK: ret
%quot = sdiv i128 %a, %b
ret i128 %quot
diff --git a/llvm/test/CodeGen/AVR/dynalloca.ll b/llvm/test/CodeGen/AVR/dynalloca.ll
index 6aa776e..f314fb0 100644
--- a/llvm/test/CodeGen/AVR/dynalloca.ll
+++ b/llvm/test/CodeGen/AVR/dynalloca.ll
@@ -53,9 +53,27 @@
; CHECK-LABEL: dynalloca2:
; CHECK: in [[SPCOPY1:r[0-9]+]], 61
; CHECK: in [[SPCOPY2:r[0-9]+]], 62
-; CHECK: push
-; CHECK-NOT: st
-; CHECK-NOT: std
+; Allocate stack space for call
+; CHECK: in {{.*}}, 61
+; CHECK: in {{.*}}, 62
+; CHECK: subi
+; CHECK: sbci
+; CHECK: in r0, 63
+; CHECK-NEXT: cli
+; CHECK-NEXT: out 62, {{.*}}
+; CHECK-NEXT: out 63, r0
+; CHECK-NEXT: out 61, {{.*}}
+; Store values on the stack
+; CHECK: ldi r16, 0
+; CHECK: ldi r17, 0
+; CHECK: std Z+5, r16
+; CHECK: std Z+6, r17
+; CHECK: std Z+7, r16
+; CHECK: std Z+8, r17
+; CHECK: std Z+3, r16
+; CHECK: std Z+4, r17
+; CHECK: std Z+1, r16
+; CHECK: std Z+2, r17
; CHECK: call
; Call frame restore
; CHECK-NEXT: in r30, 61
diff --git a/llvm/test/CodeGen/AVR/features/xmega_io.ll b/llvm/test/CodeGen/AVR/features/xmega_io.ll
new file mode 100644
index 0000000..713b2de
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/features/xmega_io.ll
@@ -0,0 +1,48 @@
+; RUN: llc -O0 < %s -march=avr -mcpu avrxmega1 | FileCheck %s -check-prefix=XMEGA
+; RUN: llc -O0 < %s -march=avr -mcpu avrxmega2 | FileCheck %s -check-prefix=XMEGA
+; RUN: llc -O0 < %s -march=avr -mcpu avrxmega3 | FileCheck %s -check-prefix=XMEGA
+; RUN: llc -O0 < %s -march=avr -mcpu avrxmega4 | FileCheck %s -check-prefix=XMEGA
+; RUN: llc -O0 < %s -march=avr -mcpu avrxmega5 | FileCheck %s -check-prefix=XMEGA
+; RUN: llc -O0 < %s -march=avr -mcpu avrxmega6 | FileCheck %s -check-prefix=XMEGA
+; RUN: llc -O0 < %s -march=avr -mcpu avrxmega7 | FileCheck %s -check-prefix=XMEGA
+; RUN: llc -O0 < %s -march=avr -mcpu avr2 | FileCheck %s -check-prefix=AVR
+; RUN: llc -O0 < %s -march=avr -mcpu avr25 | FileCheck %s -check-prefix=AVR
+; RUN: llc -O0 < %s -march=avr -mcpu avr3 | FileCheck %s -check-prefix=AVR
+; RUN: llc -O0 < %s -march=avr -mcpu avr31 | FileCheck %s -check-prefix=AVR
+; RUN: llc -O0 < %s -march=avr -mcpu avr35 | FileCheck %s -check-prefix=AVR
+; RUN: llc -O0 < %s -march=avr -mcpu avr4 | FileCheck %s -check-prefix=AVR
+; RUN: llc -O0 < %s -march=avr -mcpu avr5 | FileCheck %s -check-prefix=AVR
+; RUN: llc -O0 < %s -march=avr -mcpu avr51 | FileCheck %s -check-prefix=AVR
+; RUN: llc -O0 < %s -march=avr -mcpu avr6 | FileCheck %s -check-prefix=AVR
+
+define i8 @read8_low_io() {
+; CHECK-LABEL: read8_low_io
+; XMEGA: in r24, 8
+; AVR: lds r24, 8
+ %1 = load i8, i8* inttoptr (i16 8 to i8*)
+ ret i8 %1
+}
+
+define i8 @read8_hi_io() {
+; CHECK-LABEL: read8_hi_io
+; XMEGA: in r24, 40
+; AVR: in r24, 8
+ %1 = load i8, i8* inttoptr (i16 40 to i8*)
+ ret i8 %1
+}
+
+define i8 @read8_maybe_io() {
+; CHECK-LABEL: read8_maybe_io
+; XMEGA: lds r24, 80
+; AVR: in r24, 48
+ %1 = load i8, i8* inttoptr (i16 80 to i8*)
+ ret i8 %1
+}
+
+define i8 @read8_not_io(){
+; CHECK-LABEL: read8_not_io
+; XMEGA: lds r24, 160
+; AVR: lds r24, 160
+ %1 = load i8, i8* inttoptr (i16 160 to i8*)
+ ret i8 %1
+}
diff --git a/llvm/test/CodeGen/AVR/interrupts.ll b/llvm/test/CodeGen/AVR/interrupts.ll
index 5dddf0e..b402d86 100644
--- a/llvm/test/CodeGen/AVR/interrupts.ll
+++ b/llvm/test/CodeGen/AVR/interrupts.ll
@@ -16,6 +16,22 @@
ret void
}
+define void @interrupt_handler_via_ir_attribute() #0 {
+; CHECK-LABEL: interrupt_handler_via_ir_attribute:
+; CHECK: sei
+; CHECK-NEXT: push r0
+; CHECK-NEXT: push r1
+; CHECK-NEXT: in r0, 63
+; CHECK-NEXT: push r0
+; CHECK: clr r0
+; CHECK: pop r0
+; CHECK-NEXT: out 63, r0
+; CHECK-NEXT: pop r1
+; CHECK-NEXT: pop r0
+; CHECK-NEXT: reti
+ ret void
+}
+
define avr_signalcc void @signal_handler() {
; CHECK-LABEL: signal_handler:
; CHECK-NOT: sei
@@ -31,3 +47,22 @@
; CHECK-NEXT: reti
ret void
}
+
+define void @signal_handler_via_attribute() #1 {
+; CHECK-LABEL: signal_handler_via_attribute:
+; CHECK-NOT: sei
+; CHECK: push r0
+; CHECK-NEXT: push r1
+; CHECK-NEXT: in r0, 63
+; CHECK-NEXT: push r0
+; CHECK: clr r0
+; CHECK: pop r0
+; CHECK-NEXT: out 63, r0
+; CHECK-NEXT: pop r1
+; CHECK-NEXT: pop r0
+; CHECK-NEXT: reti
+ ret void
+}
+
+attributes #0 = { "interrupt" }
+attributes #1 = { "signal" }
diff --git a/llvm/test/CodeGen/AVR/jmp-long.ll b/llvm/test/CodeGen/AVR/jmp-long.ll
new file mode 100644
index 0000000..9878fda
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/jmp-long.ll
@@ -0,0 +1,1045 @@
+; RUN: llc -filetype=obj -march avr -mattr=jmpcall < %s | llvm-objdump -dr --mattr=jmpcall - | FileCheck %s
+
+; Test the fix in https://reviews.llvm.org/D78459.
+; Long branches (that use jmp instead of rjmp) were broken: the jump was to a
+; location 0x20000 away from where it should be. This test is a regression test
+; to make sure long branches are correct.
+
+declare void @bar() addrspace(1)
+
+define void @foo() addrspace(1) {
+ br label %1
+
+1: ; preds = %0, %1
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ tail call addrspace(0) void asm sideeffect "nop", ""()
+ ; CHECK: call 0
+ ; CHECK: R_AVR_CALL bar
+ ; CHECK: jmp 0
+ ; CHECK: R_AVR_CALL .text
+ tail call addrspace(1) void @bar()
+ br label %1
+}
diff --git a/llvm/test/CodeGen/AVR/load.ll b/llvm/test/CodeGen/AVR/load.ll
index dbadacf..53748b3 100644
--- a/llvm/test/CodeGen/AVR/load.ll
+++ b/llvm/test/CodeGen/AVR/load.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s
+; RUN: llc -mattr=avr6,sram < %s -march=avr -verify-machineinstrs | FileCheck %s
define i8 @load8(i8* %x) {
; CHECK-LABEL: load8:
diff --git a/llvm/test/CodeGen/AVR/pseudo/LDWRdPtr.mir b/llvm/test/CodeGen/AVR/pseudo/LDWRdPtr.mir
index 5bd4bf2..2343d0d 100644
--- a/llvm/test/CodeGen/AVR/pseudo/LDWRdPtr.mir
+++ b/llvm/test/CodeGen/AVR/pseudo/LDWRdPtr.mir
@@ -17,7 +17,7 @@
; CHECK-LABEL: test_ldwrdptr
- ; CHECK: $r0, $r31r30 = LDRdPtr
+ ; CHECK: $r0 = LDRdPtr $r31r30
; CHECK-NEXT: $r1 = LDDRdPtrQ $r31r30, 1
$r1r0 = LDWRdPtr $r31r30
diff --git a/llvm/test/CodeGen/AVR/return.ll b/llvm/test/CodeGen/AVR/return.ll
index 6d81faa..15157036 100644
--- a/llvm/test/CodeGen/AVR/return.ll
+++ b/llvm/test/CodeGen/AVR/return.ll
@@ -96,14 +96,14 @@
; CHECK-LABEL: return64_arg2:
; CHECK: push r28
; CHECK: push r29
-; CHECK: ldd r18, Y+3
-; CHECK: ldd r19, Y+4
-; CHECK: ldd r20, Y+5
-; CHECK: ldd r21, Y+6
-; CHECK: ldd r22, Y+7
-; CHECK: ldd r23, Y+8
-; CHECK: ldd r24, Y+9
-; CHECK: ldd r25, Y+10
+; CHECK: ldd r18, Y+5
+; CHECK: ldd r19, Y+6
+; CHECK: ldd r20, Y+7
+; CHECK: ldd r21, Y+8
+; CHECK: ldd r22, Y+9
+; CHECK: ldd r23, Y+10
+; CHECK: ldd r24, Y+11
+; CHECK: ldd r25, Y+12
; CHECK: pop r29
; CHECK: pop r28
ret i64 %z
@@ -113,10 +113,10 @@
; CHECK-LABEL: return64_trunc:
; CHECK: push r28
; CHECK: push r29
-; CHECK: ldd r22, Y+3
-; CHECK: ldd r23, Y+4
-; CHECK: ldd r24, Y+5
-; CHECK: ldd r25, Y+6
+; CHECK: ldd r22, Y+5
+; CHECK: ldd r23, Y+6
+; CHECK: ldd r24, Y+7
+; CHECK: ldd r25, Y+8
; CHECK: pop r29
; CHECK: pop r28
%result = trunc i64 %d to i32
diff --git a/llvm/test/CodeGen/AVR/sections.ll b/llvm/test/CodeGen/AVR/sections.ll
new file mode 100644
index 0000000..6d125d3
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/sections.ll
@@ -0,0 +1,31 @@
+; RUN: llc < %s -march=avr | FileCheck --check-prefixes=CHECK,NOSECTIONS %s
+; RUN: llc -function-sections -data-sections < %s -march=avr | FileCheck --check-prefixes=CHECK,SECTIONS %s
+
+; Test that functions (in address space 1) are not considered .progmem data.
+
+; CHECK: .text
+; SECTIONS: .text.somefunc,"ax",@progbits
+; CHECK-LABEL: somefunc:
+define void @somefunc() addrspace(1) {
+ ret void
+}
+
+
+; Test whether global variables are placed in the correct section.
+
+; Note: avr-gcc would place this global in .progmem.data.flash with
+; -fdata-sections. The AVR backend does not yet respect -fdata-sections in this
+; case.
+; CHECK: .section .progmem.data,"a",@progbits
+; CHECK-LABEL: flash:
+@flash = addrspace(1) constant i16 3
+
+; NOSECTIONS: .section .rodata,"a",@progbits
+; SECTIONS: .section .rodata.ram1,"a",@progbits
+; CHECK-LABEL: ram1:
+@ram1 = constant i16 3
+
+; NOSECTIONS: .data
+; SECTIONS: .section .data.ram2,"aw",@progbits
+; CHECK-LABEL: ram2:
+@ram2 = global i16 3
diff --git a/llvm/test/CodeGen/AVR/varargs.ll b/llvm/test/CodeGen/AVR/varargs.ll
index 7224ac3..a743374 100644
--- a/llvm/test/CodeGen/AVR/varargs.ll
+++ b/llvm/test/CodeGen/AVR/varargs.ll
@@ -7,12 +7,12 @@
define i16 @varargs1(i8* nocapture %x, ...) {
; CHECK-LABEL: varargs1:
; CHECK: movw r20, r28
-; CHECK: subi r20, 217
+; CHECK: subi r20, 215
; CHECK: sbci r21, 255
; CHECK: movw r24, r28
; CHECK: adiw r24, 3
-; CHECK: ldd r22, Y+37
-; CHECK: ldd r23, Y+38
+; CHECK: ldd r22, Y+39
+; CHECK: ldd r23, Y+40
; CHECK: call
%buffer = alloca [32 x i8]
%ap = alloca i8*
@@ -42,16 +42,16 @@
; CHECK-LABEL: varargcall:
; CHECK: ldi [[REG1:r[0-9]+]], 189
; CHECK: ldi [[REG2:r[0-9]+]], 205
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+3, [[REG1]]
+; CHECK: std Z+4, [[REG2]]
; CHECK: ldi [[REG1:r[0-9]+]], 191
; CHECK: ldi [[REG2:r[0-9]+]], 223
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+5, [[REG1]]
+; CHECK: std Z+6, [[REG2]]
; CHECK: ldi [[REG1:r[0-9]+]], 205
; CHECK: ldi [[REG2:r[0-9]+]], 171
-; CHECK: push [[REG2]]
-; CHECK: push [[REG1]]
+; CHECK: std Z+1, [[REG1]]
+; CHECK: std Z+2, [[REG2]]
; CHECK: call
; CHECK: adiw r30, 6
tail call void (i16, ...) @var1223(i16 -21555, i16 -12867, i16 -8257)
diff --git a/llvm/test/MC/AVR/relocations-abs.s b/llvm/test/MC/AVR/relocations-abs.s
new file mode 100644
index 0000000..1055ed5
--- /dev/null
+++ b/llvm/test/MC/AVR/relocations-abs.s
@@ -0,0 +1,8 @@
+; RUN: llvm-mc -filetype=obj -triple=avr %s | llvm-objdump -dr - | FileCheck %s
+
+; CHECK: bar:
+; CHECK-NEXT: 00 00 nop
+; CHECK-NEXT: R_AVR_16 .text+0x2
+bar:
+ .short 1f
+1:
diff --git a/llvm/test/MC/AVR/relocations.s b/llvm/test/MC/AVR/relocations.s
index 3d22e5d0..666ff3d 100644
--- a/llvm/test/MC/AVR/relocations.s
+++ b/llvm/test/MC/AVR/relocations.s
@@ -9,6 +9,9 @@
; CHECK: R_AVR_LDI SYMBOL+0x3
ldi r21, SYMBOL+3
+; CHECK: R_AVR_6 SYMBOL+0x4
+ldd r8, Y+SYMBOL+4
+
; CHECK-NEXT: R_AVR_6_ADIW FOO
adiw r24, FOO