summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AVR
diff options
context:
space:
mode:
authorDylan McKay <me@dylanmckay.io>2017-10-04 09:51:21 +0000
committerDylan McKay <me@dylanmckay.io>2017-10-04 09:51:21 +0000
commit8aecc306836815170337da3bb3b9e46678a25c69 (patch)
treeea3c47be99376090b956e905acc541911396ee01 /llvm/lib/Target/AVR
parent749f2500d1b8b9a58ef334d9b16af51537758d18 (diff)
[AVR] Fix displacement overflow for LDDW/STDW
In some cases, the code generator attempts to generate instructions such as: lddw r24, Y+63 which expands to: ldd r24, Y+63 ldd r25, Y+64 # Oops! This is actually ld r25, Y in the binary This commit limits the first offset to 62, and thus the second to 63. It also updates some asserts in AVRExpandPseudoInsts.cpp, including for INW and OUTW, which appear to be unused. Patch by Thomas Backman.
Diffstat (limited to 'llvm/lib/Target/AVR')
-rw-r--r--llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp16
-rw-r--r--llvm/lib/Target/AVR/AVRRegisterInfo.cpp2
2 files changed, 13 insertions, 5 deletions
diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index 540e05a9299..400e9bd8fdc 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -699,7 +699,9 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
OpHi = AVR::LDDRdPtrQ;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
- assert(Imm <= 63 && "Offset is out of range");
+ // 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 && "Offset is out of range");
// Use a temporary register if src and dst registers are the same.
if (DstReg == SrcReg)
@@ -1074,7 +1076,9 @@ bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
OpHi = AVR::STDPtrQRr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
- assert(Imm <= 63 && "Offset is out of range");
+ // 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 && "Offset is out of range");
auto MIBLO = buildMI(MBB, MBBI, OpLo)
.addReg(DstReg)
@@ -1104,7 +1108,9 @@ bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {
OpHi = AVR::INRdA;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
- assert(Imm <= 63 && "Address is out of range");
+ // 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");
auto MIBLO = buildMI(MBB, MBBI, OpLo)
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
@@ -1132,7 +1138,9 @@ bool AVRExpandPseudo::expand<AVR::OUTWARr>(Block &MBB, BlockIt MBBI) {
OpHi = AVR::OUTARr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
- assert(Imm <= 63 && "Address is out of range");
+ // 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)
diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
index 249dc5512c2..7099b29a8bc 100644
--- a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
+++ b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
@@ -203,7 +203,7 @@ void AVRRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
// If the offset is too big we have to adjust and restore the frame pointer
// to materialize a valid load/store with displacement.
//:TODO: consider using only one adiw/sbiw chain for more than one frame index
- if (Offset > 63) {
+ if (Offset > 62) {
unsigned AddOpc = AVR::ADIWRdK, SubOpc = AVR::SBIWRdK;
int AddOffset = Offset - 63 + 1;