"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), "">;
// 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,
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]>;
FeatureLPM, FeatureLPMX, FeatureELPM,
FeatureELPMX, FeatureSPM, FeatureSPMX,
FeatureDES, FeatureRMW,
- FeatureMultiplication, FeatureBREAK]>;
+ FeatureMultiplication, FeatureBREAK, FeatureMMR]>;
//===---------------------------------------------------------------------===//
// AVR microcontrollers supported.
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,
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),
AVRSubtarget::AVRSubtarget(const Triple &TT, const std::string &CPU,
const std::string &FS, const AVRTargetMachine &TM)
- : AVRGenSubtargetInfo(TT, CPU, FS),
- ELFArch(0),
+ : 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), m_FeatureSetDummy(false),
+ m_hasTinyEncoding(false), m_hasMemMappedGPR(false),
+ m_FeatureSetDummy(false),
InstrInfo(), FrameLowering(),
TLInfo(TM, initializeSubtargetDependencies(CPU, FS, TM)), TSInfo() {
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.
bool m_supportsMultiplication;
bool m_hasBREAK;
bool m_hasTinyEncoding;
+ 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.
--- /dev/null
+; 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
+}