diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp --- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp @@ -17,6 +17,7 @@ #include "AVRTargetMachine.h" #include "MCTargetDesc/AVRMCTargetDesc.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -1257,27 +1258,32 @@ template <> bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { + const AVRSubtarget &STI = MBB.getParent()->getSubtarget(); MachineInstr &MI = *MBBI; Register SrcLoReg, SrcHiReg; unsigned Imm = MI.getOperand(0).getImm(); Register SrcReg = MI.getOperand(1).getReg(); bool SrcIsKill = MI.getOperand(1).isKill(); - unsigned OpLo = AVR::OUTARr; - unsigned OpHi = AVR::OUTARr; TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg); // Since we add 1 to the Imm value for the high byte below, and 63 is the // highest Imm value allowed for the instruction, 62 is the limit here. assert(Imm <= 62 && "Address is out of range"); - // 16 bit I/O writes need the high byte first - auto MIBHI = buildMI(MBB, MBBI, OpHi) - .addImm(Imm + 1) - .addReg(SrcHiReg, getKillRegState(SrcIsKill)); + unsigned ELFArch = STI.getELFArch(); + bool XMega = + ELF::EF_AVR_ARCH_XMEGA1 <= ELFArch && ELFArch <= ELF::EF_AVR_ARCH_XMEGA7; - auto MIBLO = buildMI(MBB, MBBI, OpLo) - .addImm(Imm) - .addReg(SrcLoReg, getKillRegState(SrcIsKill)); + // 16 bit I/O writes need the high byte first on normal AVR devices, + // and in reverse order for the XMEGA/XMEGA3/XMEGAU families. + auto MIBHI = + buildMI(MBB, MBBI, AVR::OUTARr) + .addImm(XMega ? Imm : Imm + 1) + .addReg(XMega ? SrcLoReg : SrcHiReg, getKillRegState(SrcIsKill)); + auto MIBLO = + buildMI(MBB, MBBI, AVR::OUTARr) + .addImm(XMega ? Imm + 1 : Imm) + .addReg(XMega ? SrcHiReg : SrcLoReg, getKillRegState(SrcIsKill)); MIBLO.setMemRefs(MI.memoperands()); MIBHI.setMemRefs(MI.memoperands()); diff --git a/llvm/test/CodeGen/AVR/pseudo/OUTWARr.mir b/llvm/test/CodeGen/AVR/pseudo/OUTWARr.mir --- a/llvm/test/CodeGen/AVR/pseudo/OUTWARr.mir +++ b/llvm/test/CodeGen/AVR/pseudo/OUTWARr.mir @@ -1,4 +1,13 @@ -# RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny11 %s -o - \ +# RUN: | FileCheck %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atmega328 %s -o - \ +# RUN: | FileCheck %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny817 %s -o - \ +# RUN: | FileCheck --check-prefix=XMEGA %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atxmega64a1 %s -o - \ +# RUN: | FileCheck --check-prefix=XMEGA %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atxmega256a3u %s -o - \ +# RUN: | FileCheck --check-prefix=XMEGA %s --- | target triple = "avr--" @@ -15,9 +24,12 @@ liveins: $r15r14 ; CHECK-LABEL: test + ; CHECK: OUTARr 32, $r15 + ; CHECK-NEXT: OUTARr 31, $r14 - ; CHECK: OUTARr 32, $r15 - ; CHECK-NEXT: OUTARr 31, $r14 + ; XMEGA-LABEL: test + ; XMEGA: OUTARr 31, $r14 + ; XMEGA-NEXT: OUTARr 32, $r15 OUTWARr 31, $r15r14 ...