mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[AVR] Fix I/O instructions on XMEGA
Summary: On XMEGA, I/O address space is same as data address space - there is no 0x20 offset, because CPU General Purpose Registers are not mapped in data address space. From https://en.wikipedia.org/wiki/AVR_microcontrollers > In the XMEGA variant, the working register file is not mapped into the data address space; as such, it is not possible to treat any of the XMEGA's working registers as though they were SRAM. Instead, the I/O registers are mapped into the data address space starting at the very beginning of the address space. Reviewers: dylanmckay Reviewed By: dylanmckay Subscribers: hiraditya, Jim, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D77207 Patch by Vlastimil Labsky.
This commit is contained in:
parent
b7d2d21a27
commit
97babd4ccf
@ -121,6 +121,11 @@ def FeatureTinyEncoding : SubtargetFeature<"tinyencoding",
|
||||
"The device has Tiny core specific "
|
||||
"instruction encodings">;
|
||||
|
||||
// The device has CPU registers mapped in data address space
|
||||
def FeatureMMR : SubtargetFeature<"memmappedregs", "m_hasMemMappedGPR",
|
||||
"true", "The device has CPU registers "
|
||||
"mapped in data address space">;
|
||||
|
||||
class ELFArch<string name> : SubtargetFeature<"", "ELFArch",
|
||||
!strconcat("ELF::",name), "">;
|
||||
|
||||
@ -152,7 +157,7 @@ def ELFArchXMEGA7 : ELFArch<"EF_AVR_ARCH_XMEGA7">;
|
||||
// device should have.
|
||||
def FamilyAVR0 : Family<"avr0", []>;
|
||||
|
||||
def FamilyAVR1 : Family<"avr1", [FamilyAVR0, FeatureLPM]>;
|
||||
def FamilyAVR1 : Family<"avr1", [FamilyAVR0, FeatureLPM, FeatureMMR]>;
|
||||
|
||||
def FamilyAVR2 : Family<"avr2",
|
||||
[FamilyAVR1, FeatureIJMPCALL, FeatureADDSUBIW,
|
||||
@ -190,11 +195,14 @@ def FamilyAVR6 : Family<"avr6",
|
||||
|
||||
def FamilyTiny : Family<"avrtiny",
|
||||
[FamilyAVR0, FeatureBREAK, FeatureSRAM,
|
||||
FeatureTinyEncoding]>;
|
||||
FeatureTinyEncoding, FeatureMMR]>;
|
||||
|
||||
def FamilyXMEGA : Family<"xmega",
|
||||
[FamilyAVR51, FeatureEIJMPCALL, FeatureSPMX,
|
||||
FeatureDES]>;
|
||||
[FamilyAVR0, FeatureLPM, FeatureIJMPCALL, FeatureADDSUBIW,
|
||||
FeatureSRAM, FeatureJMPCALL, FeatureMultiplication,
|
||||
FeatureMOVW, FeatureLPMX, FeatureSPM,
|
||||
FeatureBREAK, FeatureEIJMPCALL, FeatureSPMX,
|
||||
FeatureDES, FeatureELPM, FeatureELPMX]>;
|
||||
|
||||
def FamilyXMEGAU : Family<"xmegau",
|
||||
[FamilyXMEGA, FeatureRMW]>;
|
||||
@ -208,7 +216,7 @@ def FeatureSetSpecial : FeatureSet<"special",
|
||||
FeatureLPM, FeatureLPMX, FeatureELPM,
|
||||
FeatureELPMX, FeatureSPM, FeatureSPMX,
|
||||
FeatureDES, FeatureRMW,
|
||||
FeatureMultiplication, FeatureBREAK]>;
|
||||
FeatureMultiplication, FeatureBREAK, FeatureMMR]>;
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
// AVR microcontrollers supported.
|
||||
|
@ -107,7 +107,9 @@ def imm_com8 : Operand<i8> {
|
||||
|
||||
def ioaddr_XFORM : SDNodeXForm<imm,
|
||||
[{
|
||||
return CurDAG->getTargetConstant(uint8_t(N->getZExtValue()) - 0x20, SDLoc(N), MVT::i8);
|
||||
uint8_t offset = Subtarget->getIORegisterOffset();
|
||||
return CurDAG->getTargetConstant(uint8_t(N->getZExtValue()) - offset,
|
||||
SDLoc(N), MVT::i8);
|
||||
}]>;
|
||||
|
||||
def iobitpos8_XFORM : SDNodeXForm<imm,
|
||||
@ -124,20 +126,23 @@ def iobitposn8_XFORM : SDNodeXForm<imm,
|
||||
|
||||
def ioaddr8 : PatLeaf<(imm),
|
||||
[{
|
||||
uint64_t val = N->getZExtValue();
|
||||
return val >= 0x20 && val < 0x60;
|
||||
uint8_t offset = Subtarget->getIORegisterOffset();
|
||||
uint64_t val = N->getZExtValue() - offset;
|
||||
return val >= 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),
|
||||
|
@ -29,16 +29,16 @@ namespace llvm {
|
||||
|
||||
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() {
|
||||
|
@ -71,6 +71,9 @@ public:
|
||||
bool supportsMultiplication() const { return m_supportsMultiplication; }
|
||||
bool hasBREAK() const { return m_hasBREAK; }
|
||||
bool hasTinyEncoding() const { return m_hasTinyEncoding; }
|
||||
bool hasMemMappedGPR() const { return m_hasMemMappedGPR; }
|
||||
|
||||
uint8_t getIORegisterOffset() const { return hasMemMappedGPR() ? 0x20 : 0x0; }
|
||||
|
||||
/// Gets the ELF architecture for the e_flags field
|
||||
/// of an ELF object file.
|
||||
@ -105,6 +108,7 @@ private:
|
||||
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.
|
||||
|
48
test/CodeGen/AVR/features/xmega_io.ll
Normal file
48
test/CodeGen/AVR/features/xmega_io.ll
Normal file
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user