]>
Commit | Line | Data |
---|---|---|
64c2fd3a JR |
1 | diff -Naurp gcc/config/avr/avr.c gcc/config/avr/avr.c |
2 | --- gcc/config/avr/avr.c 2012-11-09 19:05:47.000000000 +0530 | |
3 | +++ gcc/config/avr/avr.c 2012-11-14 13:57:13.000000000 +0530 | |
4 | @@ -2801,6 +2801,35 @@ avr_out_xload (rtx insn ATTRIBUTE_UNUSED | |
5 | return ""; | |
6 | } | |
7 | ||
8 | +/* | |
9 | +AVRTC-579 | |
10 | +if operand is symbol or constant expression with value > 0xbf | |
11 | + return false, otherwise true | |
12 | +This check is used to avoid lds/sts instruction with invalid memory | |
13 | +access range (valid range 0x40..0xbf). For io operand range 0x0..0x3f, | |
14 | +in/out instruction will be generated. | |
15 | +*/ | |
16 | +bool tiny_valid_direct_memory_access_range(rtx op, enum machine_mode mode) | |
17 | +{ | |
18 | + rtx x; | |
19 | + | |
20 | + if (!AVR_TINY) | |
21 | + return true; | |
22 | + | |
23 | + x = XEXP(op,0); | |
24 | + | |
25 | + if (MEM_P(op) && x && (GET_CODE(x) == SYMBOL_REF)) | |
26 | + { | |
27 | + return false; | |
28 | + } | |
29 | + if (MEM_P(op) && x && (CONSTANT_ADDRESS_P (x)) && | |
30 | + !(IN_RANGE (INTVAL (x), 0, 0xC0 - GET_MODE_SIZE (mode)))) | |
31 | + { | |
32 | + return false; | |
33 | + } | |
34 | + | |
35 | + return true; | |
36 | +} | |
37 | ||
38 | const char* | |
39 | output_movqi (rtx insn, rtx operands[], int *real_l) | |
40 | @@ -2956,9 +2985,10 @@ out_movqi_r_mr (rtx insn, rtx op[], int | |
41 | ||
42 | if (CONSTANT_ADDRESS_P (x)) | |
43 | { | |
44 | + int n_words = AVR_TINY ? 1 : 2; | |
45 | return optimize > 0 && io_address_operand (x, QImode) | |
46 | ? avr_asm_len ("in %0,%i1", op, plen, -1) | |
47 | - : avr_asm_len ("lds %0,%m1", op, plen, -2); | |
48 | + : avr_asm_len ("lds %0,%m1", op, plen, -n_words); | |
49 | } | |
50 | ||
51 | ||
52 | @@ -3213,12 +3243,13 @@ out_movhi_r_mr (rtx insn, rtx op[], int | |
53 | } | |
54 | else if (CONSTANT_ADDRESS_P (base)) | |
55 | { | |
56 | + int n_words = AVR_TINY ? 2 : 4; | |
57 | return optimize > 0 && io_address_operand (base, HImode) | |
58 | ? avr_asm_len ("in %A0,%i1" CR_TAB | |
59 | "in %B0,%i1+1", op, plen, -2) | |
60 | ||
61 | : avr_asm_len ("lds %A0,%m1" CR_TAB | |
62 | - "lds %B0,%m1+1", op, plen, -4); | |
63 | + "lds %B0,%m1+1", op, plen, -n_words); | |
64 | } | |
65 | ||
66 | fatal_insn ("unknown move insn:",insn); | |
67 | @@ -3478,10 +3509,24 @@ out_movsi_r_mr (rtx insn, rtx op[], int | |
68 | "ld %C0,%1" CR_TAB | |
69 | "ld %D0,%1"); | |
70 | else if (CONSTANT_ADDRESS_P (base)) | |
71 | - return *l=8, ("lds %A0,%m1" CR_TAB | |
72 | - "lds %B0,%m1+1" CR_TAB | |
73 | - "lds %C0,%m1+2" CR_TAB | |
74 | - "lds %D0,%m1+3"); | |
75 | + { | |
76 | + if (io_address_operand (base, SImode)) | |
77 | + { | |
78 | + *l = 4; | |
79 | + return ("in %A0,%i1" CR_TAB | |
80 | + "in %B0,%i1+1" CR_TAB | |
81 | + "in %C0,%i1+2" CR_TAB | |
82 | + "in %D0,%i1+3"); | |
83 | + } | |
84 | + else | |
85 | + { | |
86 | + *l = AVR_TINY ? 4 : 8; | |
87 | + return ("lds %A0,%m1" CR_TAB | |
88 | + "lds %B0,%m1+1" CR_TAB | |
89 | + "lds %C0,%m1+2" CR_TAB | |
90 | + "lds %D0,%m1+3"); | |
91 | + } | |
92 | + } | |
93 | ||
94 | fatal_insn ("unknown move insn:",insn); | |
95 | return ""; | |
96 | @@ -3608,10 +3653,24 @@ out_movsi_mr_r (rtx insn, rtx op[], int | |
97 | l = &tmp; | |
98 | ||
99 | if (CONSTANT_ADDRESS_P (base)) | |
100 | - return *l=8,("sts %m0,%A1" CR_TAB | |
101 | - "sts %m0+1,%B1" CR_TAB | |
102 | - "sts %m0+2,%C1" CR_TAB | |
103 | - "sts %m0+3,%D1"); | |
104 | + { | |
105 | + if (io_address_operand (base, SImode)) | |
106 | + { | |
107 | + return *l=4,("out %i0, %A1" CR_TAB | |
108 | + "out %i0+1,%B1" CR_TAB | |
109 | + "out %i0+2,%C1" CR_TAB | |
110 | + "out %i0+3,%D1"); | |
111 | + } | |
112 | + else | |
113 | + { | |
114 | + *l = AVR_TINY ? 4 : 8; | |
115 | + return ("sts %m0,%A1" CR_TAB | |
116 | + "sts %m0+1,%B1" CR_TAB | |
117 | + "sts %m0+2,%C1" CR_TAB | |
118 | + "sts %m0+3,%D1"); | |
119 | + } | |
120 | + } | |
121 | + | |
122 | if (reg_base > 0) /* (r) */ | |
123 | { | |
124 | if (AVR_TINY) | |
125 | @@ -4031,9 +4090,12 @@ avr_out_load_psi (rtx insn, rtx *op, int | |
126 | "ld %C0,%1", op, plen, -3); | |
127 | ||
128 | else if (CONSTANT_ADDRESS_P (base)) | |
129 | + { | |
130 | + int n_words = AVR_TINY ? 3 : 6; | |
131 | return avr_asm_len ("lds %A0,%m1" CR_TAB | |
132 | "lds %B0,%m1+1" CR_TAB | |
133 | - "lds %C0,%m1+2", op, plen , -6); | |
134 | + "lds %C0,%m1+2", op, plen , -n_words); | |
135 | + } | |
136 | ||
137 | fatal_insn ("unknown move insn:",insn); | |
138 | return ""; | |
139 | @@ -4129,9 +4191,12 @@ avr_out_store_psi (rtx insn, rtx *op, in | |
140 | int reg_base = true_regnum (base); | |
141 | ||
142 | if (CONSTANT_ADDRESS_P (base)) | |
143 | + { | |
144 | + int n_words = AVR_TINY ? 3 : 6; | |
145 | return avr_asm_len ("sts %m0,%A1" CR_TAB | |
146 | "sts %m0+1,%B1" CR_TAB | |
147 | - "sts %m0+2,%C1", op, plen, -6); | |
148 | + "sts %m0+2,%C1", op, plen, -n_words); | |
149 | + } | |
150 | ||
151 | if (reg_base > 0) /* (r) */ | |
152 | { | |
153 | @@ -4314,9 +4379,10 @@ out_movqi_mr_r (rtx insn, rtx op[], int | |
154 | ||
155 | if (CONSTANT_ADDRESS_P (x)) | |
156 | { | |
157 | + int n_words = AVR_TINY ? 1 : 2; | |
158 | return optimize > 0 && io_address_operand (x, QImode) | |
159 | ? avr_asm_len ("out %i0,%1", op, plen, -1) | |
160 | - : avr_asm_len ("sts %m0,%1", op, plen, -2); | |
161 | + : avr_asm_len ("sts %m0,%1", op, plen, -n_words); | |
162 | } | |
163 | else if (GET_CODE (x) == PLUS | |
164 | && REG_P (XEXP (x, 0)) | |
165 | @@ -4389,12 +4455,15 @@ avr_out_movhi_mr_r_xmega (rtx insn, rtx | |
166 | int mem_volatile_p = MEM_VOLATILE_P (dest); | |
167 | ||
168 | if (CONSTANT_ADDRESS_P (base)) | |
169 | + { | |
170 | + int n_words = AVR_TINY ? 2 : 4; | |
171 | return optimize > 0 && io_address_operand (base, HImode) | |
172 | ? avr_asm_len ("out %i0,%A1" CR_TAB | |
173 | "out %i0+1,%B1", op, plen, -2) | |
174 | ||
175 | : avr_asm_len ("sts %m0,%A1" CR_TAB | |
176 | - "sts %m0+1,%B1", op, plen, -4); | |
177 | + "sts %m0+1,%B1", op, plen, -n_words); | |
178 | + } | |
179 | ||
180 | if (reg_base > 0) | |
181 | { | |
182 | @@ -4574,12 +4643,15 @@ out_movhi_mr_r (rtx insn, rtx op[], int | |
183 | mem_volatile_p = MEM_VOLATILE_P (dest); | |
184 | ||
185 | if (CONSTANT_ADDRESS_P (base)) | |
186 | + { | |
187 | + int n_words = AVR_TINY ? 2 : 4; | |
188 | return optimize > 0 && io_address_operand (base, HImode) | |
189 | ? avr_asm_len ("out %i0+1,%B1" CR_TAB | |
190 | "out %i0,%A1", op, plen, -2) | |
191 | ||
192 | : avr_asm_len ("sts %m0+1,%B1" CR_TAB | |
193 | - "sts %m0,%A1", op, plen, -4); | |
194 | + "sts %m0,%A1", op, plen, -n_words); | |
195 | + } | |
196 | ||
197 | if (reg_base > 0) | |
198 | { | |
199 | diff -Naurp gcc/config/avr/avr.md gcc/config/avr/avr.md | |
200 | --- gcc/config/avr/avr.md 2012-11-09 19:05:47.000000000 +0530 | |
201 | +++ gcc/config/avr/avr.md 2012-11-14 13:57:13.000000000 +0530 | |
202 | @@ -629,6 +629,32 @@ | |
203 | DONE; | |
204 | } | |
205 | ||
206 | + /* AVRTC-579 | |
207 | + if the source operand expression is out of range for 'lds' instruction | |
208 | + copy source operand expression to register | |
209 | + For tiny core, LDS instruction's memory access range limited to 0x40..0xbf | |
210 | + */ | |
211 | + if (!tiny_valid_direct_memory_access_range(src,<MODE>mode)) | |
212 | + { | |
213 | + rtx srcx = XEXP(src,0); | |
214 | + operands[1] = src = replace_equiv_address (src,copy_to_mode_reg (GET_MODE(srcx),srcx)); | |
215 | + emit_move_insn(dest,src); | |
216 | + DONE; | |
217 | + } | |
218 | + | |
219 | + /* AVRTC-579 | |
220 | + if the destination operand expression is out of range for 'sts' instruction | |
221 | + copy destination operand expression to register | |
222 | + For tiny core, STS instruction's memory access range limited to 0x40..0xbf | |
223 | + */ | |
224 | + if (!tiny_valid_direct_memory_access_range(dest,<MODE>mode)) | |
225 | + { | |
226 | + rtx destx = XEXP(dest,0); | |
227 | + operands[0] = dest = replace_equiv_address (dest,copy_to_mode_reg (GET_MODE(destx),destx)); | |
228 | + emit_move_insn(dest,src); | |
229 | + DONE; | |
230 | + } | |
231 | + | |
232 | /* ; The only address-space for which we use plain MEM and reload | |
233 | ; machinery are 1-byte loads from __flash. */ | |
234 | }) | |
235 | @@ -645,9 +671,14 @@ | |
236 | (define_insn "movqi_insn" | |
237 | [(set (match_operand:QI 0 "nonimmediate_operand" "=r ,d,Qm,r ,q,r,*r") | |
238 | (match_operand:QI 1 "nox_general_operand" "rL,i,rL,Qm,r,q,i"))] | |
239 | - "register_operand (operands[0], QImode) | |
240 | + "(register_operand (operands[0], QImode) | |
241 | || register_operand (operands[1], QImode) | |
242 | - || const0_rtx == operands[1]" | |
243 | + || const0_rtx == operands[1]) && | |
244 | + /* skip if operands are out of lds/sts memory access range(0x40..0xbf) | |
245 | + though access range is checked during define_expand, it is required | |
246 | + here to avoid merging rtls during combine pass */ | |
247 | + tiny_valid_direct_memory_access_range(operands[0],QImode) && | |
248 | + tiny_valid_direct_memory_access_range(operands[1],QImode)" | |
249 | { | |
250 | return output_movqi (insn, operands, NULL); | |
251 | } | |
252 | @@ -732,9 +763,14 @@ | |
253 | (define_insn "*movhi" | |
254 | [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m ,d,*r,q,r") | |
255 | (match_operand:HI 1 "nox_general_operand" "r,L,m,rL,i,i ,r,q"))] | |
256 | - "register_operand (operands[0], HImode) | |
257 | + "(register_operand (operands[0], HImode) | |
258 | || register_operand (operands[1], HImode) | |
259 | - || const0_rtx == operands[1]" | |
260 | + || const0_rtx == operands[1]) && | |
261 | + /* skip if operands are out of lds/sts memory access range(0x40..0xbf) | |
262 | + though access range is checked during define_expand, it is required | |
263 | + here to avoid merging rtls during combine pass */ | |
264 | + tiny_valid_direct_memory_access_range(operands[0],HImode) && | |
265 | + tiny_valid_direct_memory_access_range(operands[1],HImode)" | |
266 | { | |
267 | return output_movhi (insn, operands, NULL); | |
268 | } | |
269 | @@ -842,9 +878,15 @@ | |
270 | (define_insn "*movsi" | |
271 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r") | |
272 | (match_operand:SI 1 "nox_general_operand" "r,L,Qm,rL,i ,i"))] | |
273 | - "register_operand (operands[0], SImode) | |
274 | + "((register_operand (operands[0], SImode) | |
275 | || register_operand (operands[1], SImode) | |
276 | - || const0_rtx == operands[1]" | |
277 | + || const0_rtx == operands[1]) && | |
278 | + /* skip if operands are out of lds/sts memory access range(0x40..0xbf) | |
279 | + though access range is checked during define_expand, it is required | |
280 | + here to avoid merging rtls during combine pass */ | |
281 | + tiny_valid_direct_memory_access_range(operands[0],SImode) && | |
282 | + tiny_valid_direct_memory_access_range(operands[1],SImode)) | |
283 | + " | |
284 | { | |
285 | return output_movsisf (insn, operands, NULL); | |
286 | } | |
287 | @@ -858,9 +900,15 @@ | |
288 | (define_insn "*movsf" | |
289 | [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r") | |
290 | (match_operand:SF 1 "nox_general_operand" "r,G,Qm,rG,F ,F"))] | |
291 | - "register_operand (operands[0], SFmode) | |
292 | + "((register_operand (operands[0], SFmode) | |
293 | || register_operand (operands[1], SFmode) | |
294 | - || operands[1] == CONST0_RTX (SFmode)" | |
295 | + || operands[1] == CONST0_RTX (SFmode)) && | |
296 | + /* skip if operands are out of lds/sts memory access range(0x40..0xbf) | |
297 | + though access range is checked during define_expand, it is required | |
298 | + here to avoid merging rtls during combine pass */ | |
299 | + tiny_valid_direct_memory_access_range(operands[0],SFmode) && | |
300 | + tiny_valid_direct_memory_access_range(operands[1],SFmode)) | |
301 | + " | |
302 | { | |
303 | return output_movsisf (insn, operands, NULL); | |
304 | } |