]>
Commit | Line | Data |
---|---|---|
64c2fd3a JR |
1 | diff -Naurp gcc/config/avr/avr.c gcc/config/avr/avr.c |
2 | --- gcc/config/avr/avr.c 2013-01-21 18:26:07.000000000 +0530 | |
3 | +++ gcc/config/avr/avr.c 2013-01-21 18:40:04.000000000 +0530 | |
4 | @@ -78,6 +78,17 @@ | |
5 | ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM) \ | |
6 | / SYMBOL_FLAG_MACH_DEP) | |
7 | ||
8 | +#define TINY_ADIW(REG1, REG2, I) \ | |
9 | + "subi " #REG1 ",lo8(-(" #I "))" CR_TAB \ | |
10 | + "sbci " #REG2 ",hi8(-(" #I "))" | |
11 | + | |
12 | +#define TINY_SBIW(REG1, REG2, I) \ | |
13 | + "subi " #REG1 ",lo8((" #I "))" CR_TAB \ | |
14 | + "sbci " #REG2 ",hi8((" #I "))" | |
15 | + | |
16 | +#define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO) | |
17 | +#define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO) | |
18 | + | |
19 | /* Known address spaces. The order must be the same as in the respective | |
20 | enum from avr.h (or designated initialized must be used). */ | |
21 | const avr_addrspace_t avr_addrspace[] = | |
22 | @@ -157,6 +168,9 @@ static bool avr_rtx_costs (rtx, int, int | |
23 | /* Allocate registers from r25 to r8 for parameters for function calls. */ | |
24 | #define FIRST_CUM_REG 26 | |
25 | ||
26 | +/* Last call saved register */ | |
27 | +#define LAST_CALLEE_SAVED_REG (AVR_TINY ? 21 : 17) | |
28 | + | |
29 | /* Implicit target register of LPM instruction (R0) */ | |
30 | extern GTY(()) rtx lpm_reg_rtx; | |
31 | rtx lpm_reg_rtx; | |
32 | @@ -306,7 +320,7 @@ avr_option_override (void) | |
33 | avr_addr.rampy = 0x3A + avr_current_arch->sfr_offset; | |
34 | avr_addr.rampx = 0x39 + avr_current_arch->sfr_offset; | |
35 | avr_addr.rampd = 0x38 + avr_current_arch->sfr_offset; | |
36 | - avr_addr.ccp = 0x34 + avr_current_arch->sfr_offset; | |
37 | + avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_current_arch->sfr_offset; | |
38 | ||
39 | /* SP: Stack Pointer (SP_H:SP_L) */ | |
40 | avr_addr.sp_l = 0x3D + avr_current_arch->sfr_offset; | |
41 | @@ -338,8 +352,8 @@ avr_init_expanders (void) | |
42 | all_regs_rtx[regno] = gen_rtx_REG (QImode, regno); | |
43 | ||
44 | lpm_reg_rtx = all_regs_rtx[LPM_REGNO]; | |
45 | - tmp_reg_rtx = all_regs_rtx[TMP_REGNO]; | |
46 | - zero_reg_rtx = all_regs_rtx[ZERO_REGNO]; | |
47 | + tmp_reg_rtx = all_regs_rtx[AVR_TMP_REGNO]; | |
48 | + zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO]; | |
49 | ||
50 | lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z); | |
51 | ||
52 | @@ -351,6 +365,11 @@ avr_init_expanders (void) | |
53 | ||
54 | xstring_empty = gen_rtx_CONST_STRING (VOIDmode, ""); | |
55 | xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e"); | |
56 | + | |
57 | + /* TINY core does not have regs r10-r16, but avr-dimode.md expects them | |
58 | + to be present */ | |
59 | + if (AVR_TINY) | |
60 | + avr_have_dimode = false; | |
61 | } | |
62 | ||
63 | ||
64 | @@ -792,7 +811,7 @@ sequent_regs_live (void) | |
65 | int live_seq=0; | |
66 | int cur_seq=0; | |
67 | ||
68 | - for (reg = 0; reg < 18; ++reg) | |
69 | + for (reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg) | |
70 | { | |
71 | if (fixed_regs[reg]) | |
72 | { | |
73 | @@ -903,7 +922,7 @@ emit_push_sfr (rtx sfr, bool frame_relat | |
74 | RTX_FRAME_RELATED_P (insn) = 1; | |
75 | ||
76 | /* PUSH __tmp_reg__ */ | |
77 | - emit_push_byte (TMP_REGNO, frame_related_p); | |
78 | + emit_push_byte (AVR_TMP_REGNO, frame_related_p); | |
79 | ||
80 | if (clr_p) | |
81 | { | |
82 | @@ -929,7 +948,8 @@ avr_prologue_setup_frame (HOST_WIDE_INT | |
83 | && live_seq | |
84 | && !isr_p | |
85 | && !cfun->machine->is_OS_task | |
86 | - && !cfun->machine->is_OS_main); | |
87 | + && !cfun->machine->is_OS_main | |
88 | + && !AVR_TINY); | |
89 | ||
90 | if (minimize | |
91 | && (frame_pointer_needed | |
92 | @@ -966,11 +986,11 @@ avr_prologue_setup_frame (HOST_WIDE_INT | |
93 | /* Note that live_seq always contains r28+r29, but the other | |
94 | registers to be saved are all below 18. */ | |
95 | ||
96 | - first_reg = 18 - (live_seq - 2); | |
97 | + first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2); | |
98 | ||
99 | for (reg = 29, offset = -live_seq + 1; | |
100 | reg >= first_reg; | |
101 | - reg = (reg == 28 ? 17 : reg - 1), ++offset) | |
102 | + reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset) | |
103 | { | |
104 | rtx m, r; | |
105 | ||
106 | @@ -1201,10 +1221,10 @@ expand_prologue (void) | |
107 | emit_insn (gen_enable_interrupt ()); | |
108 | ||
109 | /* Push zero reg. */ | |
110 | - emit_push_byte (ZERO_REGNO, true); | |
111 | + emit_push_byte (AVR_ZERO_REGNO, true); | |
112 | ||
113 | /* Push tmp reg. */ | |
114 | - emit_push_byte (TMP_REGNO, true); | |
115 | + emit_push_byte (AVR_TMP_REGNO, true); | |
116 | ||
117 | /* Push SREG. */ | |
118 | /* ??? There's no dwarf2 column reserved for SREG. */ | |
119 | @@ -1344,7 +1364,8 @@ expand_epilogue (bool sibcall_p) | |
120 | && live_seq | |
121 | && !isr_p | |
122 | && !cfun->machine->is_OS_task | |
123 | - && !cfun->machine->is_OS_main); | |
124 | + && !cfun->machine->is_OS_main | |
125 | + && !AVR_TINY); | |
126 | ||
127 | if (minimize | |
128 | && (live_seq > 4 | |
129 | @@ -1502,14 +1523,14 @@ expand_epilogue (bool sibcall_p) | |
130 | ||
131 | /* Restore SREG using tmp_reg as scratch. */ | |
132 | ||
133 | - emit_pop_byte (TMP_REGNO); | |
134 | + emit_pop_byte (AVR_TMP_REGNO); | |
135 | emit_move_insn (sreg_rtx, tmp_reg_rtx); | |
136 | ||
137 | /* Restore tmp REG. */ | |
138 | - emit_pop_byte (TMP_REGNO); | |
139 | + emit_pop_byte (AVR_TMP_REGNO); | |
140 | ||
141 | /* Restore zero REG. */ | |
142 | - emit_pop_byte (ZERO_REGNO); | |
143 | + emit_pop_byte (AVR_ZERO_REGNO); | |
144 | } | |
145 | ||
146 | if (!sibcall_p) | |
147 | @@ -2009,7 +2030,7 @@ avr_print_operand (FILE *file, rtx x, in | |
148 | fprintf (file, "__RAMPX__"); | |
149 | else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd) | |
150 | fprintf (file, "__RAMPD__"); | |
151 | - else if (AVR_XMEGA && ival == avr_addr.ccp) | |
152 | + else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp) | |
153 | fprintf (file, "__CCP__"); | |
154 | else if (ival == avr_addr.sreg) fprintf (file, "__SREG__"); | |
155 | else if (ival == avr_addr.sp_l) fprintf (file, "__SP_L__"); | |
156 | @@ -2052,6 +2073,13 @@ avr_print_operand (FILE *file, rtx x, in | |
157 | ||
158 | avr_print_operand (file, XEXP (addr, 1), 0); | |
159 | } | |
160 | + else if (code == 'b') | |
161 | + { | |
162 | + if (GET_CODE (addr) != PLUS) | |
163 | + fatal_insn ("bad address, not (reg+disp):", addr); | |
164 | + | |
165 | + avr_print_operand_address (file, XEXP (addr, 0)); | |
166 | + } | |
167 | else if (code == 'p' || code == 'r') | |
168 | { | |
169 | if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC) | |
170 | @@ -2392,7 +2420,7 @@ avr_simplify_comparison_p (enum machine_ | |
171 | int | |
172 | function_arg_regno_p(int r) | |
173 | { | |
174 | - return (r >= 8 && r <= 25); | |
175 | + return (AVR_TINY ? r >= 20 && r <= 25 : r >= 8 && r <= 25); | |
176 | } | |
177 | ||
178 | /* Initializing the variable cum for the state at the beginning | |
179 | @@ -2402,7 +2430,7 @@ void | |
180 | init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname, | |
181 | tree fndecl ATTRIBUTE_UNUSED) | |
182 | { | |
183 | - cum->nregs = 18; | |
184 | + cum->nregs = AVR_TINY ? 6 : 18; | |
185 | cum->regno = FIRST_CUM_REG; | |
186 | if (!libname && stdarg_p (fntype)) | |
187 | cum->nregs = 0; | |
188 | @@ -2900,6 +2928,25 @@ output_movhi (rtx insn, rtx xop[], int * | |
189 | return ""; | |
190 | } | |
191 | ||
192 | +/* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */ | |
193 | +static const char* | |
194 | +avr_out_movqi_r_mr_reg_disp_tiny (rtx insn, rtx op[], int *plen) | |
195 | +{ | |
196 | + rtx dest = op[0]; | |
197 | + rtx src = op[1]; | |
198 | + rtx x = XEXP (src, 0); | |
199 | + op[2] = XEXP(x, 0); | |
200 | + | |
201 | + avr_asm_len (TINY_ADIW (%A2, %B2, %o1) CR_TAB | |
202 | + "ld %0,%b1" , op, plen, -3); | |
203 | + | |
204 | + if (!reg_overlap_mentioned_p (dest, XEXP (x,0)) | |
205 | + && !reg_unused_after (insn, XEXP (x,0))) | |
206 | + avr_asm_len (TINY_SBIW (%A2, %B2, %o1), op, plen, 2); | |
207 | + | |
208 | + return ""; | |
209 | +} | |
210 | + | |
211 | static const char* | |
212 | out_movqi_r_mr (rtx insn, rtx op[], int *plen) | |
213 | { | |
214 | @@ -2913,13 +2960,18 @@ out_movqi_r_mr (rtx insn, rtx op[], int | |
215 | ? avr_asm_len ("in %0,%i1", op, plen, -1) | |
216 | : avr_asm_len ("lds %0,%m1", op, plen, -2); | |
217 | } | |
218 | - else if (GET_CODE (x) == PLUS | |
219 | + | |
220 | + | |
221 | + if (GET_CODE (x) == PLUS | |
222 | && REG_P (XEXP (x, 0)) | |
223 | && CONST_INT_P (XEXP (x, 1))) | |
224 | { | |
225 | /* memory access by reg+disp */ | |
226 | ||
227 | int disp = INTVAL (XEXP (x, 1)); | |
228 | + | |
229 | + if (AVR_TINY) | |
230 | + return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen); | |
231 | ||
232 | if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63) | |
233 | { | |
234 | @@ -2941,25 +2993,105 @@ out_movqi_r_mr (rtx insn, rtx op[], int | |
235 | { | |
236 | /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude | |
237 | it but I have this situation with extremal optimizing options. */ | |
238 | - | |
239 | - avr_asm_len ("adiw r26,%o1" CR_TAB | |
240 | - "ld %0,X", op, plen, -2); | |
241 | + | |
242 | + avr_asm_len ("adiw r26, %o1" CR_TAB | |
243 | + "ld %0,X", op, plen, -2); | |
244 | ||
245 | if (!reg_overlap_mentioned_p (dest, XEXP (x,0)) | |
246 | && !reg_unused_after (insn, XEXP (x,0))) | |
247 | { | |
248 | - avr_asm_len ("sbiw r26,%o1", op, plen, 1); | |
249 | + avr_asm_len ("sbiw r26, %o1", op, plen, 1); | |
250 | } | |
251 | ||
252 | return ""; | |
253 | } | |
254 | ||
255 | - return avr_asm_len ("ldd %0,%1", op, plen, -1); | |
256 | + return avr_asm_len ("ldd %0,%1", op, plen, -1); | |
257 | } | |
258 | ||
259 | return avr_asm_len ("ld %0,%1", op, plen, -1); | |
260 | } | |
261 | ||
262 | +/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */ | |
263 | +static const char* | |
264 | +avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen) | |
265 | +{ | |
266 | + rtx dest = op[0]; | |
267 | + rtx src = op[1]; | |
268 | + rtx base = XEXP (src, 0); | |
269 | + | |
270 | + int reg_dest = true_regnum (dest); | |
271 | + int reg_base = true_regnum (base); | |
272 | + | |
273 | + op[2] = base; | |
274 | + | |
275 | + if (reg_dest == reg_base) /* R = (R) */ | |
276 | + return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB | |
277 | + "ld %B0,%1" CR_TAB | |
278 | + "mov %A0,__tmp_reg__", op, plen, -3); | |
279 | + | |
280 | + return avr_asm_len ("ld %A0,%1" CR_TAB | |
281 | + TINY_ADIW (%A2, %B2, 1) CR_TAB | |
282 | + "ld %B0,%1" CR_TAB | |
283 | + TINY_SBIW (%A2, %B2, 1), op, plen, -6); | |
284 | + | |
285 | +} | |
286 | + | |
287 | +/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */ | |
288 | +static const char* | |
289 | +avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen) | |
290 | +{ | |
291 | + rtx dest = op[0]; | |
292 | + rtx src = op[1]; | |
293 | + rtx base = XEXP (src, 0); | |
294 | + | |
295 | + int reg_dest = true_regnum (dest); | |
296 | + int reg_base = true_regnum (XEXP (base, 0)); | |
297 | + op[2] = XEXP (base, 0); | |
298 | + | |
299 | + if (reg_base == reg_dest) | |
300 | + { | |
301 | + return avr_asm_len (TINY_ADIW (%A2, %B2, %o1) CR_TAB | |
302 | + "ld __tmp_reg__,%b1+" CR_TAB | |
303 | + "ld %B0,%b1" CR_TAB | |
304 | + "mov %A0,__tmp_reg__", op, plen, -5); | |
305 | + } | |
306 | + else | |
307 | + { | |
308 | + return avr_asm_len (TINY_ADIW (%A2, %B2, %o1) CR_TAB | |
309 | + "ld %A0,%b1+" CR_TAB | |
310 | + "ld %B0,%b1" CR_TAB | |
311 | + TINY_SBIW (%A2, %B2, %o1+1), op, plen, -6); | |
312 | + } | |
313 | +} | |
314 | + | |
315 | +/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */ | |
316 | +static const char* | |
317 | +avr_out_movhi_r_mr_pre_dec_tiny (rtx insn, rtx op[], int *plen) | |
318 | +{ | |
319 | + int mem_volatile_p = 0; | |
320 | + rtx dest = op[0]; | |
321 | + rtx src = op[1]; | |
322 | + rtx base = XEXP (src, 0); | |
323 | + op[2] = XEXP (base, 0); | |
324 | + | |
325 | + /* "volatile" forces reading low byte first, even if less efficient, | |
326 | + for correct operation with 16-bit I/O registers. */ | |
327 | + mem_volatile_p = MEM_VOLATILE_P (src); | |
328 | + | |
329 | + if (reg_overlap_mentioned_p (dest, XEXP (base, 0))) | |
330 | + fatal_insn ("incorrect insn:", insn); | |
331 | + | |
332 | + if (!mem_volatile_p) | |
333 | + return avr_asm_len ("ld %B0,%1" CR_TAB | |
334 | + "ld %A0,%1", op, plen, -2); | |
335 | + | |
336 | + return avr_asm_len (TINY_SBIW (%A2, %B2, 2) CR_TAB | |
337 | + "ld %A0,%p1+" CR_TAB | |
338 | + "ld %B0,%p1" CR_TAB | |
339 | + TINY_SBIW (%A2, %B2, 1), op, plen, -6); | |
340 | +} | |
341 | + | |
342 | static const char* | |
343 | out_movhi_r_mr (rtx insn, rtx op[], int *plen) | |
344 | { | |
345 | @@ -2974,20 +3106,27 @@ out_movhi_r_mr (rtx insn, rtx op[], int | |
346 | ||
347 | if (reg_base > 0) | |
348 | { | |
349 | + if (AVR_TINY) | |
350 | + return avr_out_movhi_r_mr_reg_no_disp_tiny (op, plen); | |
351 | + | |
352 | if (reg_dest == reg_base) /* R = (R) */ | |
353 | return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB | |
354 | "ld %B0,%1" CR_TAB | |
355 | "mov %A0,__tmp_reg__", op, plen, -3); | |
356 | ||
357 | if (reg_base != REG_X) | |
358 | + { | |
359 | return avr_asm_len ("ld %A0,%1" CR_TAB | |
360 | - "ldd %B0,%1+1", op, plen, -2); | |
361 | - | |
362 | + "ldd %B0,%1+1", op, plen, -2); | |
363 | + } | |
364 | + | |
365 | avr_asm_len ("ld %A0,X+" CR_TAB | |
366 | "ld %B0,X", op, plen, -2); | |
367 | ||
368 | if (!reg_unused_after (insn, base)) | |
369 | + { | |
370 | avr_asm_len ("sbiw r26,1", op, plen, 1); | |
371 | + } | |
372 | ||
373 | return ""; | |
374 | } | |
375 | @@ -2996,6 +3135,9 @@ out_movhi_r_mr (rtx insn, rtx op[], int | |
376 | int disp = INTVAL (XEXP (base, 1)); | |
377 | int reg_base = true_regnum (XEXP (base, 0)); | |
378 | ||
379 | + if (AVR_TINY) | |
380 | + return avr_out_movhi_r_mr_reg_disp_tiny (op, plen); | |
381 | + | |
382 | if (disp > MAX_LD_OFFSET (GET_MODE (src))) | |
383 | { | |
384 | if (REGNO (XEXP (base, 0)) != REG_Y) | |
385 | @@ -3007,7 +3149,7 @@ out_movhi_r_mr (rtx insn, rtx op[], int | |
386 | "ldd %B0,Y+63" CR_TAB | |
387 | "sbiw r28,%o1-62", op, plen, -4) | |
388 | ||
389 | - : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB | |
390 | + : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB | |
391 | "sbci r29,hi8(-%o1)" CR_TAB | |
392 | "ld %A0,Y" CR_TAB | |
393 | "ldd %B0,Y+1" CR_TAB | |
394 | @@ -3041,6 +3183,9 @@ out_movhi_r_mr (rtx insn, rtx op[], int | |
395 | } | |
396 | else if (GET_CODE (base) == PRE_DEC) /* (--R) */ | |
397 | { | |
398 | + if (AVR_TINY) | |
399 | + return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen); | |
400 | + | |
401 | if (reg_overlap_mentioned_p (dest, XEXP (base, 0))) | |
402 | fatal_insn ("incorrect insn:", insn); | |
403 | ||
404 | @@ -3081,6 +3226,101 @@ out_movhi_r_mr (rtx insn, rtx op[], int | |
405 | } | |
406 | ||
407 | static const char* | |
408 | +avr_out_movsi_r_mr_reg_no_disp_tiny (rtx insn, rtx op[], int *l) | |
409 | +{ | |
410 | + rtx dest = op[0]; | |
411 | + rtx src = op[1]; | |
412 | + rtx base = XEXP (src, 0); | |
413 | + int reg_dest = true_regnum (dest); | |
414 | + int reg_base = true_regnum (base); | |
415 | + op[2] = base; | |
416 | + | |
417 | + if (reg_dest == reg_base) | |
418 | + { | |
419 | + /* "ld r26,-X" is undefined */ | |
420 | + return *l=9, (TINY_ADIW (%A2, %B2, 3) CR_TAB | |
421 | + "ld %D0,%1" CR_TAB | |
422 | + "ld %C0,-%1" CR_TAB | |
423 | + "ld __tmp_reg__,-%1" CR_TAB | |
424 | + TINY_SBIW (%A2, %B2, 1) CR_TAB | |
425 | + "ld %A0,%1" CR_TAB | |
426 | + "mov %B0,__tmp_reg__"); | |
427 | + } | |
428 | + else if (reg_dest == reg_base - 2) | |
429 | + { | |
430 | + return *l=5, ("ld %A0,%1+" CR_TAB | |
431 | + "ld %B0,%1+" CR_TAB | |
432 | + "ld __tmp_reg__,%1+" CR_TAB | |
433 | + "ld %D0,%1" CR_TAB | |
434 | + "mov %C0,__tmp_reg__"); | |
435 | + } | |
436 | + else if (reg_unused_after (insn, base)) | |
437 | + { | |
438 | + return *l=4, ("ld %A0,%1+" CR_TAB | |
439 | + "ld %B0,%1+" CR_TAB | |
440 | + "ld %C0,%1+" CR_TAB | |
441 | + "ld %D0,%1"); | |
442 | + } | |
443 | + else | |
444 | + { | |
445 | + return *l=6, ("ld %A0,%1+" CR_TAB | |
446 | + "ld %B0,%1+" CR_TAB | |
447 | + "ld %C0,%1+" CR_TAB | |
448 | + "ld %D0,%1" CR_TAB | |
449 | + TINY_SBIW (%A2, %B2, 3)); | |
450 | + } | |
451 | +} | |
452 | + | |
453 | +static const char* | |
454 | +avr_out_movsi_r_mr_reg_disp_tiny (rtx insn, rtx op[], int *l) | |
455 | +{ | |
456 | + rtx dest = op[0]; | |
457 | + rtx src = op[1]; | |
458 | + rtx base = XEXP (src, 0); | |
459 | + int reg_dest = true_regnum (dest); | |
460 | + int reg_base = true_regnum (XEXP (base, 0)); | |
461 | + op[2] = XEXP (base, 0); | |
462 | + | |
463 | + if (reg_dest == reg_base) | |
464 | + { | |
465 | + /* "ld r26,-X" is undefined */ | |
466 | + return *l=9, (TINY_ADIW (%A2, %B2, %o1+3) CR_TAB | |
467 | + "ld %D0,%b1" CR_TAB | |
468 | + "ld %C0,-%b1" CR_TAB | |
469 | + "ld __tmp_reg__,-%b1" CR_TAB | |
470 | + TINY_SBIW (%A2, %B2, 1) CR_TAB | |
471 | + "ld %A0,%b1" CR_TAB | |
472 | + "mov %B0,__tmp_reg__"); | |
473 | + } | |
474 | + else if (reg_dest == reg_base - 2) | |
475 | + { | |
476 | + return *l=7, (TINY_ADIW (%A2, %B2, %o1) CR_TAB | |
477 | + "ld %A0,%b1+" CR_TAB | |
478 | + "ld %B0,%b1+" CR_TAB | |
479 | + "ld __tmp_reg__,%b1+" CR_TAB | |
480 | + "ld %D0,%b1" CR_TAB | |
481 | + "mov %C0,__tmp_reg__"); | |
482 | + } | |
483 | + else if (reg_unused_after (insn, XEXP (base, 0))) | |
484 | + { | |
485 | + return *l=6, (TINY_ADIW (%A2, %B2, %o1) CR_TAB | |
486 | + "ld %A0,%b1+" CR_TAB | |
487 | + "ld %B0,%b1+" CR_TAB | |
488 | + "ld %C0,%b1+" CR_TAB | |
489 | + "ld %D0,%b1"); | |
490 | + } | |
491 | + else | |
492 | + { | |
493 | + return *l=8, (TINY_ADIW (%A2, %B2, %o1) CR_TAB | |
494 | + "ld %A0,%b1+" CR_TAB | |
495 | + "ld %B0,%b1+" CR_TAB | |
496 | + "ld %C0,%b1+" CR_TAB | |
497 | + "ld %D0,%b1" CR_TAB | |
498 | + TINY_SBIW (%A2, %B2, %o1+3)); | |
499 | + } | |
500 | +} | |
501 | + | |
502 | +static const char* | |
503 | out_movsi_r_mr (rtx insn, rtx op[], int *l) | |
504 | { | |
505 | rtx dest = op[0]; | |
506 | @@ -3095,6 +3335,9 @@ out_movsi_r_mr (rtx insn, rtx op[], int | |
507 | ||
508 | if (reg_base > 0) | |
509 | { | |
510 | + if (AVR_TINY) | |
511 | + return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l); | |
512 | + | |
513 | if (reg_base == REG_X) /* (R26) */ | |
514 | { | |
515 | if (reg_dest == REG_X) | |
516 | @@ -3149,6 +3392,9 @@ out_movsi_r_mr (rtx insn, rtx op[], int | |
517 | { | |
518 | int disp = INTVAL (XEXP (base, 1)); | |
519 | ||
520 | + if (AVR_TINY) | |
521 | + return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l); | |
522 | + | |
523 | if (disp > MAX_LD_OFFSET (GET_MODE (src))) | |
524 | { | |
525 | if (REGNO (XEXP (base, 0)) != REG_Y) | |
526 | @@ -3242,6 +3488,113 @@ out_movsi_r_mr (rtx insn, rtx op[], int | |
527 | } | |
528 | ||
529 | static const char* | |
530 | +avr_out_movsi_mr_r_reg_no_disp_tiny (rtx insn, rtx op[], int *l) | |
531 | +{ | |
532 | + rtx dest = op[0]; | |
533 | + rtx src = op[1]; | |
534 | + rtx base = XEXP (dest, 0); | |
535 | + int reg_base = true_regnum (base); | |
536 | + int reg_src = true_regnum (src); | |
537 | + op[2] = base; | |
538 | + | |
539 | + if (reg_base == reg_src) | |
540 | + { | |
541 | + /* "ld r26,-X" is undefined */ | |
542 | + if (reg_unused_after (insn, base)) | |
543 | + { | |
544 | + return *l=7, ("mov __tmp_reg__, %B1" CR_TAB | |
545 | + "st %0,%A1" CR_TAB | |
546 | + TINY_ADIW (%A2, %B2, 1) CR_TAB | |
547 | + "st %0+,__tmp_reg__" CR_TAB | |
548 | + "st %0+,%C1" CR_TAB | |
549 | + "st %0+,%D1"); | |
550 | + } | |
551 | + else | |
552 | + { | |
553 | + return *l=9, ("mov __tmp_reg__, %B1" CR_TAB | |
554 | + "st %0,%A1" CR_TAB | |
555 | + TINY_ADIW (%A2, %B2, 1) CR_TAB | |
556 | + "st %0+,__tmp_reg__" CR_TAB | |
557 | + "st %0+,%C1" CR_TAB | |
558 | + "st %0+,%D1" CR_TAB | |
559 | + TINY_SBIW (%A2, %B2, 3)); | |
560 | + } | |
561 | + } | |
562 | + else if (reg_base == reg_src + 2) | |
563 | + { | |
564 | + if (reg_unused_after (insn, base)) | |
565 | + return *l=7, ("mov __zero_reg__,%C1" CR_TAB | |
566 | + "mov __tmp_reg__,%D1" CR_TAB | |
567 | + "st %0+,%A1" CR_TAB | |
568 | + "st %0+,%B1" CR_TAB | |
569 | + "st %0+,__zero_reg__" CR_TAB | |
570 | + "st %0,__tmp_reg__" CR_TAB | |
571 | + "clr __zero_reg__"); | |
572 | + else | |
573 | + return *l=9, ("mov __zero_reg__,%C1" CR_TAB | |
574 | + "mov __tmp_reg__,%D1" CR_TAB | |
575 | + "st %0+,%A1" CR_TAB | |
576 | + "st %0+,%B1" CR_TAB | |
577 | + "st %0+,__zero_reg__" CR_TAB | |
578 | + "st %0,__tmp_reg__" CR_TAB | |
579 | + "clr __zero_reg__" CR_TAB | |
580 | + TINY_SBIW (%A2, %B2, 3)); | |
581 | + } | |
582 | + | |
583 | + return *l=6, ("st %0+,%A1" CR_TAB | |
584 | + "st %0+,%B1" CR_TAB | |
585 | + "st %0+,%C1" CR_TAB | |
586 | + "st %0,%D1" CR_TAB | |
587 | + TINY_SBIW (%A2, %B2, 3)); | |
588 | +} | |
589 | + | |
590 | +static const char* | |
591 | +avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l) | |
592 | +{ | |
593 | + rtx dest = op[0]; | |
594 | + rtx src = op[1]; | |
595 | + rtx base = XEXP (dest, 0); | |
596 | + int reg_base = REGNO (XEXP (base, 0)); | |
597 | + int reg_src =true_regnum (src); | |
598 | + | |
599 | + op[2] = XEXP (base, 0); | |
600 | + | |
601 | + if (reg_base == reg_src) | |
602 | + { | |
603 | + *l = 11; | |
604 | + return ("mov __tmp_reg__,%A2" CR_TAB | |
605 | + "mov __zero_reg__,%B2" CR_TAB | |
606 | + TINY_ADIW (%A2, %B2, %o0) CR_TAB | |
607 | + "st %b0+,__tmp_reg__" CR_TAB | |
608 | + "st %b0+,__zero_reg__" CR_TAB | |
609 | + "st %b0+,%C2" CR_TAB | |
610 | + "st %b0,%D2" CR_TAB | |
611 | + "clr __zero_reg__" CR_TAB | |
612 | + TINY_SBIW (%A2, %B2, %o0+3)); | |
613 | + } | |
614 | + else if (reg_src == reg_base - 2) | |
615 | + { | |
616 | + *l = 11; | |
617 | + return ("mov __tmp_reg__,%C2" CR_TAB | |
618 | + "mov __zero_reg__,%D2" CR_TAB | |
619 | + TINY_ADIW (%A2, %B2, %o0) CR_TAB | |
620 | + "st %b0+,%A0" CR_TAB | |
621 | + "st %b0+,%B0" CR_TAB | |
622 | + "st %b0+,__tmp_reg__" CR_TAB | |
623 | + "st %b0,__zero_reg__" CR_TAB | |
624 | + "clr __zero_reg__" CR_TAB | |
625 | + TINY_SBIW (%A2, %B2, %o0+3)); | |
626 | + } | |
627 | + *l = 8; | |
628 | + return (TINY_ADIW (%A2, %B2, %o0) CR_TAB | |
629 | + "st %b0+,%A1" CR_TAB | |
630 | + "st %b0+,%B1" CR_TAB | |
631 | + "st %b0+,%C1" CR_TAB | |
632 | + "st %b0,%D1" CR_TAB | |
633 | + TINY_SBIW (%A2, %B2, %o0+3)); | |
634 | +} | |
635 | + | |
636 | +static const char* | |
637 | out_movsi_mr_r (rtx insn, rtx op[], int *l) | |
638 | { | |
639 | rtx dest = op[0]; | |
640 | @@ -3261,6 +3614,9 @@ out_movsi_mr_r (rtx insn, rtx op[], int | |
641 | "sts %m0+3,%D1"); | |
642 | if (reg_base > 0) /* (r) */ | |
643 | { | |
644 | + if (AVR_TINY) | |
645 | + return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l); | |
646 | + | |
647 | if (reg_base == REG_X) /* (R26) */ | |
648 | { | |
649 | if (reg_src == REG_X) | |
650 | @@ -3317,6 +3673,10 @@ out_movsi_mr_r (rtx insn, rtx op[], int | |
651 | else if (GET_CODE (base) == PLUS) /* (R + i) */ | |
652 | { | |
653 | int disp = INTVAL (XEXP (base, 1)); | |
654 | + | |
655 | + if (AVR_TINY) | |
656 | + return avr_out_movsi_mr_r_reg_disp_tiny (op, l); | |
657 | + | |
658 | reg_base = REGNO (XEXP (base, 0)); | |
659 | if (disp > MAX_LD_OFFSET (GET_MODE (dest))) | |
660 | { | |
661 | @@ -3476,6 +3836,75 @@ output_movsisf (rtx insn, rtx operands[] | |
662 | /* Handle loads of 24-bit types from memory to register. */ | |
663 | ||
664 | static const char* | |
665 | +avr_out_load_psi_reg_no_disp_tiny (rtx insn, rtx *op, int *plen) | |
666 | +{ | |
667 | + rtx dest = op[0]; | |
668 | + rtx src = op[1]; | |
669 | + rtx base = XEXP (src, 0); | |
670 | + int reg_dest = true_regnum (dest); | |
671 | + int reg_base = true_regnum (base); | |
672 | + op[2] = base; | |
673 | + | |
674 | + if (reg_base == reg_dest) | |
675 | + { | |
676 | + return avr_asm_len (TINY_ADIW (%A2, %B2, 2) CR_TAB | |
677 | + "ld %C0,%1" CR_TAB | |
678 | + "ld __tmp_reg__,-%1" CR_TAB | |
679 | + TINY_SBIW (%A2, %B2, 1) CR_TAB | |
680 | + "ld %A0,%1" CR_TAB | |
681 | + "mov %B0,__tmp_reg__", op, plen, -8); | |
682 | + } | |
683 | + else | |
684 | + { | |
685 | + return avr_asm_len ("ld %A0,%1+" CR_TAB | |
686 | + "ld %B0,%1+" CR_TAB | |
687 | + "ld %C0,%1", op, plen, -3); | |
688 | + | |
689 | + if (reg_dest != reg_base - 2 && | |
690 | + !reg_unused_after (insn, base)) | |
691 | + { | |
692 | + avr_asm_len (TINY_SBIW (%A2, %B2, 2), op, plen, 2); | |
693 | + } | |
694 | + return ""; | |
695 | + } | |
696 | +} | |
697 | + | |
698 | +static const char* | |
699 | +avr_out_load_psi_reg_disp_tiny (rtx insn, rtx *op, int *plen) | |
700 | +{ | |
701 | + rtx dest = op[0]; | |
702 | + rtx src = op[1]; | |
703 | + rtx base = XEXP (src, 0); | |
704 | + int reg_dest = true_regnum (dest); | |
705 | + int reg_base = true_regnum (base); | |
706 | + op[2] = XEXP (base, 0); | |
707 | + | |
708 | + reg_base = true_regnum (XEXP (base, 0)); | |
709 | + if (reg_base == reg_dest) | |
710 | + { | |
711 | + return avr_asm_len (TINY_ADIW (%A2, %B2, %o1+2) CR_TAB | |
712 | + "ld %C0,%b1" CR_TAB | |
713 | + "ld __tmp_reg__,-%b1" CR_TAB | |
714 | + TINY_SBIW (%A2, %B2, 1) CR_TAB | |
715 | + "ld %A0,%b1" CR_TAB | |
716 | + "mov %B0,__tmp_reg__", op, plen, -8); | |
717 | + } | |
718 | + else | |
719 | + { | |
720 | + avr_asm_len (TINY_ADIW (%A2, %B2, %o1) CR_TAB | |
721 | + "ld %A0,%b1+" CR_TAB | |
722 | + "ld %B0,%b1+" CR_TAB | |
723 | + "ld %C0,%b1", op, plen, -5); | |
724 | + | |
725 | + if (reg_dest != (reg_base - 2) | |
726 | + && !reg_unused_after (insn, XEXP (base, 0))) | |
727 | + avr_asm_len (TINY_SBIW (%A2, %B2, %o1+2), op, plen, 2); | |
728 | + | |
729 | + return ""; | |
730 | + } | |
731 | +} | |
732 | + | |
733 | +static const char* | |
734 | avr_out_load_psi (rtx insn, rtx *op, int *plen) | |
735 | { | |
736 | rtx dest = op[0]; | |
737 | @@ -3486,6 +3915,9 @@ avr_out_load_psi (rtx insn, rtx *op, int | |
738 | ||
739 | if (reg_base > 0) | |
740 | { | |
741 | + if (AVR_TINY) | |
742 | + return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen); | |
743 | + | |
744 | if (reg_base == REG_X) /* (R26) */ | |
745 | { | |
746 | if (reg_dest == REG_X) | |
747 | @@ -3527,6 +3959,9 @@ avr_out_load_psi (rtx insn, rtx *op, int | |
748 | else if (GET_CODE (base) == PLUS) /* (R + i) */ | |
749 | { | |
750 | int disp = INTVAL (XEXP (base, 1)); | |
751 | + | |
752 | + if (AVR_TINY) | |
753 | + return avr_out_load_psi_reg_disp_tiny (insn, op, plen); | |
754 | ||
755 | if (disp > MAX_LD_OFFSET (GET_MODE (src))) | |
756 | { | |
757 | @@ -3604,6 +4039,85 @@ avr_out_load_psi (rtx insn, rtx *op, int | |
758 | return ""; | |
759 | } | |
760 | ||
761 | + | |
762 | +static const char* | |
763 | +avr_out_store_psi_reg_no_disp_tiny (rtx insn, rtx *op, int *plen) | |
764 | +{ | |
765 | + rtx dest = op[0]; | |
766 | + rtx src = op[1]; | |
767 | + rtx base = XEXP (dest, 0); | |
768 | + int reg_base = true_regnum (base); | |
769 | + int reg_src = true_regnum (src); | |
770 | + op[2] = base; | |
771 | + | |
772 | + if (reg_base == reg_src) | |
773 | + { | |
774 | + avr_asm_len ("st %0,%A1" CR_TAB | |
775 | + "mov __tmp_reg__,%B1" CR_TAB | |
776 | + TINY_ADIW (%A2, %B2, 1) CR_TAB /* st X+, r27 is undefined */ | |
777 | + "st %0+,__tmp_reg__" CR_TAB | |
778 | + "st %0,%C1", op, plen, -6); | |
779 | + | |
780 | + } | |
781 | + else if (reg_src == reg_base - 2) | |
782 | + { | |
783 | + avr_asm_len ("st %0,%A1" CR_TAB | |
784 | + "mov __tmp_reg__,%C1" CR_TAB | |
785 | + TINY_ADIW (%A2, %B2, 1) CR_TAB | |
786 | + "st %0+,%B1" CR_TAB | |
787 | + "st %0,__tmp_reg__", op, plen, 6); | |
788 | + } | |
789 | + else | |
790 | + { | |
791 | + avr_asm_len ("st %0+,%A1" CR_TAB | |
792 | + "st %0+,%B1" CR_TAB | |
793 | + "st %0,%C1", op, plen, -3); | |
794 | + } | |
795 | + | |
796 | + if (!reg_unused_after (insn, base)) | |
797 | + avr_asm_len (TINY_SBIW (%A2, %B2, 2), op, plen, 2); | |
798 | + | |
799 | + return ""; | |
800 | +} | |
801 | + | |
802 | +static const char* | |
803 | +avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen) | |
804 | +{ | |
805 | + rtx dest = op[0]; | |
806 | + rtx src = op[1]; | |
807 | + rtx base = XEXP (dest, 0); | |
808 | + int reg_base = REGNO (XEXP (base, 0)); | |
809 | + int reg_src = true_regnum (src); | |
810 | + op[2] = XEXP (base, 0); | |
811 | + | |
812 | + if (reg_src == reg_base) | |
813 | + { | |
814 | + return avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB | |
815 | + "mov __zero_reg__,%B1" CR_TAB | |
816 | + TINY_ADIW (%A2, %B2, %o0) CR_TAB | |
817 | + "st %b0+,__tmp_reg__" CR_TAB | |
818 | + "st %b0+,__zero_reg__" CR_TAB | |
819 | + "st %b0,%C1" CR_TAB | |
820 | + "clr __zero_reg__" CR_TAB | |
821 | + TINY_SBIW (%A2, %B2, %o0+2), op, plen, -10); | |
822 | + } | |
823 | + else if (reg_src == reg_base - 2) | |
824 | + { | |
825 | + return avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB | |
826 | + TINY_ADIW (%A2, %B2, %o0) CR_TAB | |
827 | + "st %b0+,%A1" CR_TAB | |
828 | + "st %b0+,%B1" CR_TAB | |
829 | + "st %b0,__tmp_reg__" CR_TAB | |
830 | + TINY_SBIW (%A2, %B2, %o0+2), op, plen, -8); | |
831 | + } | |
832 | + | |
833 | + return avr_asm_len (TINY_ADIW (%A2, %B2, %o0) CR_TAB | |
834 | + "st %b0+,%A1" CR_TAB | |
835 | + "st %b0+,%B1" CR_TAB | |
836 | + "st %b0,%C1" CR_TAB | |
837 | + TINY_SBIW (%A2, %B2, %o0+2), op, plen, -7); | |
838 | +} | |
839 | + | |
840 | /* Handle store of 24-bit type from register or zero to memory. */ | |
841 | ||
842 | static const char* | |
843 | @@ -3621,6 +4135,9 @@ avr_out_store_psi (rtx insn, rtx *op, in | |
844 | ||
845 | if (reg_base > 0) /* (r) */ | |
846 | { | |
847 | + if (AVR_TINY) | |
848 | + return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen); | |
849 | + | |
850 | if (reg_base == REG_X) /* (R26) */ | |
851 | { | |
852 | gcc_assert (!reg_overlap_mentioned_p (base, src)); | |
853 | @@ -3642,6 +4159,10 @@ avr_out_store_psi (rtx insn, rtx *op, in | |
854 | else if (GET_CODE (base) == PLUS) /* (R + i) */ | |
855 | { | |
856 | int disp = INTVAL (XEXP (base, 1)); | |
857 | + | |
858 | + if (AVR_TINY) | |
859 | + return avr_out_store_psi_reg_disp_tiny (op, plen); | |
860 | + | |
861 | reg_base = REGNO (XEXP (base, 0)); | |
862 | ||
863 | if (disp > MAX_LD_OFFSET (GET_MODE (dest))) | |
864 | @@ -3758,6 +4279,31 @@ avr_out_movpsi (rtx insn, rtx *op, int * | |
865 | return ""; | |
866 | } | |
867 | ||
868 | +static const char* | |
869 | +avr_out_movqi_mr_r_reg_disp_tiny (rtx insn, rtx op[], int *plen) | |
870 | +{ | |
871 | + rtx dest = op[0]; | |
872 | + rtx src = op[1]; | |
873 | + rtx x = XEXP (dest, 0); | |
874 | + op[2] = XEXP (x, 0); | |
875 | + | |
876 | + if (reg_overlap_mentioned_p (src, XEXP (x, 0))) | |
877 | + { | |
878 | + avr_asm_len ("mov __tmp_reg__,%1" CR_TAB | |
879 | + TINY_ADIW (%A2, %B2, %o0) CR_TAB | |
880 | + "st %b0,__tmp_reg__", op, plen, -4); | |
881 | + } | |
882 | + else | |
883 | + { | |
884 | + avr_asm_len (TINY_ADIW (%A2, %B2, %o0) CR_TAB | |
885 | + "st %b0,%1" , op, plen, -3); | |
886 | + } | |
887 | + | |
888 | + if (!reg_unused_after (insn, XEXP (x,0))) | |
889 | + avr_asm_len (TINY_SBIW (%A2, %B2, %o0), op, plen, 2); | |
890 | + | |
891 | + return ""; | |
892 | +} | |
893 | ||
894 | static const char* | |
895 | out_movqi_mr_r (rtx insn, rtx op[], int *plen) | |
896 | @@ -3780,6 +4326,9 @@ out_movqi_mr_r (rtx insn, rtx op[], int | |
897 | ||
898 | int disp = INTVAL (XEXP (x, 1)); | |
899 | ||
900 | + if (AVR_TINY) | |
901 | + return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen); | |
902 | + | |
903 | if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63) | |
904 | { | |
905 | if (REGNO (XEXP (x, 0)) != REG_Y) | |
906 | @@ -3934,6 +4483,76 @@ avr_out_movhi_mr_r_xmega (rtx insn, rtx | |
907 | return ""; | |
908 | } | |
909 | ||
910 | +static const char* | |
911 | +avr_out_movhi_mr_r_reg_no_disp_tiny (rtx insn, rtx op[], int *plen) | |
912 | +{ | |
913 | + rtx dest = op[0]; | |
914 | + rtx src = op[1]; | |
915 | + rtx base = XEXP (dest, 0); | |
916 | + int reg_base = true_regnum (base); | |
917 | + int reg_src = true_regnum (src); | |
918 | + int mem_volatile_p = MEM_VOLATILE_P (dest); | |
919 | + op[2] = base; | |
920 | + | |
921 | + if (reg_base == reg_src) | |
922 | + { | |
923 | + return !mem_volatile_p && reg_unused_after (insn, src) | |
924 | + ? avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB | |
925 | + "st %0,%A1" CR_TAB | |
926 | + TINY_ADIW (%A2, %B2, 1) CR_TAB | |
927 | + "st %0,__tmp_reg__", op, plen, -5) | |
928 | + : avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB | |
929 | + TINY_ADIW (%A2, %B2, 1) CR_TAB | |
930 | + "st %0,__tmp_reg__" CR_TAB | |
931 | + TINY_SBIW (%A2, %B2, 1) CR_TAB | |
932 | + "st %0, %A1", op, plen, -7); | |
933 | + } | |
934 | + | |
935 | + return !mem_volatile_p && reg_unused_after (insn, base) | |
936 | + ? avr_asm_len ("st %0+,%A1" CR_TAB | |
937 | + "st %0,%B1", op, plen, -2) | |
938 | + : avr_asm_len (TINY_ADIW (%A2, %B2, 1) CR_TAB | |
939 | + "st %0,%B1" CR_TAB | |
940 | + "st -%0,%A1", op, plen, -4); | |
941 | +} | |
942 | + | |
943 | +static const char* | |
944 | +avr_out_movhi_mr_r_reg_disp_tiny (rtx op[], int *plen) | |
945 | +{ | |
946 | + rtx dest = op[0]; | |
947 | + rtx src = op[1]; | |
948 | + rtx base = XEXP (dest, 0); | |
949 | + int reg_base = REGNO (XEXP (base, 0)); | |
950 | + int reg_src = true_regnum (src); | |
951 | + op[2] = XEXP (base, 0); | |
952 | + | |
953 | + return reg_src == reg_base | |
954 | + ? avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB | |
955 | + "mov __zero_reg__,%B1" CR_TAB | |
956 | + TINY_ADIW (%A2, %B2, %o0+1) CR_TAB | |
957 | + "st %b0,__zero_reg__" CR_TAB | |
958 | + "st -%b0,__tmp_reg__" CR_TAB | |
959 | + "clr __zero_reg__" CR_TAB | |
960 | + TINY_SBIW (%A2, %B2, %o0), op, plen, -9) | |
961 | + | |
962 | + : avr_asm_len (TINY_ADIW (%A2, %B2, %o0+1) CR_TAB | |
963 | + "st %b0,%B1" CR_TAB | |
964 | + "st -%b0,%A1" CR_TAB | |
965 | + TINY_SBIW (%A2, %B2, %o0), op, plen, -6); | |
966 | +} | |
967 | + | |
968 | +static const char* | |
969 | +avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen) | |
970 | +{ | |
971 | + rtx dest = op[0]; | |
972 | + rtx base = XEXP (dest, 0); | |
973 | + op[2] = XEXP (base, 0); | |
974 | + | |
975 | + return avr_asm_len (TINY_ADIW (%A2, %B2, 1) CR_TAB | |
976 | + "st %p0,%B1" CR_TAB | |
977 | + "st -%p0,%A1" CR_TAB | |
978 | + TINY_ADIW (%A2, %B2, 2), op, plen, -6); | |
979 | +} | |
980 | ||
981 | static const char* | |
982 | out_movhi_mr_r (rtx insn, rtx op[], int *plen) | |
983 | @@ -3964,6 +4583,9 @@ out_movhi_mr_r (rtx insn, rtx op[], int | |
984 | ||
985 | if (reg_base > 0) | |
986 | { | |
987 | + if (AVR_TINY) | |
988 | + return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen); | |
989 | + | |
990 | if (reg_base != REG_X) | |
991 | return avr_asm_len ("std %0+1,%B1" CR_TAB | |
992 | "st %0,%A1", op, plen, -2); | |
993 | @@ -3992,6 +4614,10 @@ out_movhi_mr_r (rtx insn, rtx op[], int | |
994 | else if (GET_CODE (base) == PLUS) | |
995 | { | |
996 | int disp = INTVAL (XEXP (base, 1)); | |
997 | + | |
998 | + if (AVR_TINY) | |
999 | + return avr_out_movhi_mr_r_reg_disp_tiny (op, plen); | |
1000 | + | |
1001 | reg_base = REGNO (XEXP (base, 0)); | |
1002 | if (disp > MAX_LD_OFFSET (GET_MODE (dest))) | |
1003 | { | |
1004 | @@ -4040,6 +4666,8 @@ out_movhi_mr_r (rtx insn, rtx op[], int | |
1005 | if (!mem_volatile_p) | |
1006 | return avr_asm_len ("st %0,%A1" CR_TAB | |
1007 | "st %0,%B1", op, plen, -2); | |
1008 | + if (AVR_TINY) | |
1009 | + return avr_out_movhi_mr_r_post_inc_tiny (op, plen); | |
1010 | ||
1011 | return REGNO (XEXP (base, 0)) == REG_X | |
1012 | ? avr_asm_len ("adiw r26,1" CR_TAB | |
1013 | @@ -4212,7 +4840,11 @@ avr_out_compare (rtx insn, rtx *xop, int | |
1014 | && (val8 == 0 | |
1015 | || reg_unused_after (insn, xreg))) | |
1016 | { | |
1017 | - avr_asm_len ("sbiw %0,%1", xop, plen, 1); | |
1018 | + if (AVR_TINY) | |
1019 | + avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2); | |
1020 | + else | |
1021 | + avr_asm_len ("sbiw %0,%1", xop, plen, 1); | |
1022 | + | |
1023 | i++; | |
1024 | continue; | |
1025 | } | |
1026 | @@ -4222,7 +4854,9 @@ avr_out_compare (rtx insn, rtx *xop, int | |
1027 | && compare_eq_p (insn) | |
1028 | && reg_unused_after (insn, xreg)) | |
1029 | { | |
1030 | - return avr_asm_len ("adiw %0,%n1", xop, plen, 1); | |
1031 | + return AVR_TINY | |
1032 | + ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2) | |
1033 | + : avr_asm_len ("adiw %0,%n1", xop, plen, 1); | |
1034 | } | |
1035 | } | |
1036 | ||
1037 | @@ -7411,10 +8045,10 @@ avr_file_start (void) | |
1038 | fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset); | |
1039 | if (AVR_HAVE_RAMPD) | |
1040 | fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset); | |
1041 | - if (AVR_XMEGA) | |
1042 | + if (AVR_XMEGA || AVR_TINY) | |
1043 | fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset); | |
1044 | - fprintf (asm_out_file, "__tmp_reg__ = %d\n", TMP_REGNO); | |
1045 | - fprintf (asm_out_file, "__zero_reg__ = %d\n", ZERO_REGNO); | |
1046 | + fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO); | |
1047 | + fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO); | |
1048 | } | |
1049 | ||
1050 | ||
1051 | @@ -7461,6 +8095,17 @@ order_regs_for_local_alloc (void) | |
1052 | 0,1, | |
1053 | 32,33,34,35 | |
1054 | }; | |
1055 | + static const int tiny_order_0[] = { | |
1056 | + 24,25, | |
1057 | + 22,23, | |
1058 | + 30,31, | |
1059 | + 26,27, | |
1060 | + 28,29, | |
1061 | + 21,20,19,18, | |
1062 | + 16,17, | |
1063 | + 32,33,34,35, | |
1064 | + 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 | |
1065 | + }; | |
1066 | static const int order_1[] = { | |
1067 | 18,19, | |
1068 | 20,21, | |
1069 | @@ -7473,6 +8118,17 @@ order_regs_for_local_alloc (void) | |
1070 | 0,1, | |
1071 | 32,33,34,35 | |
1072 | }; | |
1073 | + static const int tiny_order_1[] = { | |
1074 | + 22,23, | |
1075 | + 24,25, | |
1076 | + 30,31, | |
1077 | + 26,27, | |
1078 | + 28,29, | |
1079 | + 21,20,19,18, | |
1080 | + 16,17, | |
1081 | + 32,33,34,35, | |
1082 | + 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 | |
1083 | + }; | |
1084 | static const int order_2[] = { | |
1085 | 25,24, | |
1086 | 23,22, | |
1087 | @@ -7487,9 +8143,14 @@ order_regs_for_local_alloc (void) | |
1088 | 32,33,34,35 | |
1089 | }; | |
1090 | ||
1091 | - const int *order = (TARGET_ORDER_1 ? order_1 : | |
1092 | - TARGET_ORDER_2 ? order_2 : | |
1093 | - order_0); | |
1094 | + /* | |
1095 | + Select specific register allocation order. Tiny Core (attiny4/5/9/10/20/40) | |
1096 | + devices has only 16 registers, so different allocation order should be used | |
1097 | + */ | |
1098 | + const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1) : | |
1099 | + TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_1 : order_2) : | |
1100 | + (AVR_TINY ? tiny_order_0 : order_0)); | |
1101 | + | |
1102 | for (i=0; i < ARRAY_SIZE (order_0); ++i) | |
1103 | reg_alloc_order[i] = order[i]; | |
1104 | } | |
1105 | @@ -9151,7 +9812,7 @@ output_reload_in_const (rtx *op, rtx clo | |
1106 | { | |
1107 | if (!clear_p) | |
1108 | avr_asm_len (ldreg_p ? "ldi %0,0" | |
1109 | - : ZERO_REGNO == REGNO (xdest[n]) ? "clr %0" | |
1110 | + : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0" | |
1111 | : "mov %0,__zero_reg__", | |
1112 | &xdest[n], len, 1); | |
1113 | continue; | |
1114 | @@ -9350,6 +10011,50 @@ avr_output_addr_vec_elt (FILE *stream, i | |
1115 | fprintf (stream, "\trjmp .L%d\n", value); | |
1116 | } | |
1117 | ||
1118 | +static void | |
1119 | +avr_conditional_register_usage(void) { | |
1120 | + | |
1121 | + if (AVR_TINY) { | |
1122 | + unsigned int i; | |
1123 | + | |
1124 | + const int tiny_reg_alloc_order[] = { | |
1125 | + 24,25, | |
1126 | + 22,23, | |
1127 | + 30,31, | |
1128 | + 26,27, | |
1129 | + 28,29, | |
1130 | + 21,20,19,18, | |
1131 | + 16,17, | |
1132 | + 32,33,34,35, | |
1133 | + 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 | |
1134 | + }; | |
1135 | + | |
1136 | + /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list | |
1137 | + - R0-R15 are not available in Tiny Core devices | |
1138 | + - R16 and R17 are fixed registers | |
1139 | + */ | |
1140 | + for (i = 0; i <= 17; i++) { | |
1141 | + fixed_regs[i] = 1; | |
1142 | + call_used_regs[i] = 1; | |
1143 | + } | |
1144 | + | |
1145 | + /* Set R18 to R21 as callee saved registers | |
1146 | + - R18, R19, R20 and R21 are the callee saved registers in Tiny Core devices | |
1147 | + */ | |
1148 | + for (i = 18; i <= LAST_CALLEE_SAVED_REG; i++) { | |
1149 | + call_used_regs[i] = 0; | |
1150 | + } | |
1151 | + | |
1152 | + /*update register allocation order for Tiny Core devices */ | |
1153 | + for (i=0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++) { | |
1154 | + reg_alloc_order[i] = tiny_reg_alloc_order[i]; | |
1155 | + } | |
1156 | + | |
1157 | + CLEAR_HARD_REG_SET(reg_class_contents[(int)ADDW_REGS]); | |
1158 | + CLEAR_HARD_REG_SET(reg_class_contents[(int)NO_LD_REGS]); | |
1159 | + } | |
1160 | +} | |
1161 | + | |
1162 | /* Returns true if SCRATCH are safe to be allocated as a scratch | |
1163 | registers (for a define_peephole2) in the current function. */ | |
1164 | ||
1165 | @@ -9495,13 +10200,20 @@ avr_asm_out_dtor (rtx symbol, int priori | |
1166 | static bool | |
1167 | avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) | |
1168 | { | |
1169 | - if (TYPE_MODE (type) == BLKmode) | |
1170 | - { | |
1171 | - HOST_WIDE_INT size = int_size_in_bytes (type); | |
1172 | - return (size == -1 || size > 8); | |
1173 | - } | |
1174 | + HOST_WIDE_INT size = int_size_in_bytes (type); | |
1175 | + HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8; | |
1176 | + | |
1177 | + /* In avr, there are 8 return registers. But, for Tiny Core | |
1178 | + (attiny4/5/9/10/20/40) devices, only 4 registers available. | |
1179 | + Return true if size is unknown or greater than the limit */ | |
1180 | + if ((size == -1) || (size > ret_size_limit)) | |
1181 | + { | |
1182 | + return true; | |
1183 | + } | |
1184 | else | |
1185 | + { | |
1186 | return false; | |
1187 | + } | |
1188 | } | |
1189 | ||
1190 | /* Worker function for CASE_VALUES_THRESHOLD. */ | |
1191 | @@ -10949,6 +11661,9 @@ avr_fold_builtin (tree fndecl, int n_arg | |
1192 | #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE | |
1193 | #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value | |
1194 | ||
1195 | +#undef TARGET_CONDITIONAL_REGISTER_USAGE | |
1196 | +#define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage | |
1197 | + | |
1198 | #undef TARGET_HARD_REGNO_SCRATCH_OK | |
1199 | #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok | |
1200 | #undef TARGET_CASE_VALUES_THRESHOLD | |
1201 | diff -Naurp gcc/config/avr/avr-c.c gcc/config/avr/avr-c.c | |
1202 | --- gcc/config/avr/avr-c.c 2012-09-05 17:49:47.000000000 +0530 | |
1203 | +++ gcc/config/avr/avr-c.c 2013-01-21 18:40:04.000000000 +0530 | |
1204 | @@ -113,6 +113,23 @@ avr_cpu_cpp_builtins (struct cpp_reader | |
1205 | } | |
1206 | if (AVR_XMEGA) | |
1207 | cpp_define (pfile, "__AVR_XMEGA__"); | |
1208 | + | |
1209 | + if (AVR_TINY) | |
1210 | + { | |
1211 | + cpp_define (pfile, "__AVR_TINY__"); | |
1212 | + | |
1213 | + /* Define macro "__AVR_TINY_PM_BASE_ADDRESS__" with mapped program memory | |
1214 | + start address. This macro shall be referred where mapped program memory | |
1215 | + is accessed. (Eg. copying data section (do_copy_data) contents to data | |
1216 | + memory region. | |
1217 | + NOTE: | |
1218 | + Program memory of AVR_TINY devices can not be accessed directly, it has | |
1219 | + been mapped to the data memory. For AVR_TINY devices (ATtiny4/ 5/ 9/ 10/ | |
1220 | + 20 and 40) mapped program memory starts at 0x4000. | |
1221 | + */ | |
1222 | + cpp_define (pfile, "__AVR_TINY_PM_BASE_ADDRESS__=0x4000"); | |
1223 | + } | |
1224 | + | |
1225 | if (avr_current_arch->have_eijmp_eicall) | |
1226 | { | |
1227 | cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__"); | |
1228 | diff -Naurp gcc/config/avr/avr-devices.c gcc/config/avr/avr-devices.c | |
1229 | --- gcc/config/avr/avr-devices.c 2012-08-06 20:04:27.000000000 +0530 | |
1230 | +++ gcc/config/avr/avr-devices.c 2013-01-21 18:40:04.000000000 +0530 | |
1231 | @@ -30,29 +30,30 @@ const struct base_arch_s | |
1232 | avr_arch_types[] = | |
1233 | { | |
1234 | /* unknown device specified */ | |
1235 | - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, NULL, "avr2" }, | |
1236 | + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, NULL, "avr2" }, | |
1237 | /* | |
1238 | - A M J LM E E E X R d S S O A | |
1239 | - S U M PO L L I M A a t F ff r | |
1240 | - M L P MV P P J E M t a R s c | |
1241 | - XW M M M G P a r e h | |
1242 | - X P A D t t ID */ | |
1243 | - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "1", "avr1" }, | |
1244 | - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "2", "avr2" }, | |
1245 | - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, "25", "avr25" }, | |
1246 | - { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "3", "avr3" }, | |
1247 | - { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0x0060, 32, "31", "avr31" }, | |
1248 | - { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, "35", "avr35" }, | |
1249 | - { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, "4", "avr4" }, | |
1250 | - { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, "5", "avr5" }, | |
1251 | - { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, "51", "avr51" }, | |
1252 | - { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0x0060, 32, "6", "avr6" }, | |
1253 | + A M J LM E E E X R T d S S O A | |
1254 | + S U M PO L L I M A I a t F ff r | |
1255 | + M L P MV P P J E M N t a R s c | |
1256 | + XW M M M G P Y a r e h | |
1257 | + X P A D t t ID */ | |
1258 | + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "1", "avr1" }, | |
1259 | + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "2", "avr2" }, | |
1260 | + { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "25", "avr25" }, | |
1261 | + { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "3", "avr3" }, | |
1262 | + { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, "31", "avr31" }, | |
1263 | + { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "35", "avr35" }, | |
1264 | + { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "4", "avr4" }, | |
1265 | + { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "5", "avr5" }, | |
1266 | + { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0x0060, 32, "51", "avr51" }, | |
1267 | + { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, "6", "avr6" }, | |
1268 | ||
1269 | - { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0x2000, 0, "102", "avrxmega2" }, | |
1270 | - { 0, 1, 1, 1, 1, 1, 0, 1, 0, 0x2000, 0, "104", "avrxmega4" }, | |
1271 | - { 0, 1, 1, 1, 1, 1, 0, 1, 1, 0x2000, 0, "105", "avrxmega5" }, | |
1272 | - { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000, 0, "106", "avrxmega6" }, | |
1273 | - { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0x2000, 0, "107", "avrxmega7" } | |
1274 | + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x0040, 0, "100", "avrtiny" }, | |
1275 | + { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0x2000, 0, "102", "avrxmega2" }, | |
1276 | + { 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0x2000, 0, "104", "avrxmega4" }, | |
1277 | + { 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0x2000, 0, "105", "avrxmega5" }, | |
1278 | + { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0x2000, 0, "106", "avrxmega6" }, | |
1279 | + { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000, 0, "107", "avrxmega7" } | |
1280 | }; | |
1281 | ||
1282 | const struct mcu_type_s avr_mcu_types[] = { | |
1283 | diff -Naurp gcc/config/avr/avr.h gcc/config/avr/avr.h | |
1284 | --- gcc/config/avr/avr.h 2013-01-21 18:26:07.000000000 +0530 | |
1285 | +++ gcc/config/avr/avr.h 2013-01-21 18:40:04.000000000 +0530 | |
1286 | @@ -52,6 +52,9 @@ struct base_arch_s | |
1287 | /* This core has the RAMPD special function register | |
1288 | and thus also the RAMPX, RAMPY and RAMPZ registers. */ | |
1289 | int have_rampd; | |
1290 | + | |
1291 | + /* This is a TINY core. */ | |
1292 | + int tiny_p; | |
1293 | ||
1294 | /* Default start of data section address for architecture. */ | |
1295 | int default_data_section_start; | |
1296 | @@ -83,6 +86,7 @@ enum avr_arch | |
1297 | ARCH_AVR5, | |
1298 | ARCH_AVR51, | |
1299 | ARCH_AVR6, | |
1300 | + ARCH_AVRTINY, | |
1301 | ARCH_AVRXMEGA2, | |
1302 | ARCH_AVRXMEGA4, | |
1303 | ARCH_AVRXMEGA5, | |
1304 | @@ -213,6 +217,7 @@ enum | |
1305 | #define AVR_3_BYTE_PC (AVR_HAVE_EIJMP_EICALL) | |
1306 | ||
1307 | #define AVR_XMEGA (avr_current_arch->xmega_p) | |
1308 | +#define AVR_TINY (avr_current_arch->tiny_p) | |
1309 | ||
1310 | #define BITS_BIG_ENDIAN 0 | |
1311 | #define BYTES_BIG_ENDIAN 0 | |
1312 | @@ -342,7 +347,6 @@ enum reg_class { | |
1313 | ALL_REGS, LIM_REG_CLASSES | |
1314 | }; | |
1315 | ||
1316 | - | |
1317 | #define N_REG_CLASSES (int)LIM_REG_CLASSES | |
1318 | ||
1319 | #define REG_CLASS_NAMES { \ | |
1320 | @@ -417,7 +421,7 @@ enum reg_class { | |
1321 | ||
1322 | #define ARG_POINTER_REGNUM 34 | |
1323 | ||
1324 | -#define STATIC_CHAIN_REGNUM 2 | |
1325 | +#define STATIC_CHAIN_REGNUM ((AVR_TINY) ? 18 :2) | |
1326 | ||
1327 | #define ELIMINABLE_REGS { \ | |
1328 | {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ | |
1329 | diff -Naurp gcc/config/avr/avr-mcus.def gcc/config/avr/avr-mcus.def | |
1330 | --- gcc/config/avr/avr-mcus.def 2012-09-10 16:16:27.000000000 +0530 | |
1331 | +++ gcc/config/avr/avr-mcus.def 2013-01-21 18:40:04.000000000 +0530 | |
1332 | @@ -231,6 +231,14 @@ AVR_MCU ("atxmega256d3", ARCH_AVRXME | |
1333 | AVR_MCU ("avrxmega7", ARCH_AVRXMEGA7, NULL, 0, 0, 0x2000, 3, "x128a1") | |
1334 | AVR_MCU ("atxmega128a1", ARCH_AVRXMEGA7, "__AVR_ATxmega128A1__", 0, 0, 0x2000, 3, "x128a1") | |
1335 | AVR_MCU ("atxmega128a1u", ARCH_AVRXMEGA7, "__AVR_ATxmega128A1U__", 0, 0, 0x2000, 3, "x128a1u") | |
1336 | +/* Tiny family */ | |
1337 | +AVR_MCU ("avrtiny", ARCH_AVRTINY, NULL, 0, 0, 0x0040, 1, "tn10") | |
1338 | +AVR_MCU ("attiny4", ARCH_AVRTINY, "__AVR_ATtiny4__", 0, 0, 0x0040, 1, "tn4") | |
1339 | +AVR_MCU ("attiny5", ARCH_AVRTINY, "__AVR_ATtiny5__", 0, 0, 0x0040, 1, "tn5") | |
1340 | +AVR_MCU ("attiny9", ARCH_AVRTINY, "__AVR_ATtiny9__", 0, 0, 0x0040, 1, "tn9") | |
1341 | +AVR_MCU ("attiny10", ARCH_AVRTINY, "__AVR_ATtiny10__", 0, 0, 0x0040, 1, "tn10") | |
1342 | +AVR_MCU ("attiny20", ARCH_AVRTINY, "__AVR_ATtiny20__", 0, 0, 0x0040, 1, "tn20") | |
1343 | +AVR_MCU ("attiny40", ARCH_AVRTINY, "__AVR_ATtiny40__", 0, 0, 0x0040, 1, "tn40") | |
1344 | /* Assembler only. */ | |
1345 | AVR_MCU ("avr1", ARCH_AVR1, NULL, 0, 0, 0x0060, 1, "s1200") | |
1346 | AVR_MCU ("at90s1200", ARCH_AVR1, "__AVR_AT90S1200__", 0, 0, 0x0060, 1, "s1200") | |
1347 | diff -Naurp gcc/config/avr/avr.md gcc/config/avr/avr.md | |
1348 | --- gcc/config/avr/avr.md 2012-03-22 20:36:57.000000000 +0530 | |
1349 | +++ gcc/config/avr/avr.md 2013-01-21 18:40:04.000000000 +0530 | |
1350 | @@ -59,6 +59,11 @@ | |
1351 | (ZERO_REGNO 1) ; zero register r1 | |
1352 | ]) | |
1353 | ||
1354 | +(define_constants | |
1355 | + [ (TMP_REGNO_TINY 16) ; r16 is temp register for TINY10 | |
1356 | + (ZERO_REGNO_TINY 17) ; r17 is zero register for TINY10 | |
1357 | + ]) | |
1358 | + | |
1359 | (define_c_enum "unspec" | |
1360 | [UNSPEC_STRLEN | |
1361 | UNSPEC_MOVMEM | |
1362 | @@ -158,9 +163,10 @@ | |
1363 | ;; lpm : ISA has no LPMX lpmx : ISA has LPMX | |
1364 | ;; elpm : ISA has ELPM but no ELPMX elpmx : ISA has ELPMX | |
1365 | ;; no_xmega: non-XMEGA core xmega : XMEGA core | |
1366 | +;; no_tiny: non-TINY core tiny : TINY core | |
1367 | ||
1368 | (define_attr "isa" | |
1369 | - "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega, | |
1370 | + "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega, no_tiny,tiny, | |
1371 | standard" | |
1372 | (const_string "standard")) | |
1373 | ||
1374 | @@ -212,9 +218,18 @@ | |
1375 | (match_test "AVR_XMEGA")) | |
1376 | (const_int 1) | |
1377 | ||
1378 | + (and (eq_attr "isa" "tiny") | |
1379 | + (match_test "AVR_TINY")) | |
1380 | + (const_int 1) | |
1381 | + | |
1382 | (and (eq_attr "isa" "no_xmega") | |
1383 | (match_test "!AVR_XMEGA")) | |
1384 | (const_int 1) | |
1385 | + | |
1386 | + (and (eq_attr "isa" "no_tiny") | |
1387 | + (match_test "!AVR_TINY")) | |
1388 | + (const_int 1) | |
1389 | + | |
1390 | ] (const_int 0))) | |
1391 | ||
1392 | ||
1393 | @@ -5413,18 +5428,18 @@ | |
1394 | (set_attr "cc" "clobber")]) | |
1395 | ||
1396 | (define_insn "delay_cycles_2" | |
1397 | - [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "n") | |
1398 | + [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "n,n") | |
1399 | (const_int 2)] | |
1400 | UNSPECV_DELAY_CYCLES) | |
1401 | (set (match_operand:BLK 1 "" "") | |
1402 | (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER)) | |
1403 | - (clobber (match_scratch:HI 2 "=&w"))] | |
1404 | + (clobber (match_scratch:HI 2 "=&w,&d"))] | |
1405 | "" | |
1406 | - "ldi %A2,lo8(%0) | |
1407 | - ldi %B2,hi8(%0) | |
1408 | - 1: sbiw %A2,1 | |
1409 | - brne 1b" | |
1410 | - [(set_attr "length" "4") | |
1411 | + "@ | |
1412 | + ldi %A2,lo8(%0)\;ldi %B2,hi8(%0)\;1: sbiw %A2,1\;brne 1b | |
1413 | + ldi %A2,lo8(%0)\;ldi %B2,hi8(%0)\;1: subi %A2,1\;sbci %B2,0\;brne 1b" | |
1414 | + [(set_attr "length" "4,5") | |
1415 | + (set_attr "isa" "no_tiny,tiny") | |
1416 | (set_attr "cc" "clobber")]) | |
1417 | ||
1418 | (define_insn "delay_cycles_3" | |
1419 | diff -Naurp gcc/config/avr/avr-tables.opt gcc/config/avr/avr-tables.opt | |
1420 | --- gcc/config/avr/avr-tables.opt 2012-09-20 12:53:55.000000000 +0530 | |
1421 | +++ gcc/config/avr/avr-tables.opt 2013-01-21 18:40:04.000000000 +0530 | |
1422 | @@ -579,20 +579,41 @@ EnumValue | |
1423 | Enum(avr_mcu) String(atxmega128a1u) Value(184) | |
1424 | ||
1425 | EnumValue | |
1426 | -Enum(avr_mcu) String(avr1) Value(185) | |
1427 | +Enum(avr_mcu) String(avrtiny) Value(185) | |
1428 | ||
1429 | EnumValue | |
1430 | -Enum(avr_mcu) String(at90s1200) Value(186) | |
1431 | +Enum(avr_mcu) String(attiny4) Value(186) | |
1432 | ||
1433 | EnumValue | |
1434 | -Enum(avr_mcu) String(attiny11) Value(187) | |
1435 | +Enum(avr_mcu) String(attiny5) Value(187) | |
1436 | ||
1437 | EnumValue | |
1438 | -Enum(avr_mcu) String(attiny12) Value(188) | |
1439 | +Enum(avr_mcu) String(attiny9) Value(188) | |
1440 | ||
1441 | EnumValue | |
1442 | -Enum(avr_mcu) String(attiny15) Value(189) | |
1443 | +Enum(avr_mcu) String(attiny10) Value(189) | |
1444 | ||
1445 | EnumValue | |
1446 | -Enum(avr_mcu) String(attiny28) Value(190) | |
1447 | +Enum(avr_mcu) String(attiny20) Value(190) | |
1448 | + | |
1449 | +EnumValue | |
1450 | +Enum(avr_mcu) String(attiny40) Value(191) | |
1451 | + | |
1452 | +EnumValue | |
1453 | +Enum(avr_mcu) String(avr1) Value(192) | |
1454 | + | |
1455 | +EnumValue | |
1456 | +Enum(avr_mcu) String(at90s1200) Value(193) | |
1457 | + | |
1458 | +EnumValue | |
1459 | +Enum(avr_mcu) String(attiny11) Value(194) | |
1460 | + | |
1461 | +EnumValue | |
1462 | +Enum(avr_mcu) String(attiny12) Value(195) | |
1463 | + | |
1464 | +EnumValue | |
1465 | +Enum(avr_mcu) String(attiny15) Value(196) | |
1466 | + | |
1467 | +EnumValue | |
1468 | +Enum(avr_mcu) String(attiny28) Value(197) | |
1469 | ||
1470 | diff -Naurp gcc/config/avr/t-multilib gcc/config/avr/t-multilib | |
1471 | --- gcc/config/avr/t-multilib 2012-09-20 12:53:55.000000000 +0530 | |
1472 | +++ gcc/config/avr/t-multilib 2013-01-21 18:40:04.000000000 +0530 | |
1473 | @@ -21,9 +21,9 @@ | |
1474 | # along with GCC; see the file COPYING3. If not see | |
1475 | # <http://www.gnu.org/licenses/>. | |
1476 | ||
1477 | -MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7 msp8 | |
1478 | +MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7/mmcu=avrtiny msp8 | |
1479 | ||
1480 | -MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack avr25/tiny-stack | |
1481 | +MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny tiny-stack avr25/tiny-stack | |
1482 | ||
1483 | MULTILIB_EXCEPTIONS = \ | |
1484 | mmcu=avr3/msp8 \ | |
1485 | @@ -37,7 +37,8 @@ MULTILIB_EXCEPTIONS = \ | |
1486 | mmcu=avrxmega4/msp8 \ | |
1487 | mmcu=avrxmega5/msp8 \ | |
1488 | mmcu=avrxmega6/msp8 \ | |
1489 | - mmcu=avrxmega7/msp8 | |
1490 | + mmcu=avrxmega7/msp8 \ | |
1491 | + mmcu=avrtiny/msp8 | |
1492 | ||
1493 | MULTILIB_MATCHES = \ | |
1494 | mmcu?avr2=mmcu?at90s2313 \ | |
1495 | @@ -210,4 +211,10 @@ MULTILIB_MATCHES = \ | |
1496 | mmcu?avrxmega6=mmcu?atxmega256a3bu \ | |
1497 | mmcu?avrxmega6=mmcu?atxmega256d3 \ | |
1498 | mmcu?avrxmega7=mmcu?atxmega128a1 \ | |
1499 | - mmcu?avrxmega7=mmcu?atxmega128a1u | |
1500 | + mmcu?avrxmega7=mmcu?atxmega128a1u \ | |
1501 | + mmcu?avrtiny=mmcu?attiny4 \ | |
1502 | + mmcu?avrtiny=mmcu?attiny5 \ | |
1503 | + mmcu?avrtiny=mmcu?attiny9 \ | |
1504 | + mmcu?avrtiny=mmcu?attiny10 \ | |
1505 | + mmcu?avrtiny=mmcu?attiny20 \ | |
1506 | + mmcu?avrtiny=mmcu?attiny40 | |
1507 | diff -Naurp libgcc/config/avr/lib1funcs.S libgcc/config/avr/lib1funcs.S | |
1508 | --- libgcc/config/avr/lib1funcs.S 2012-03-28 14:34:11.000000000 +0530 | |
1509 | +++ libgcc/config/avr/lib1funcs.S 2013-01-21 18:58:03.000000000 +0530 | |
1510 | @@ -22,8 +22,13 @@ a copy of the GCC Runtime Library Except | |
1511 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
1512 | <http://www.gnu.org/licenses/>. */ | |
1513 | ||
1514 | +#if defined (__AVR_TINY__) | |
1515 | +#define __zero_reg__ r17 | |
1516 | +#define __tmp_reg__ r16 | |
1517 | +#else | |
1518 | #define __zero_reg__ r1 | |
1519 | #define __tmp_reg__ r0 | |
1520 | +#endif | |
1521 | #define __SREG__ 0x3f | |
1522 | #if defined (__AVR_HAVE_SPH__) | |
1523 | #define __SP_H__ 0x3e | |
1524 | @@ -80,6 +85,15 @@ see the files COPYING3 and COPYING.RUNTI | |
1525 | #define XJMP rjmp | |
1526 | #endif | |
1527 | ||
1528 | +.macro wsubi r_arg1, i_arg2 | |
1529 | +#if defined (__AVR_TINY__) | |
1530 | + subi \r_arg1, lo8(\i_arg2) | |
1531 | + sbci \r_arg1+1, hi8(\i_arg2) | |
1532 | +#else | |
1533 | + sbiw \r_arg1, \i_arg2 | |
1534 | +#endif | |
1535 | +.endm | |
1536 | + | |
1537 | .macro DEFUN name | |
1538 | .global \name | |
1539 | .func \name | |
1540 | @@ -150,12 +164,12 @@ ENDF __umulqihi3 | |
1541 | Multiplication 16 x 16 without MUL | |
1542 | *******************************************************/ | |
1543 | #if defined (L_mulhi3) | |
1544 | -#define r_arg1L r24 /* multiplier Low */ | |
1545 | -#define r_arg1H r25 /* multiplier High */ | |
1546 | -#define r_arg2L r22 /* multiplicand Low */ | |
1547 | -#define r_arg2H r23 /* multiplicand High */ | |
1548 | +#define r_arg1L 24 /* multiplier Low */ | |
1549 | +#define r_arg1H 25 /* multiplier High */ | |
1550 | +#define r_arg2L 22 /* multiplicand Low */ | |
1551 | +#define r_arg2H 23 /* multiplicand High */ | |
1552 | #define r_resL __tmp_reg__ /* result Low */ | |
1553 | -#define r_resH r21 /* result High */ | |
1554 | +#define r_resH 21 /* result High */ | |
1555 | ||
1556 | DEFUN __mulhi3 | |
1557 | clr r_resH ; clear result | |
1558 | @@ -175,7 +189,7 @@ __mulhi3_skip1: | |
1559 | ||
1560 | lsr r_arg1H ; gets LSB of multiplier | |
1561 | ror r_arg1L | |
1562 | - sbiw r_arg1L,0 | |
1563 | + wsubi r_arg1L,0 | |
1564 | brne __mulhi3_loop ; exit if multiplier = 0 | |
1565 | __mulhi3_exit: | |
1566 | mov r_arg1H,r_resH ; result to return register | |
1567 | @@ -230,22 +244,34 @@ ENDF __umulhisi3 | |
1568 | /******************************************************* | |
1569 | Multiplication 32 x 32 without MUL | |
1570 | *******************************************************/ | |
1571 | -#define r_arg1L r22 /* multiplier Low */ | |
1572 | -#define r_arg1H r23 | |
1573 | -#define r_arg1HL r24 | |
1574 | -#define r_arg1HH r25 /* multiplier High */ | |
1575 | - | |
1576 | -#define r_arg2L r18 /* multiplicand Low */ | |
1577 | -#define r_arg2H r19 | |
1578 | -#define r_arg2HL r20 | |
1579 | -#define r_arg2HH r21 /* multiplicand High */ | |
1580 | +#define r_arg1L 22 /* multiplier Low */ | |
1581 | +#define r_arg1H 23 | |
1582 | +#define r_arg1HL 24 | |
1583 | +#define r_arg1HH 25 /* multiplier High */ | |
1584 | + | |
1585 | +#define r_arg2L 18 /* multiplicand Low */ | |
1586 | +#define r_arg2H 19 | |
1587 | +#define r_arg2HL 20 | |
1588 | +#define r_arg2HH 21 /* multiplicand High */ | |
1589 | ||
1590 | -#define r_resL r26 /* result Low */ | |
1591 | -#define r_resH r27 | |
1592 | -#define r_resHL r30 | |
1593 | -#define r_resHH r31 /* result High */ | |
1594 | +#define r_resL 26 /* result Low */ | |
1595 | +#define r_resH 27 | |
1596 | +#define r_resHL 30 | |
1597 | +#define r_resHH 31 /* result High */ | |
1598 | ||
1599 | DEFUN __mulsi3 | |
1600 | +#if defined (__AVR_TINY__) | |
1601 | + in r26,__SP_L__ ; safe to use X, as it is r_resL/H | |
1602 | + in r27,__SP_H__ | |
1603 | + subi r26, lo8(-3) ; Add 3 to point past return address | |
1604 | + sbci r27, hi8(-3) | |
1605 | + push r_arg2L ; save callee saved regs | |
1606 | + push r_arg2H | |
1607 | + ld r_arg2L,X+ ; load from caller stack | |
1608 | + ld r_arg2H,X+ | |
1609 | + ld r_arg2HL,X+ | |
1610 | + ld r_arg2HH,X | |
1611 | +#endif /* defined (__AVR_TINY__) */ | |
1612 | clr r_resHH ; clear result | |
1613 | clr r_resHL ; clear result | |
1614 | clr r_resH ; clear result | |
1615 | @@ -268,7 +294,7 @@ __mulsi3_skip1: | |
1616 | ror r_arg1H | |
1617 | ror r_arg1L | |
1618 | brne __mulsi3_loop | |
1619 | - sbiw r_arg1HL,0 | |
1620 | + wsubi r_arg1HL,0 | |
1621 | cpc r_arg1H,r_arg1L | |
1622 | brne __mulsi3_loop ; exit if multiplier = 0 | |
1623 | __mulsi3_exit: | |
1624 | @@ -276,6 +302,10 @@ __mulsi3_exit: | |
1625 | mov_l r_arg1HL,r_resHL | |
1626 | mov_h r_arg1H,r_resH | |
1627 | mov_l r_arg1L,r_resL | |
1628 | +#if defined (__AVR_TINY__) | |
1629 | + pop r_arg2H ; restore callee saved regs | |
1630 | + pop r_arg2L | |
1631 | +#endif /* defined (__AVR_TINY__) */ | |
1632 | ret | |
1633 | ENDF __mulsi3 | |
1634 | ||
1635 | @@ -514,9 +544,12 @@ ENDF __mulpsi3 | |
1636 | #undef C0 | |
1637 | ||
1638 | #else /* !HAVE_MUL */ | |
1639 | - | |
1640 | ;; C[0..2]: Expand Result | |
1641 | +#if defined (__AVR_TINY__) | |
1642 | +#define C0 16 | |
1643 | +#else | |
1644 | #define C0 0 | |
1645 | +#endif /* defined (__AVR_TINY__) */ | |
1646 | #define C1 C0+1 | |
1647 | #define C2 21 | |
1648 | ||
1649 | @@ -524,6 +557,17 @@ ENDF __mulpsi3 | |
1650 | ;; Clobbers: __tmp_reg__, R18, R19, R20, R21 | |
1651 | ||
1652 | DEFUN __mulpsi3 | |
1653 | +#if defined (__AVR_TINY__) | |
1654 | + in r26,__SP_L__ | |
1655 | + in r27,__SP_H__ | |
1656 | + subi r26, lo8(-3) ; Add 3 to point past return address | |
1657 | + sbci r27, hi8(-3) | |
1658 | + push B0 ; save callee saved regs | |
1659 | + push B1 | |
1660 | + ld B0,X+ ; load from caller stack | |
1661 | + ld B1,X+ | |
1662 | + ld B2,X+ | |
1663 | +#endif /* defined (__AVR_TINY__) */ | |
1664 | ||
1665 | ;; C[] = 0 | |
1666 | clr __tmp_reg__ | |
1667 | @@ -550,6 +594,10 @@ DEFUN __mulpsi3 | |
1668 | mov A2, C2 | |
1669 | ||
1670 | clr __zero_reg__ | |
1671 | +#if defined (__AVR_TINY__) | |
1672 | + pop B1 | |
1673 | + pop B0 | |
1674 | +#endif /* (__AVR_TINY__) */ | |
1675 | ret | |
1676 | ENDF __mulpsi3 | |
1677 | ||
1678 | @@ -618,6 +666,7 @@ ENDF __mulsqipsi3 | |
1679 | Multiplication 64 x 64 | |
1680 | *******************************************************/ | |
1681 | ||
1682 | +#if !defined (__AVR_TINY__) | |
1683 | #if defined (L_muldi3) | |
1684 | ||
1685 | ;; A[] = A[] * B[] | |
1686 | @@ -855,6 +904,7 @@ ENDF __muldi3 | |
1687 | #undef A0 | |
1688 | ||
1689 | #endif /* L_muldi3 */ | |
1690 | +#endif /* !defined (__AVR_TINY__) */ | |
1691 | ||
1692 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1693 | ||
1694 | @@ -1027,7 +1077,7 @@ ENDF __divmodhi4 | |
1695 | #define r_cnt 21 | |
1696 | ||
1697 | #if defined (L_udivmodpsi4) | |
1698 | -;; R24:R22 = R24:R22 udiv R20:R18 | |
1699 | +;; R24:R22 = R24:R24 udiv R20:R18 | |
1700 | ;; R20:R18 = R24:R22 umod R20:R18 | |
1701 | ;; Clobbers: R21, R25, R26 | |
1702 | ||
1703 | @@ -1248,6 +1298,10 @@ ENDF __divmodsi4 | |
1704 | #endif /* defined (L_divmodsi4) */ | |
1705 | ||
1706 | ||
1707 | +/* *di routines use registers below R19 and won't work with tiny arch | |
1708 | + right now. */ | |
1709 | + | |
1710 | +#if !defined (__AVR_TINY__) | |
1711 | /******************************************************* | |
1712 | Division 64 / 64 | |
1713 | Modulo 64 % 64 | |
1714 | @@ -1665,12 +1719,15 @@ ENDF __negdi2 | |
1715 | #undef A1 | |
1716 | #undef A0 | |
1717 | ||
1718 | +#endif /* !defined (__AVR_TINY__) */ | |
1719 | + | |
1720 | \f | |
1721 | .section .text.libgcc.prologue, "ax", @progbits | |
1722 | ||
1723 | /********************************** | |
1724 | * This is a prologue subroutine | |
1725 | **********************************/ | |
1726 | +#if !defined (__AVR_TINY__) | |
1727 | #if defined (L_prologue) | |
1728 | ||
1729 | ;; This function does not clobber T-flag; 64-bit division relies on it | |
1730 | @@ -1776,6 +1833,7 @@ DEFUN __epilogue_restores__ | |
1731 | ret | |
1732 | ENDF __epilogue_restores__ | |
1733 | #endif /* defined (L_epilogue) */ | |
1734 | +#endif /* !defined (__AVR_TINY__) */ | |
1735 | ||
1736 | #ifdef L_exit | |
1737 | .section .fini9,"ax",@progbits | |
1738 | @@ -1820,8 +1878,13 @@ DEFUN __tablejump__ | |
1739 | #else | |
1740 | ijmp | |
1741 | #endif | |
1742 | - | |
1743 | -#else /* !HAVE_LPMX */ | |
1744 | +#elif defined (__AVR_TINY__) | |
1745 | + wsubi 30, -(__AVR_TINY_PM_BASE_ADDRESS__) ; Add PM offset to Z | |
1746 | + ld __tmp_reg__, Z+ | |
1747 | + ld r31, Z ; Use ld instead of lpm to load Z | |
1748 | + mov r30, __tmp_reg__ | |
1749 | + ijmp | |
1750 | +#else /* !HAVE_LPMX && !AVR_TINY */ | |
1751 | lpm | |
1752 | adiw r30, 1 | |
1753 | push r0 | |
1754 | @@ -1836,6 +1899,26 @@ DEFUN __tablejump__ | |
1755 | ENDF __tablejump__ | |
1756 | #endif /* defined (L_tablejump) */ | |
1757 | ||
1758 | +#if defined(__AVR_TINY__) | |
1759 | +#ifdef L_copy_data | |
1760 | + .section .init4,"ax",@progbits | |
1761 | + .global __do_copy_data | |
1762 | +__do_copy_data: | |
1763 | + ldi r18, hi8(__data_end) | |
1764 | + ldi r26, lo8(__data_start) | |
1765 | + ldi r27, hi8(__data_start) | |
1766 | + ldi r30, lo8(__data_load_start + __AVR_TINY_PM_BASE_ADDRESS__) | |
1767 | + ldi r31, hi8(__data_load_start + __AVR_TINY_PM_BASE_ADDRESS__) | |
1768 | + rjmp .L__do_copy_data_start | |
1769 | +.L__do_copy_data_loop: | |
1770 | + ld r19, z+ | |
1771 | + st X+, r19 | |
1772 | +.L__do_copy_data_start: | |
1773 | + cpi r26, lo8(__data_end) | |
1774 | + cpc r27, r18 | |
1775 | + brne .L__do_copy_data_loop | |
1776 | +#endif | |
1777 | +#else | |
1778 | #ifdef L_copy_data | |
1779 | .section .init4,"ax",@progbits | |
1780 | DEFUN __do_copy_data | |
1781 | @@ -1901,13 +1984,14 @@ DEFUN __do_copy_data | |
1782 | #endif /* ELPM && RAMPD */ | |
1783 | ENDF __do_copy_data | |
1784 | #endif /* L_copy_data */ | |
1785 | +#endif /* !defined (__AVR_TINY__) */ | |
1786 | ||
1787 | /* __do_clear_bss is only necessary if there is anything in .bss section. */ | |
1788 | ||
1789 | #ifdef L_clear_bss | |
1790 | .section .init4,"ax",@progbits | |
1791 | DEFUN __do_clear_bss | |
1792 | - ldi r17, hi8(__bss_end) | |
1793 | + ldi r18, hi8(__bss_end) | |
1794 | ldi r26, lo8(__bss_start) | |
1795 | ldi r27, hi8(__bss_start) | |
1796 | rjmp .do_clear_bss_start | |
1797 | @@ -1915,7 +1999,7 @@ DEFUN __do_clear_bss | |
1798 | st X+, __zero_reg__ | |
1799 | .do_clear_bss_start: | |
1800 | cpi r26, lo8(__bss_end) | |
1801 | - cpc r27, r17 | |
1802 | + cpc r27, r18 | |
1803 | brne .do_clear_bss_loop | |
1804 | ENDF __do_clear_bss | |
1805 | #endif /* L_clear_bss */ | |
1806 | @@ -1951,7 +2035,7 @@ DEFUN __do_global_ctors | |
1807 | ldi r29, hi8(__ctors_end) | |
1808 | rjmp .L__do_global_ctors_start | |
1809 | .L__do_global_ctors_loop: | |
1810 | - sbiw r28, 2 | |
1811 | + wsubi r28, 2 | |
1812 | mov_h r31, r29 | |
1813 | mov_l r30, r28 | |
1814 | XCALL __tablejump__ | |
1815 | @@ -1994,7 +2078,11 @@ DEFUN __do_global_dtors | |
1816 | mov_h r31, r29 | |
1817 | mov_l r30, r28 | |
1818 | XCALL __tablejump__ | |
1819 | - adiw r28, 2 | |
1820 | +#if defined (__AVR_TINY__) | |
1821 | + wsubi r28, -2 | |
1822 | +#else | |
1823 | + adiw r28, 2 | |
1824 | +#endif | |
1825 | .L__do_global_dtors_start: | |
1826 | cpi r28, lo8(__dtors_end) | |
1827 | cpc r29, r17 | |
1828 | @@ -2005,6 +2093,7 @@ ENDF __do_global_dtors | |
1829 | ||
1830 | .section .text.libgcc, "ax", @progbits | |
1831 | ||
1832 | +#if !defined (__AVR_TINY__) | |
1833 | #ifdef L_tablejump_elpm | |
1834 | DEFUN __tablejump_elpm__ | |
1835 | #if defined (__AVR_HAVE_ELPMX__) | |
1836 | @@ -2035,7 +2124,9 @@ DEFUN __tablejump_elpm__ | |
1837 | #endif | |
1838 | ENDF __tablejump_elpm__ | |
1839 | #endif /* defined (L_tablejump_elpm) */ | |
1840 | +#endif /* !defined (__AVR_TINY__) */ | |
1841 | ||
1842 | +#if !defined (__AVR_TINY__) | |
1843 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1844 | ;; Loading n bytes from Flash; n = 3,4 | |
1845 | ;; R22... = Flash[Z] | |
1846 | @@ -2081,7 +2172,9 @@ ENDF __load_4 | |
1847 | #endif /* L_load_4 */ | |
1848 | ||
1849 | #endif /* L_load_3 || L_load_3 */ | |
1850 | +#endif /* !defined (__AVR_TINY__) */ | |
1851 | ||
1852 | +#if !defined (__AVR_TINY__) | |
1853 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1854 | ;; Loading n bytes from Flash or RAM; n = 1,2,3,4 | |
1855 | ;; R22... = Flash[R21:Z] or RAM[Z] depending on R21.7 | |
1856 | @@ -2207,7 +2300,9 @@ ENDF __xload_4 | |
1857 | #endif /* L_xload_4 */ | |
1858 | ||
1859 | #endif /* L_xload_{1|2|3|4} */ | |
1860 | +#endif /* if !defined (__AVR_TINY__) */ | |
1861 | ||
1862 | +#if !defined (__AVR_TINY__) | |
1863 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1864 | ;; memcopy from Address Space __pgmx to RAM | |
1865 | ;; R23:Z = Source Address | |
1866 | @@ -2279,6 +2374,7 @@ ENDF __movmemx_hi | |
1867 | #undef LOOP | |
1868 | ||
1869 | #endif /* L_movmemx */ | |
1870 | +#endif /* !defined (__AVR_TINY__) */ | |
1871 | ||
1872 | \f | |
1873 | .section .text.libgcc.builtins, "ax", @progbits | |
1874 | diff -Naurp libgcc/config/avr/t-avr libgcc/config/avr/t-avr | |
1875 | --- libgcc/config/avr/t-avr 2012-01-10 15:12:10.000000000 +0530 | |
1876 | +++ libgcc/config/avr/t-avr 2013-01-21 18:40:04.000000000 +0530 | |
1877 | @@ -1,13 +1,9 @@ | |
1878 | LIB1ASMSRC = avr/lib1funcs.S | |
1879 | + | |
1880 | LIB1ASMFUNCS = \ | |
1881 | _mulqi3 \ | |
1882 | _mulhi3 \ | |
1883 | - _mulpsi3 _mulsqipsi3 \ | |
1884 | - _mulhisi3 \ | |
1885 | - _umulhisi3 \ | |
1886 | - _usmulhisi3 \ | |
1887 | - _muluhisi3 \ | |
1888 | - _mulshisi3 \ | |
1889 | + _mulpsi3 \ | |
1890 | _mulsi3 \ | |
1891 | _udivmodqi4 \ | |
1892 | _divmodqi4 \ | |
1893 | @@ -16,19 +12,9 @@ LIB1ASMFUNCS = \ | |
1894 | _divmodpsi4 _udivmodpsi4 \ | |
1895 | _udivmodsi4 \ | |
1896 | _divmodsi4 \ | |
1897 | - _divdi3 _udivdi3 \ | |
1898 | - _muldi3 \ | |
1899 | - _udivmod64 \ | |
1900 | - _negdi2 \ | |
1901 | - _prologue \ | |
1902 | - _epilogue \ | |
1903 | _exit \ | |
1904 | _cleanup \ | |
1905 | _tablejump \ | |
1906 | - _tablejump_elpm \ | |
1907 | - _load_3 _load_4 \ | |
1908 | - _xload_1 _xload_2 _xload_3 _xload_4 \ | |
1909 | - _movmemx \ | |
1910 | _copy_data \ | |
1911 | _clear_bss \ | |
1912 | _ctors \ | |
1913 | @@ -38,22 +24,52 @@ LIB1ASMFUNCS = \ | |
1914 | _loop_ffsqi2 \ | |
1915 | _ctzsi2 \ | |
1916 | _ctzhi2 \ | |
1917 | - _clzdi2 \ | |
1918 | _clzsi2 \ | |
1919 | _clzhi2 \ | |
1920 | - _paritydi2 \ | |
1921 | _paritysi2 \ | |
1922 | _parityhi2 \ | |
1923 | _popcounthi2 \ | |
1924 | _popcountsi2 \ | |
1925 | - _popcountdi2 \ | |
1926 | _popcountqi2 \ | |
1927 | _bswapsi2 \ | |
1928 | + _fmul _fmuls _fmulsu | |
1929 | + | |
1930 | +# The below functions either use registers that are not present | |
1931 | +# in tiny core, or use a different register conventions (don't save | |
1932 | +# callee saved regs, for example) | |
1933 | +# _mulhisi3 and variations - clobber R18, R19 | |
1934 | +# All *di funcs - use regs < R16 or expect args in regs < R20 | |
1935 | +# _prologue and _epilogue save registers < R16 | |
1936 | +# _tablejump/_tablejump_elmp - expect lpm and elpm support | |
1937 | +# _load ad _xload variations - expect lpm and elpm support | |
1938 | +# _movmemx - expects elpm/lpm | |
1939 | + | |
1940 | +ifneq ($(MULTIFLAGS),-mmcu=avrtiny) | |
1941 | +LIB1ASMFUNCS += \ | |
1942 | + _mulsqipsi3 \ | |
1943 | + _mulhisi3 \ | |
1944 | + _umulhisi3 \ | |
1945 | + _usmulhisi3 \ | |
1946 | + _muluhisi3 \ | |
1947 | + _mulshisi3 \ | |
1948 | + _divdi3 _udivdi3 \ | |
1949 | + _muldi3 \ | |
1950 | + _udivmod64 \ | |
1951 | + _negdi2 \ | |
1952 | + _prologue \ | |
1953 | + _epilogue \ | |
1954 | + _tablejump_elpm \ | |
1955 | + _load_3 _load_4 \ | |
1956 | + _xload_1 _xload_2 _xload_3 _xload_4 \ | |
1957 | + _movmemx \ | |
1958 | + _clzdi2 \ | |
1959 | + _paritydi2 \ | |
1960 | + _popcountdi2 \ | |
1961 | _bswapdi2 \ | |
1962 | _ashldi3 _ashrdi3 _lshrdi3 _rotldi3 \ | |
1963 | _adddi3 _adddi3_s8 _subdi3 \ | |
1964 | - _cmpdi2 _cmpdi2_s8 \ | |
1965 | - _fmul _fmuls _fmulsu | |
1966 | + _cmpdi2 _cmpdi2_s8 | |
1967 | +endif | |
1968 | ||
1969 | LIB2FUNCS_EXCLUDE = \ | |
1970 | _moddi3 _umoddi3 \ |