]> git.pld-linux.org Git - packages/crossavr-gcc.git/blame - 301-gcc-tiny-support.patch
- cleanup, updated BRs, stub texinfo build (not packaged and would require patch...
[packages/crossavr-gcc.git] / 301-gcc-tiny-support.patch
CommitLineData
64c2fd3a
JR
1diff -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
1201diff -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__");
1228diff -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[] = {
1283diff -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}, \
1329diff -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")
1347diff -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"
1419diff -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
1470diff -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
1507diff -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
1874diff -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 \
This page took 0.417987 seconds and 4 git commands to generate.