27
27
#include " llvm/Support/MathExtras.h"
28
28
#include " llvm/Support/raw_ostream.h"
29
29
30
- // FIXME: we should be doing checks to make sure asm operands
31
- // are not out of bounds.
32
-
33
30
namespace adjust {
34
31
35
32
using namespace llvm ;
36
33
37
34
static void signed_width (unsigned Width, uint64_t Value,
38
35
std::string Description, const MCFixup &Fixup,
39
- MCContext *Ctx = nullptr ) {
36
+ MCContext *Ctx) {
40
37
if (!isIntN (Width, Value)) {
41
38
std::string Diagnostic = " out of range " + Description;
42
39
@@ -46,17 +43,13 @@ static void signed_width(unsigned Width, uint64_t Value,
46
43
Diagnostic += " (expected an integer in the range " + std::to_string (Min) +
47
44
" to " + std::to_string (Max) + " )" ;
48
45
49
- if (Ctx) {
50
- Ctx->reportError (Fixup.getLoc (), Diagnostic);
51
- } else {
52
- llvm_unreachable (Diagnostic.c_str ());
53
- }
46
+ Ctx->reportError (Fixup.getLoc (), Diagnostic);
54
47
}
55
48
}
56
49
57
50
static void unsigned_width (unsigned Width, uint64_t Value,
58
51
std::string Description, const MCFixup &Fixup,
59
- MCContext *Ctx = nullptr ) {
52
+ MCContext *Ctx) {
60
53
if (!isUIntN (Width, Value)) {
61
54
std::string Diagnostic = " out of range " + Description;
62
55
@@ -65,17 +58,13 @@ static void unsigned_width(unsigned Width, uint64_t Value,
65
58
Diagnostic +=
66
59
" (expected an integer in the range 0 to " + std::to_string (Max) + " )" ;
67
60
68
- if (Ctx) {
69
- Ctx->reportError (Fixup.getLoc (), Diagnostic);
70
- } else {
71
- llvm_unreachable (Diagnostic.c_str ());
72
- }
61
+ Ctx->reportError (Fixup.getLoc (), Diagnostic);
73
62
}
74
63
}
75
64
76
65
// / Adjusts the value of a branch target before fixup application.
77
66
static void adjustBranch (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
78
- MCContext *Ctx = nullptr ) {
67
+ MCContext *Ctx) {
79
68
// We have one extra bit of precision because the value is rightshifted by
80
69
// one.
81
70
unsigned_width (Size + 1 , Value, std::string (" branch target" ), Fixup, Ctx);
@@ -86,13 +75,28 @@ static void adjustBranch(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
86
75
87
76
// / Adjusts the value of a relative branch target before fixup application.
88
77
static void adjustRelativeBranch (unsigned Size , const MCFixup &Fixup,
89
- uint64_t &Value, MCContext *Ctx = nullptr ) {
78
+ uint64_t &Value, MCContext *Ctx) {
90
79
// Jumps are relative to the current instruction.
91
80
Value -= 2 ;
92
81
93
82
// We have one extra bit of precision because the value is rightshifted by
94
83
// one.
95
- signed_width (Size + 1 , Value, std::string (" branch target" ), Fixup, Ctx);
84
+ Size += 1 ;
85
+
86
+ if (!isIntN (Size , Value) &&
87
+ Ctx->getSubtargetInfo ()->hasFeature (AVR::FeatureWrappingRjmp)) {
88
+ const int32_t FlashSize = 0x2000 ;
89
+ int32_t SignedValue = Value;
90
+
91
+ uint64_t WrappedValue = SignedValue > 0 ? (uint64_t )(Value - FlashSize)
92
+ : (uint64_t )(FlashSize + Value);
93
+
94
+ if (isIntN (Size , WrappedValue)) {
95
+ Value = WrappedValue;
96
+ }
97
+ }
98
+
99
+ signed_width (Size , Value, std::string (" branch target" ), Fixup, Ctx);
96
100
97
101
// Rightshifts the value by one.
98
102
AVR::fixups::adjustBranchTarget (Value);
@@ -105,7 +109,7 @@ static void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup,
105
109
// /
106
110
// / Offset of 0 (so the result is left shifted by 3 bits before application).
107
111
static void fixup_call (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
108
- MCContext *Ctx = nullptr ) {
112
+ MCContext *Ctx) {
109
113
adjustBranch (Size , Fixup, Value, Ctx);
110
114
111
115
auto top = Value & (0xf00000 << 6 ); // the top four bits
@@ -121,7 +125,7 @@ static void fixup_call(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
121
125
// / 0000 00kk kkkk k000
122
126
// / Offset of 0 (so the result is left shifted by 3 bits before application).
123
127
static void fixup_7_pcrel (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
124
- MCContext *Ctx = nullptr ) {
128
+ MCContext *Ctx) {
125
129
adjustRelativeBranch (Size , Fixup, Value, Ctx);
126
130
127
131
// Because the value may be negative, we must mask out the sign bits
@@ -135,7 +139,7 @@ static void fixup_7_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
135
139
// / 0000 kkkk kkkk kkkk
136
140
// / Offset of 0 (so the result isn't left-shifted before application).
137
141
static void fixup_13_pcrel (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
138
- MCContext *Ctx = nullptr ) {
142
+ MCContext *Ctx) {
139
143
adjustRelativeBranch (Size , Fixup, Value, Ctx);
140
144
141
145
// Because the value may be negative, we must mask out the sign bits
@@ -147,8 +151,7 @@ static void fixup_13_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
147
151
// /
148
152
// / Resolves to:
149
153
// / 10q0 qq10 0000 1qqq
150
- static void fixup_6 (const MCFixup &Fixup, uint64_t &Value,
151
- MCContext *Ctx = nullptr ) {
154
+ static void fixup_6 (const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
152
155
unsigned_width (6 , Value, std::string (" immediate" ), Fixup, Ctx);
153
156
154
157
Value = ((Value & 0x20 ) << 8 ) | ((Value & 0x18 ) << 7 ) | (Value & 0x07 );
@@ -160,7 +163,7 @@ static void fixup_6(const MCFixup &Fixup, uint64_t &Value,
160
163
// / Resolves to:
161
164
// / 0000 0000 kk00 kkkk
162
165
static void fixup_6_adiw (const MCFixup &Fixup, uint64_t &Value,
163
- MCContext *Ctx = nullptr ) {
166
+ MCContext *Ctx) {
164
167
unsigned_width (6 , Value, std::string (" immediate" ), Fixup, Ctx);
165
168
166
169
Value = ((Value & 0x30 ) << 2 ) | (Value & 0x0f );
@@ -170,8 +173,7 @@ static void fixup_6_adiw(const MCFixup &Fixup, uint64_t &Value,
170
173
// /
171
174
// / Resolves to:
172
175
// / 0000 0000 AAAA A000
173
- static void fixup_port5 (const MCFixup &Fixup, uint64_t &Value,
174
- MCContext *Ctx = nullptr ) {
176
+ static void fixup_port5 (const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
175
177
unsigned_width (5 , Value, std::string (" port number" ), Fixup, Ctx);
176
178
177
179
Value &= 0x1f ;
@@ -183,8 +185,7 @@ static void fixup_port5(const MCFixup &Fixup, uint64_t &Value,
183
185
// /
184
186
// / Resolves to:
185
187
// / 1011 0AAd dddd AAAA
186
- static void fixup_port6 (const MCFixup &Fixup, uint64_t &Value,
187
- MCContext *Ctx = nullptr ) {
188
+ static void fixup_port6 (const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
188
189
unsigned_width (6 , Value, std::string (" port number" ), Fixup, Ctx);
189
190
190
191
Value = ((Value & 0x30 ) << 5 ) | (Value & 0x0f );
@@ -195,7 +196,7 @@ static void fixup_port6(const MCFixup &Fixup, uint64_t &Value,
195
196
// / Resolves to:
196
197
// / 1010 ikkk dddd kkkk
197
198
static void fixup_lds_sts_16 (const MCFixup &Fixup, uint64_t &Value,
198
- MCContext *Ctx = nullptr ) {
199
+ MCContext *Ctx) {
199
200
unsigned_width (7 , Value, std::string (" immediate" ), Fixup, Ctx);
200
201
Value = ((Value & 0x70 ) << 8 ) | (Value & 0x0f );
201
202
}
@@ -213,7 +214,7 @@ namespace ldi {
213
214
// / 0000 KKKK 0000 KKKK
214
215
// / Offset of 0 (so the result isn't left-shifted before application).
215
216
static void fixup (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
216
- MCContext *Ctx = nullptr ) {
217
+ MCContext *Ctx) {
217
218
uint64_t upper = Value & 0xf0 ;
218
219
uint64_t lower = Value & 0x0f ;
219
220
@@ -223,25 +224,25 @@ static void fixup(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
223
224
static void neg (uint64_t &Value) { Value *= -1 ; }
224
225
225
226
static void lo8 (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
226
- MCContext *Ctx = nullptr ) {
227
+ MCContext *Ctx) {
227
228
Value &= 0xff ;
228
229
ldi::fixup (Size , Fixup, Value, Ctx);
229
230
}
230
231
231
232
static void hi8 (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
232
- MCContext *Ctx = nullptr ) {
233
+ MCContext *Ctx) {
233
234
Value = (Value & 0xff00 ) >> 8 ;
234
235
ldi::fixup (Size , Fixup, Value, Ctx);
235
236
}
236
237
237
238
static void hh8 (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
238
- MCContext *Ctx = nullptr ) {
239
+ MCContext *Ctx) {
239
240
Value = (Value & 0xff0000 ) >> 16 ;
240
241
ldi::fixup (Size , Fixup, Value, Ctx);
241
242
}
242
243
243
244
static void ms8 (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
244
- MCContext *Ctx = nullptr ) {
245
+ MCContext *Ctx) {
245
246
Value = (Value & 0xff000000 ) >> 24 ;
246
247
ldi::fixup (Size , Fixup, Value, Ctx);
247
248
}
0 commit comments